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() 하도록 하자.
const [users] = connection.query(
SELECT * FROM user;
); 에 await를 붙여야하지 않나 싶습니다!