[Node.js] mysql2/promise 사용법

STEVELOPER·2022년 10월 6일
0

Node.js

목록 보기
3/9

node.js 로 서버를 구축하면서 mysql 을 사용하게 되었는데 콜백 방식보다 async/await 방식이 직관적이고 편리해서 mysql2/promise 모듈을 사용하게 되었다.

해당 포스트를 기록하는 이유는 이 모듈을 잘못 사용하면서 too many connections 에러를 접하게 되고 몇몇 mysql 설정을 건드려보게 되어 기록용으로 작성한다.

본론

우선 기본적인 mysql2/promise 사용법은 다음과 같다

import mysql from "mysql2/promise";

export const pool = mysql.createPool({
	host: x.x.x.x, // localhost or ip
    user: username,
    password: password,
    port: xxxx,
    database: database,
    multipleStatements: true // allows to use multiple statements
});

기존 mysql 의 createConnection() 은 새로운 connection 을 생성하므로 직접 끊어야 하는것으로 기억한다. 하지만 createPool 의 경우 connection 을 가져오고 다시 반환하면 해당 pool 을 다시 꺼내서 쓰는 형식이라고 한다.

하지만 pool.query() 이런식으로 사용해도 pool 이 자동으로 반납된다 했으나 무언가 잘 되지 않는 것처럼 보였고 일정 시간이 지나면 어김없이 too many connections 가 날 괴롭혔다.

그래서 pool.getConnection(async(conn) => conn); 방식을 사용했는데 이는 마찬가지로 사용후 release 를 해주어야한다. 그래도 async/await 을 사용할 수 있어 충분히 메리트가 있었다.

const selectQuery = async() => {
	const connection = await pool.getConnection(async(conn) => conn);
    const [users] = connection.query(`SELECT * FROM user;`);
    connection.release();
    return users;
}

에러

mysql 의 사용 방식을 변경하면서 마주했던 문제점인 too many connections 는
mysql 의 설정값 max_connections 를 Max_used_connections 가 넘어서면서 발생한다고 한다.
터미널에서 mysql 에 접속하면 확인할 수 있다.

mysql -u root -p

접속한 후,

mysql> show variables like "%max_connections%";
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 214   |
+-----------------+-------+
mysql> set global max_connections = 500;

mysql 을 재시작할 경우 별 다른 설정파일(my.cnf 등) 을 지정하지 않았다면 기본값으로
돌아온다.
wait_timeout 도 마찬가지다.

 mysql> show variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
mysql> set wait_timeout = 500;

mysql status

mysql> show status like "%CONNECT%";
+-----------------------------------------------+---------------------+
| Variable_name                                 | Value               |
+-----------------------------------------------+---------------------+
| Aborted_connects                              | 6                   |
| Connection_errors_accept                      | 0                   |
| Connection_errors_internal                    | 0                   |
| Connection_errors_max_connections             | 0                   |
| Connection_errors_peer_address                | 0                   |
| Connection_errors_select                      | 0                   |
| Connection_errors_tcpwrap                     | 0                   |
| Connections                                   | 64                  |
| Locked_connects                               | 0                   |
| Max_used_connections                          | 39                  |
| Max_used_connections_time                     | 2022-10-06 13:54:23 |
| Performance_schema_session_connect_attrs_lost | 0                   |
| Ssl_client_connects                           | 0                   |
| Ssl_connect_renegotiates                      | 0                   |
| Ssl_finished_connects                         | 0                   |
| Threads_connected                             | 38                  |
+-----------------------------------------------+---------------------+

Connections : 누적된 connection 수
Max_used_connections : 최대로 연결된 connection 수
Threads_connected : 현재 연결된 connection 수

Threads_connected 가 계속해서 늘어나는 현상이 발생했었으나
.release() 를 사용한 이후 늘어나지 않았다.

mysql.createPool() 을 정의할 때 connectionLimit 을 통해 release() 가 제대로 이루어지지 않았거나 connection 이 사용중이어서 일을 하지 않는 pool 이 없을경우 connection 이 새로 생성되지 않게 할 수도 있다고 한다.

pool.getConnection(async(conn) => conn) 방식을 사용할 경우
잊지않고 pool.release() 하도록 하자.

profile
JavaScript, Node.js, Express, React, React Native, GraphQL, Apollo, Prisma, MySQL

1개의 댓글

comment-user-thumbnail
2023년 9월 27일

const [users] = connection.query(SELECT * FROM user;); 에 await를 붙여야하지 않나 싶습니다!

답글 달기