node.js + mysql connection pooling

前端 未结 7 1091
执念已碎
执念已碎 2020-11-28 02:25

I\'m trying to figure out how to structure my application to use MySQL most efficent way. I\'m using node-mysql module. Other threads here suggested to use connection poolin

7条回答
  •  情歌与酒
    2020-11-28 02:57

    You should avoid using pool.getConnection() if you can. If you call pool.getConnection(), you must call connection.release() when you are done using the connection. Otherwise, your application will get stuck waiting forever for connections to be returned to the pool once you hit the connection limit.

    For simple queries, you can use pool.query(). This shorthand will automatically call connection.release() for you—even in error conditions.

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

    However, in some cases you must use pool.getConnection(). These cases include:

    • Making multiple queries within a transaction.
    • Sharing data objects such as temporary tables between subsequent queries.

    If you must use pool.getConnection(), ensure you call connection.release() using a pattern similar to below:

    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);
                      });
                    }
                  });
                }
              });
            }
          });
        }
      });
    }
    

    I personally prefer to use Promises and the useAsync() pattern. This pattern combined with async/await makes it a lot harder to accidentally forget to release() the connection because it turns your lexical scoping into an automatic call to .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}`);
    }
    

提交回复
热议问题