Node.js MySQL需要持久连接

我需要一个持久的MySQL连接为我的节点networking应用程序。 问题是这种情况一天发生几次:

Error: Connection lost: The server closed the connection. at Protocol.end (/var/www/n/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:895:16 at process._tickCallback (node.js:415:13) error: Forever detected script exited with code: 8 error: Forever restarting script for 2 time info: socket.io started 

这是我的连接代码:

 // Yes I know multipleStatements can be dangerous in the wrong hands. var sql = mysql.createConnection({ host: 'localhost', user: 'my_username', password: 'my_password', database: 'my_database', multipleStatements: true }); sql.connect(); function handleDisconnect(connection) { connection.on('error', function(err) { if (!err.fatal) { return; } if (err.code !== 'PROTOCOL_CONNECTION_LOST') { throw err; } console.log('Re-connecting lost connection: ' + err.stack); sql = mysql.createConnection(connection.config); handleDisconnect(sql); sql.connect(); }); } handleDisconnect(sql); 

正如你所看到的,handleDisconnect代码不起作用。

使用mysql连接池。 它会重新连接,当一个连接死亡,并获得能够同时进行多个SQL查询的额外好处。 如果您不使用数据库池,则应用程序将在等待当前正在运行的数据库请求完成时阻止数据库请求。

我通常定义一个数据库模块,使我的查询与我的路线保持分离。 它看起来像这样…

 var mysql = require('mysql'); var pool = mysql.createPool({ host : 'example.org', user : 'bob', password : 'secret' }); exports.getUsers = function(callback) { pool.getConnection(function(err, connection) { if(err) { console.log(err); callback(true); return; } var sql = "SELECT id,name FROM users"; connection.query(sql, [], function(err, results) { connection.release(); // always put connection back in pool after last query if(err) { console.log(err); callback(true); return; } callback(false, results); }); }); }); 

我知道这是超级延迟,但我已经写了一个解决scheme,我认为可能会更通用和可用。 我写了一个完全依赖于connection.query()的应用程序,并切换到一个池打破了这些调用。

这是我的解决scheme:

 var mysql = require('mysql'); var pool = mysql.createPool({ host : 'localhost', user : 'user', password : 'secret', database : 'test', port : 3306 }); module.exports = { query: function(){ var sql_args = []; var args = []; for(var i=0; i<arguments.length; i++){ args.push(arguments[i]); } var callback = args[args.length-1]; //last arg is callback pool.getConnection(function(err, connection) { if(err) { console.log(err); return callback(err); } if(args.length > 2){ sql_args = args[1]; } connection.query(args[0], sql_args, function(err, results) { connection.release(); // always put connection back in pool after last query if(err){ console.log(err); return callback(err); } callback(null, results); }); }); } }; 

这将实例化池一次,然后导出一个名为query的方法。 现在,当任何地方调用connection.query()时,它将调用此方法,该方法首先从池中获取连接,然后将parameter passing给连接。 它具有首先获取callback的附加效果,因此可以callback从池中获取连接的任何错误。

要使用这个,只需要它作为模块来代替mysql。 例:

 var connection = require('../middleware/db'); function get_active_sessions(){ connection.query('Select * from `sessions` where `Active`=1 and Expires>?;', [~~(new Date()/1000)], function(err, results){ if(err){ console.log(err); } else{ console.log(results); } }); } 

这看起来就像正常的查询,但实际上打开一个池,并在后台从池中抓取连接。

回应@gladsocc问题:

有没有一种方法来使用池而不重构所有的东西? 我在应用程序中有几十个SQL查询。

这是我最终build立的。 这是查询function的包装。 它会抓住连接,执行查询,然后释放连接。

 var pool = mysql.createPool(config.db); exports.connection = { query: function () { var queryArgs = Array.prototype.slice.call(arguments), events = [], eventNameIndex = {}; pool.getConnection(function (err, conn) { if (err) { if (eventNameIndex.error) { eventNameIndex.error(); } } if (conn) { var q = conn.query.apply(conn, queryArgs); q.on('end', function () { conn.release(); }); events.forEach(function (args) { q.on.apply(q, args); }); } }); return { on: function (eventName, callback) { events.push(Array.prototype.slice.call(arguments)); eventNameIndex[eventName] = callback; return this; } }; } }; 

我就像平常一样使用它。

 db.connection.query("SELECT * FROM `table` WHERE `id` = ? ", row_id) .on('result', function (row) { setData(row); }) .on('error', function (err) { callback({error: true, err: err}); });