2015년 1월 11일 일요일

[node mysql] node-mysql -> connection pool

  • connection은 연결 때 마다 connection을 새로 만들고 사용하면 연결을 끊는다. 1회성의 성격을 가진다는 뜻이다. 때문에 연결시마다 connection을 새로 생성하는데에 있어 낭비되는 자원이 생긴다.
  • pool은 connection들을 미리 만들어서 관리를 해주기 때문에 이러한 문제를 해결할 수 있다. 
  • connection pooling 기법은 미리 설정해 놓은 크기의 connection들을 준비하여 요청을 받으면 자원을 빌려주고 돌려받는다. pool은 그 connection의 연결을 끊지 않고 요청을 다시 기다리기 시작한다.
    • 즉 connection들을 관리하며 재사용을 한다.
  • 정해진 pool의 크기내의 연결은 원활한 연결을 지원하며, 넘어서는 연결 요청이 들어오면 이후의 요청들은 connection자원들이 생길때까지 대기를 한다.
    • pool이 아닌 보통의 connection에서는 많은 크기의 요청도 다 받아들이지만 느려지는 등의 부하를 준다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var mysql = require('mysql');
var pool  = mysql.createPool({
  connectionLimit : 10,
  host     : 'localhost',
  user     : 'root',
  password : '1234',
  database : 'node'
});

pool.on('connection', function (connection) {
  console.log('SET SESSION auto_increment_increment=1')
});

pool.on('enqueue', function () {
  console.log('Waiting for available connection slot');
});

for(var i = 1;i<=15;i++){
 console.log(i);
 var pool_con =
  pool.getConnection(function(err, connection) {
    // Use the connection
    connection.query( 'SELECT 1+1 AS solution', function(err, rows) {
      // And done with the connection.
      connection.release();

      // Don't use the connection here, it has been returned to the pool.
    });
  });
}


  • pooling의 예제 입니다. 
  • 3번 Line에서 connectionLimit는 pool의 크기입니다.
  • 10번라인은 pool내의 connection의 자원이 생길때 이벤트처리입니다.
  • 14번라인은 pool의 크기를 넘어서는 요청을 받아 대기열에 들어갈경우 발생하는 이벤트 처리입니다.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
0
1
2
3
4
5
6
7
8
9
10
Waiting for available connection slot
11
Waiting for available connection slot
12
Waiting for available connection slot
13
Waiting for available connection slot
14
Waiting for available connection slot
15
Waiting for available connection slot
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1
SET SESSION auto_increment_increment=1

  • 이 나옴을 볼수 있습니다.
  • pool의 크기가 10개인 만큼 10개까지는 처리가 잘되다가 이후부터는 enqueue이벤트가 발생, 즉 대기열에 들어감을 알수 있습니다.
  • 이후 release가 발생된다면 자원이 생겨 다음 요청을 처리하고 다시 다음 요청은 대기열에 들어가는 것이 계속 반복됩니다.
  • 이후 모든 요청이 처리되면 잉여 connection들이 생기면서 connection이벤트가 발생합니다. 모든 처리가 다 되는 시점에는 pool의 크기인 10번이 발생합니다.

2015년 1월 5일 월요일

[node mysql] node-mysql 예제


  • Express-ejs를 이용한 웹 서버에서 DB에 저장하는 것을 하기전에 mysql모듈에서 제공하는 기능들을 하나하나 알아가 보려고 합니다.
  • 또한 DB에 대한 아주 기초적인 쿼리문이나 지식이 필요합니다.

Mysql 모듈을 설치하기전에..

  • 당연 필요한것은 mysql입니다. mysql은 무료로 제공되고 있는 DataBase로서 가장 사랑받고 있습니다.
  • http://dev.mysql.com/downloads/mysql/에서 다운, 설치를 할수 있습니다.

Mysql 테이블 생성하기

  • node라는 스키마(데이터베이스)를 새로 만들어 줍니다.

1
2
3
create database node;

use node;

  • 저의 이전 회원가입 페이지에 맞는 테이블을 기준으로 테스트를 하겠습니다.

1
2
3
4
5
6
7
8
9
create table member(
 m_id varchar(20) primary key,
    m_pass varchar(200) not null,
    m_name varchar(20) not null,
    m_tel varchar(13) not null,
    m_date date not null,
    m_gender char(1) not null,
    m_email varchar(100) not null
);

  • 회원가입에 맞는 간단한 DB가 완성되었습니다. 이제 Node를 이용하여 테스트 해봅시다.

Mysql 모듈 설치하기

  • 우선 mysql 프로젝트 파일을 만들어 줍니다.
  • mysql이라는 모듈을 이용하여 mysql과 연결을 해보려고 합니다.
  • 설치 명령어는 npm install mysql 입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
C:\>mkdir mysql_tutorial

C:\>cd mysql_tutorial

C:\mysql_tutorial>npm install mysql
mysql@2.5.4 node_modules\mysql
├── require-all@0.0.8
├── bignumber.js@1.4.1
└── readable-stream@1.1.13 (string_decoder@0.10.31, isarray@0.0.1, inherits@2
.0.1, core-util-is@1.0.1)

