[Node.js, MYSQL] PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR 에러 해결하기

이애옹·2024년 8월 6일
0
post-thumbnail
post-custom-banner

❌ PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR 에러 발생

API 서버를 개발하고 배포 한 뒤에, 테스트를 진행하던 도중 아래와 같은 에러가 발생했다

Error: Cannot enqueue Query after fatal error.
at Protocol._validateEnqueue (/app/node_modules/mysql/lib/protocol/Protocol.js:212:16)
at Protocol._enqueue (/app/node_modules/mysql/lib/protocol/Protocol.js:138:13)
at Connection.query (/app/node_modules/mysql/lib/Connection.js:198:25)
at /app/models/receiveCardList.models.v1.js:604:14
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
fatal: false
}

분명 지난주까지만 해도 발생하지 않던 에러였는데,
월요일에 출근 후 테스트를 하던 중 에러가 발생했다 !!!
로컬로 돌려보니 로컬에는 이상이 없길래, 에러코드를 검색하고 확인하던 도중 또 정상 작동 하는것을 확인했다.

지금 당장은 실제 운영하는 서비스는 아니고 테스트 단계라서 문제가 없지만,
추후에 실제 운영하는 서비스에서 이런 에러가 나면 안될 것 같아 에러에 대해 확인 해 봤당

💬 에러 원인 분석

해당 문제가 발생한 원인을 chatGPT 에게 물어보니 다음과 같이 알려줬다.

PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR 오류는 주로 Node.js와 MySQL을 사용할 때 발생하는 에러입니다. 이 에러는 Node.js 애플리케이션이 MySQL 데이터베이스에 연결하려고 할 때, 이전에 발생한 치명적인 오류(fatal error) 이후에 다시 요청을 시도할 때 발생합니다.

  • MySQL 연결이 끊어진 경우: MySQL 서버와의 연결이 끊어진 후에 쿼리를 실행하려고 할 때 발생합니다.
  • 치명적인 오류가 발생한 경우: 이전 쿼리나 명령어 실행 중에 치명적인 오류가 발생했을 때, 이 오류 이후에 새로운 쿼리를 보내려고 하면 이 에러가 발생합니다.
  • 잘못된 커넥션 관리: MySQL 커넥션 풀이나 연결을 잘못 관리하여, 이미 문제가 발생한 연결을 다시 사용하려고 할 때 발생할 수 있습니다.

내가 Mysql DB를 이용해서 연결을 하고 있는데,
커넥션 문제가 발생한 것 같다.

이전까지는 문제가 없었기에 관련 자료를 더 찾아봤는데, 문제가 될 수 있는 원인으로는

1. 많은 요청으로 인한 과부화
2. 커넥션이 이뤄진 후 일정 시간동안 쿼리가 발송되지 않아 커넥션 끊김

이렇게 두가지가 대표적인 것 같다~~

나는 위에서 말했듯이 주말동안 쿼리를 사용하지 않다가
그 다음주에 테스트를 하던 도중 오류가 발생했기 때문에 2번째 이유가 원인인 것 같았다.

📌 에러 해결하기

위 원인에 대한 해결 방법을 찾아보니 두가지가 있었다.

1. 활동하지 않는 커넥션을 끊을때까지 서버가 대기하는 시간 늘리기
2. 무의미한 더미 쿼리를 계속 보내면서 자동으로 커넥션이 끊어지는 것을 방지하기

난 이중에서 2번째 방식을 사용했다! 왜냐면 이전 프로젝트에서 이미 이 방법을 사용하고 있어서~~

📝 node-schdule 모듈 설치

일단 스케줄러를 이용해 1분마다 쿼리를 요청해야 하므로 스케줄러를 설치 해 줬다

npm i node-schedule

위 명령어로 설치 해 주면 된다.

📝 MYSQL 상태 체크 소스 추가하기

그 다음, schedule 폴더 생성 후 mysql 상태를 체크하는 스케줄러를 넣을 js 파일을 생성한다.
나는 mysqlConnChk.js 파일을 생성 해 줬다.

이제 해당 파일에 상태 체크 코드 넣기!

const cron = require('node-schedule');
const pool = require('../db/mysqlPool');

cron.scheduleJob('*/1 * * * *', async function() {
	try {
		const query = `SELECT 1`;
		const client = await pool.acquire(); // await를 사용하여 클라이언트를 획득

		try {
			client.query(query, (err, result, fields) => {
				if (err) {
					console.error(err);
				} else {
					console.log('mysqlConnChk success!!');
				}
			});
		} finally {
			pool.release(client); // finally 블록에서 항상 클라이언트를 릴리즈
		}
	} catch (err) {
		const errObj = {
			error: err,
			message: err.message
		};
		console.error(errObj);
	}
});

스케줄러가 1분마다 작동하게 해줬고,
SELECT 1 이라는 database와 관련 없는 무의미한 더미 쿼리를 보내도록 구현 해 뒀다.

그리고 스케줄러가 계속 작동 할 수 있도록 app.js 에 스케줄러 작동 코드를 넣어주면 된다
끝~

👀 참고자료

profile
안녕하세요
post-custom-banner

0개의 댓글