# [Nodejs] 解決 MySQL Error: Connection lost. The server closed the connection 的方法

# 定時斷線若無跡可尋真的很令人頭大

最近在幫朋友使用 nodeJs 架測試用伺服器時發生一件令我困擾萬分的問題。

那就是,我的 nodeJs Server 所連接的 mysql 資料庫大約在幾個小時後就會自動斷線,使 nodeJs Server 拋出一個 PROTOCOL_CONNECTION_LOST 的 Exception。

MySQL Error: Connection lost. The server closed the connection

我一開始以為是自己的程式程式問題,千測萬測找不出原因來。之後在網路上查找,才知道原來是因為 MySQL 本身有一個機制: wait_time 。當超超過這個時間的時候便會 connection lost . 這時,再去 request MySQL 時便會連接不上 MySQL。

解決方法網路上查到有兩種

# 第一種方法:在偵測到拋出 PROTOCOL_CONNECTION_LOST 時就重新執行連線。

在偵測到拋出 PROTOCOL_CONNECTION_LOST 時就重新執行連線。我們可以把這封裝成一個 module,在需要的地方使用。要注意的是,在使用 conn 時,不可以將其設為 global variable ,不然無法得到更新的 conn

var mysql = require('mysql');
var mysql_config = {
    host: '127.0.0.1',
    user:'your user',
    password:'your password',
    database:'your database'
};
function disconnect_handler() {
   let conn = mysql.createConnection(mysql_config);
    conn.connect(err => {
        (err) && setTimeout('disconnect_handler()', 2000);
    });
    conn.on('error', err => {
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            //db error 重新連線
            disconnect_handler();
        } else {
            throw err;
        }
    });
    exports.conn = conn;
}
exports.disconnect_handler =  disconnect_handler;

# 第二種方法:使用 Connection pool

使用 Connection pool。當需要 connection 時,從 connection pool 拿取連線即可。

程式碼大約如下:

var mysql = require("mysql");
var pool = mysql.createPool({
    host: 'your host',
    user:'your account',
    password:'your password',
    database:'your database',
    connectionLimit : 10, // 可以自己設定
});
var query = function(sql, options, callback) {
    console.log(sql, options, callback);
    if (typeof options === "function") {
        callback = options;
        options = undefined;
    }
    pool.getConnection(function(err, conn){
        if (err) {
            callback(err, null, null);
        } else {
            conn.query(sql, options, function(err, results, fields){
                // callback
                callback(err, results, fields);
            });
            // release connection。
            // 要注意的是,connection 的釋放需要在此 release,而不能在 callback 中 release
            conn.release();
        }
    });
};
module.exports = query;

一樣將此封裝成一個 module,並且在想使用的地方使用。

我後來選擇了第二種方式,並且封裝成一個 middleware。大約類似如此方式使用:

app.use(function (req, res, next) {
    req.query = mysqlPoolQuery;
    next();
});

如此一來就順利解決了 mySQL 的 connection closed 問題了。

Like z20240z's work