C:\mysql_tutorial>


  • mysql 모듈을 설치하였으니 바로 js파일(저의 경우 mysqls.js)을 만들어서 테스트 해봅시다.

예제 Test

  • 연결하기 -> 값 입력 -> 조회 -> 변경 -> 삭제 순서대로 해보겠습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : '[address]',
  user     : '[user]',
  password : '[password]',
});

connection.connect();

connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
  if (err) throw err;

  console.log(rows);
  console.log('The solution is: ', rows[0].solution);
});

connection.end();

  • 가장 처음 나오는 예제입니다.
  • 3~5번 라인에서는 각자에 맞는 값을 넣어 설정을 해줍니다.
    • 로컬에서 테스트한다면 [adress] 부분에 localhost
    • 여러가지 옵션이 여기의 connection option에 쭈욱 설명되어 있습니다.
  • 13번 라인은 예제에 없지만 결과값의 리턴 형식을 보기 위해 넣었습니다.
  • node [test].js 로 실행합니다.


1
2
3
4
5
C:\mysql_tutorial>node mysqls.js
[ { solution: 2 } ]
The solution is:  2

C:\mysql_tutorial>

  • [{solution:2}] 를 보아 결과값은 레코드별로 배열로, 컬럼은 JSON방식으로 넘어오는 것을 어림짐작 할수 있겠네요.
  • 예상된 결과가 잘 나왔음을 알수 있습니다.

Insert

mysqls.js

1
2
3
4
5
6
7
8
9
...
connection.connect();
var post  = { m_tel: '010-1234-5678', m_id: 'GilDong', m_pass: 'password1', m_name: '홍길동', m_date: '2000-01-01', m_gender: '남', m_email: 'GilDong@Hong.com' };
var query = connection.query('INSERT INTO member SET ?', post, function(err, result) {
  // Neat!
  console.log(result);
});

connection.end();

  • connection.query(쿼리,입력값,결과처리)로 이루어 집니다.
  • 입력값은 위의 post에 넣어준것처럼 json방식으로 입력하면되고 이는 ejs에서 값이 넘어오는 방식이랑 같으니 값을 db에 넘겨주기에도 편합니다.
  • 이제 실행을 해봅시다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
C:\mysql_tutorial>node mysqls.js
undefined

C:\mysql_tutorial>node mysqls.js
{ fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0 }

  • 1~2라인은 실패 했을 경우 result, 4~12라인은 성공했을 경우 result 입니다.
  • mysql workbench에서 확인한 결과 값이 잘 들어갔음을 알수 있습니다.
  • Delete, Update 문도 이와같이 사용하면됩니다.

??와 ?(속성,값이 여러개인경우)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
connection.connect();

var table = 'member';
var columns = ['m_id', 'm_pass'];
var where = 'm_id';
var userId = 'GilDong';
var query = connection.query('SELECT ?? FROM ?? WHERE ?? = ?', [columns, table, where,userId], function(err,rows, results) {
 console.log(rows);
});

connection.end();


  • 쿼리문에서 ?? 인경우에는 컬럼명, 테이블 명와 같은 속성값일 경우 씁니다.
  • ??와는 다르게 ?인 경우에는 값(변수) 일 경우 사용되며
  • 쿼리문의 ??,?의 순서대로 배열에 넣어 query의 두번째 속성값으로 입력하면됩니다.

결과값(리턴값) 보기

  • select로 한번 더 다른 예제를 해보겠습니다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
...
connection.connect();

connection.query('SELECT * from member', function(err, rows, fields) {
  if (err) throw err;

  console.log(rows);
  console.log(fields);
});

connection.end();

  • select와 동시에 옆에 err,rows,fields에 대한 것을 알아보겠습니다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
C:\mysql_tutorial>node mysqls.js
[ { m_id: 'GilDong',
    m_pass: 'password1',
    m_name: '홍길동',
    m_tel: '010-1234-5678',
    m_date: Sat Jan 01 2000 00:00:00 GMT+0900 (대한민국 표준시),
    m_gender: '남',
    m_email: 'GilDong@Hong.com' } ]
[ { catalog: 'def',
    db: 'node',
    table: 'member',
    orgTable: 'member',
    name: 'm_id',
    orgName: 'm_id',
    charsetNr: 33,
    length: 60,
    type: 253,
    flags: 20483,
    decimals: 0,
    default: undefined,
    zeroFill: false,
    protocol41: true },

  • rows는 앞에서 봤듯이 해당 결과에 대한 것을 레코드는 행렬로, 컬럼명와 값은 json으로 들어오는 것을 볼수 있고,
  • fields에 대한 값은 각각 컬럼에 대한 자세한 정보를 보여주고 있습니다.


1
2
3
4
5
6
7
8
9
connection.connect();

var post = {m_id:'GilDong'};
connection.query('SELECT * from member where ?',post, function(err, rows, fields) {
  if (err) throw err;

  console.log(rows);
  console.log(fields);
});

  • 위의 insert문과 같이 이렇게 사용할수 있습니다.