node.js + mysql连接池

kas*_*lan 66 mysql node.js

我正在试图弄清楚如何构建我的应用程序以使用MySQL最有效的方式.我正在使用node-mysql模块.这里的其他线程建议使用连接池,所以我设置了一个小模块mysql.js

var mysql = require('mysql');

var pool  = mysql.createPool({
    host     : 'localhost',
    user     : 'root',
    password : 'root',
    database : 'guess'
});

exports.pool = pool;
Run Code Online (Sandbox Code Playgroud)

现在每当我想查询mysql时,我需要这个模块,然后查询数据库

var mysql = require('../db/mysql').pool;

var test = function(req, res) {
     mysql.getConnection(function(err, conn){
         conn.query("select * from users", function(err, rows) {
              res.json(rows);
         })
     })
}
Run Code Online (Sandbox Code Playgroud)

这是好方法吗?我真的找不到太多使用mysql连接的例子,除了非常简单的例子,其中一切都在主app.js脚本中完成,所以我真的不知道什么是约定/最佳实践.

我应该在每次查询后总是使用connection.end()吗?如果我在某个地方忘了怎么办?

如何重写我的mysql模块的导出部分只返回一个连接,所以我不必每次都写getConnection()?

Kla*_*aak 52

这是一个很好的方法.

如果您只想获得连接,请将以下代码添加到池所在的模块中:

var getConnection = function(callback) {
    pool.getConnection(function(err, connection) {
        callback(err, connection);
    });
};

module.exports = getConnection;
Run Code Online (Sandbox Code Playgroud)

你仍然必须每次都写getConnection.但是你可以在第一次获得它时保存模块中的连接.

完成使用后不要忘记结束连接:

connection.release();
Run Code Online (Sandbox Code Playgroud)

  • 只是一个抬头.它是`connection.release();`现在,对于池. (13认同)
  • 你也可以直接使用`pool.query()`。这是 `pool.getConnection()` -> `connection.query()` -> `connection.release()` 代码流的快捷方式。 (2认同)

小智 13

你会发现这个包装有用:)

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;
            }
        };
    }
};
Run Code Online (Sandbox Code Playgroud)

需要它,像这样使用它:

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});
          });
Run Code Online (Sandbox Code Playgroud)


bin*_*nki 10

pool.getConnection()如果可以,应避免使用。如果您致电pool.getConnection(),则必须connection.release()在使用完连接后致电。否则,一旦达到连接限制,您的应用程序将永远陷入等待连接返回到池的状态。

对于简单查询,可以使用pool.query()connection.release()即使在错误情况下,该速记也会自动为您服务。

function doSomething(cb) {
  pool.query('SELECT 2*2 "value"', (ex, rows) => {
    if (ex) {
      cb(ex);
    } else {
      cb(null, rows[0].value);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

但是,在某些情况下,您必须使用pool.getConnection()。这些情况包括:

  1. 在事务中进行多个查询。
  2. 在后续查询之间共享数据对象,例如临时表。

如果必须使用pool.getConnection(),请确保connection.release()使用类似于以下的模式进行调用:

function doSomething(cb) {
  pool.getConnection((ex, connection) => {
    if (ex) {
      cb(ex);
    } else {
      // Ensure that any call to cb releases the connection
      // by wrapping it.
      cb = (cb => {
        return function () {
          connection.release();
          cb.apply(this, arguments);
        };
      })(cb);
      connection.beginTransaction(ex => {
        if (ex) {
          cb(ex);
        } else {
          connection.query('INSERT INTO table1 ("value") VALUES (\'my value\');', ex => {
            if (ex) {
              cb(ex);
            } else {
              connection.query('INSERT INTO table2 ("value") VALUES (\'my other value\')', ex => {
                if (ex) {
                  cb(ex);
                } else {
                  connection.commit(ex => {
                    cb(ex);
                  });
                }
              });
            }
          });
        }
      });
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢使用Promises和useAsync()模式。与async/ 结合使用的这种模式await使意外忘记release()连接变得更加困难,因为它将词法作用域转换为对以下内容的自动调用.release()

async function usePooledConnectionAsync(actionAsync) {
  const connection = await new Promise((resolve, reject) => {
    pool.getConnection((ex, connection) => {
      if (ex) {
        reject(ex);
      } else {
        resolve(connection);
      }
    });
  });
  try {
    return await actionAsync(connection);
  } finally {
    connection.release();
  }
}

async function doSomethingElse() {
  // Usage example:
  const result = await usePooledConnectionAsync(async connection => {
    const rows = await new Promise((resolve, reject) => {
      connection.query('SELECT 2*4 "value"', (ex, rows) => {
        if (ex) {
          reject(ex);
        } else {
          resolve(rows);
        }
      });
    });
    return rows[0].value;
  });
  console.log(`result=${result}`);
}
Run Code Online (Sandbox Code Playgroud)


Sag*_*fan 7

我正在使用这个与mysql的基类连接:

"base.js"

var mysql   = require("mysql");

var pool = mysql.createPool({
    connectionLimit : 10,
    host: Config.appSettings().database.host,
    user: Config.appSettings().database.username,
    password: Config.appSettings().database.password,
    database: Config.appSettings().database.database
});


var DB = (function () {

    function _query(query, params, callback) {
        pool.getConnection(function (err, connection) {
            if (err) {
                connection.release();
                callback(null, err);
                throw err;
            }

            connection.query(query, params, function (err, rows) {
                connection.release();
                if (!err) {
                    callback(rows);
                }
                else {
                    callback(null, err);
                }

            });

            connection.on('error', function (err) {
                connection.release();
                callback(null, err);
                throw err;
            });
        });
    };

    return {
        query: _query
    };
})();

module.exports = DB;
Run Code Online (Sandbox Code Playgroud)

就这样使用它:

var DB = require('../dal/base.js');

DB.query("select * from tasks", null, function (data, error) {
   callback(data, error);
});
Run Code Online (Sandbox Code Playgroud)