【问题标题】:nodejs mysql Error: Connection lost The server closed the connectionnodejs mysql错误:连接丢失服务器关闭了连接
【发布时间】:2013-12-11 05:01:10
【问题描述】:

当我使用node mysql时,在12:00到2:00之间出现一个错误,表明TCP连接被服务器关闭。这是完整的消息:

Error: Connection lost: The server closed the connection.
at Protocol.end (/opt/node-v0.10.20-linux-x64/IM/node_modules/mysql/lib/protocol/Protocol.js:73:13)
at Socket.onend (stream.js:79:10)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)

solution。但是,我通过这种方式尝试后,问题也出现了。现在我不知道该怎么办。有人遇到这个问题吗?

下面是我写的方法:

    var handleKFDisconnect = function() {
    kfdb.on('error', function(err) {
        if (!err.fatal) {
            return;
        }
        if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
            console.log("PROTOCOL_CONNECTION_LOST");
            throw err;
        }
        log.error("The database is error:" + err.stack);

        kfdb = mysql.createConnection(kf_config);

        console.log("kfid");

        console.log(kfdb);
        handleKFDisconnect();
    });
   };
   handleKFDisconnect();

【问题讨论】:

  • 请注意,您的代码中有一条错误消息:if (err.code !== 'PROTOCOL_CONNECTION_LOST') { console.log("PROTOCOL_CONNECTION_LOST"); throw err; }。如果 if() 不是 not PROTOCOL_CONNECTION_LOST,则您执行该块,但消息说这是错误...可能非常令人困惑。

标签: mysql node.js dbconnection


【解决方案1】:

尝试使用this code处理服务器断开连接:

var db_config = {
  host: 'localhost',
    user: 'root',
    password: '',
    database: 'example'
};

var connection;

function handleDisconnect() {
  connection = mysql.createConnection(db_config); // Recreate the connection, since
                                                  // the old one cannot be reused.

  connection.connect(function(err) {              // The server is either down
    if(err) {                                     // or restarting (takes a while sometimes).
      console.log('error when connecting to db:', err);
      setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
    }                                     // to avoid a hot loop, and to allow our node script to
  });                                     // process asynchronous requests in the meantime.
                                          // If you're also serving http, display a 503 error.
  connection.on('error', function(err) {
    console.log('db error', err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
      handleDisconnect();                         // lost due to either server restart, or a
    } else {                                      // connnection idle timeout (the wait_timeout
      throw err;                                  // server variable configures this)
    }
  });
}

handleDisconnect();

在您的代码中,我缺少connection = mysql.createConnection(db_config); 之后的部分

【讨论】:

  • 好的,我会试试这个。但是我怎么能模拟这种情况
  • 提示:我正在通过重新启动 mysql 服务来测试重新连接,以确保一切正常。
  • @jackieLin你可以模拟一下情况,重启mysql服务,在ubuntu sudo service mysql restart
  • 谢谢@user3073745,重启解决了这个问题
  • 完美适用于节点 8.* 、npm 5.6.0 和 mysql:5.7...谢谢!!
【解决方案2】:

我不记得我最初使用此机制的用例。如今,我想不出任何有效的用例。

您的客户端应该能够检测到连接何时丢失并允许您重新创建连接。如果使用同一连接执行部分程序逻辑很重要,则使用事务。

tl;博士;请勿使用此方法。


一个务实的解决方案是强制 MySQL 保持连接:

setInterval(function () {
    db.query('SELECT 1');
}, 5000);

我更喜欢这个解决方案而不是连接池和处理断开连接,因为它不需要以一种知道连接存在的方式来构建你的代码。每 5 秒进行一次查询可确保连接保持活动状态并且不会发生 PROTOCOL_CONNECTION_LOST

此外,此方法可确保您保持相同的连接处于活动状态,而不是重新连接。这个很重要。考虑一下如果您的脚本依赖于LAST_INSERT_ID() 并且 mysql 连接在您不知情的情况下被重置会发生什么?

但是,这只能确保不会发生连接超时(wait_timeoutinteractive_timeout)。正如预期的那样,在所有其他情况下它都会失败。因此,请务必处理其他错误。

【讨论】:

  • 只是好奇,你会把那个数据库查询放在哪里?在nodejs服务器的底部对吗?唯一的问题是,我只使用 mysql 对用户进行一次身份验证,然后我将他们的数据存储在我的 rpg 游戏的临时用户对象中。不知道为什么我今天随机得到这个mysql关闭错误,嗯。我也在正确关闭连接等等。
  • 您应该根据需要连接到数据库并断开连接。此解决方案适用于持续运行并始终使用数据库连接的服务。
  • 听起来不太可能,因为您的代码遵循所描述的模式(类似于gist.github.com/gajus/5bcd3c7ec5ddcaf53893)。如果这种情况在数千个查询中只发生一两次,我会假设存在连接问题、服务器过载或类似情况。
  • 这可能是有史以来最糟糕的建议!有人建议您应该用查询来锤击数据库,这样连接就不会消失?如果 100 人这样做会怎样?或者为什么不是 10 000,如果您的应用程序没有注意到,线程应该返回到 MYSQL 线程池而不是占用线程,这样您的弱代码就不会中断!在这种情况下,如果发生此类事件,您将实现重新连接的功能!
  • 我已经更新了答案以反映我不推荐这种方法。感谢 Patrik 的提醒。
【解决方案3】:

更好的解决方案是使用池 - 它会为您处理。

const pool = mysql.createPool({
  host: 'localhost',
  user: '--',
  database: '---',
  password: '----'
});

// ... later
pool.query('select 1 + 1', (err, rows) => { /* */ });

https://github.com/sidorares/node-mysql2/issues/836

【讨论】:

  • 这应该是公认的答案。使用池机制将隐藏有关如何处理连接超时的所有复杂细节。此外,在 MySQL 节点模块附带的 node_modules/mysql/Readme.md 文件中有关于如何使用它的文档。
【解决方案4】:

要模拟断开的连接尝试

connection.destroy();

更多信息在这里:https://github.com/felixge/node-mysql/blob/master/Readme.md#terminating-connections

【讨论】:

    【解决方案5】:

    在每个查询中创建和销毁连接可能很复杂,当我决定安装 MariaDB 而不是 MySQL 时,我对服务器迁移有些头疼。出于某种原因,文件 etc/my.cnf 中的参数 wait_timeout 的默认值为 10 秒(这导致无法实现持久性)。然后,将解决方案设置为28800,即8小时。好吧,我希望对这个“güevonada”有所帮助......对不起我的英语不好。

    【讨论】:

      【解决方案6】:

      这个模块不是一个一个地创建和管理连接,而是使用 mysql.createPool(config) 提供内置的连接池。

      var mysql = require('mysql');
      var pool  = mysql.createPool({
        connectionLimit : 10,
        host            : 'example.org',
        user            : 'bob',
        password        : 'secret',
        database        : 'my_db'
      });
       
      pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
        if (error) throw error;
        console.log('The solution is: ', results[0].solution);
      });
      

      这是 pool.getConnection() -> connection.query() -> connection.release() 代码流的快捷方式。使用 pool.getConnection() 对于为后续查询共享连接状态很有用。这是因为对 pool.query() 的两次调用可能会使用两个不同的连接并并行运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-28
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 1970-01-01
        • 1970-01-01
        • 2018-02-25
        • 2018-12-11
        相关资源
        最近更新 更多