如何在 Node js 中承诺一个 mysql 池连接?

Posted

技术标签:

【中文标题】如何在 Node js 中承诺一个 mysql 池连接?【英文标题】:How to promisify a mysql pool connection in Node js? 【发布时间】:2021-07-15 19:31:42 【问题描述】:

我正在尝试了解如何使用节点 js 工具来承诺池连接。 我会使用async/await 逻辑保持我的代码干净(没有回调地狱,我真的不喜欢特别是交易)。

这是我的配置文件:

const mysql = require('mysql');
const util = require('util');

const pool = mysql.createPool(
  connectionLimit: 10,
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
);

// Ping database to check for common exception errors.
pool.getConnection((err, connection) => 
  if (err) 
    if (err.code === 'PROTOCOL_CONNECTION_LOST') 
      console.error('Database connection was closed.')
    
    if (err.code === 'ER_CON_COUNT_ERROR') 
      console.error('Database has too many connections.')
    
    if (err.code === 'ECONNREFUSED') 
      console.error('Database connection was refused.')
    
  

  if (connection) connection.release();

  return;
)

// Promisify for Node.js async/await.
pool.query = util.promisify(pool.query)

module.exports = pool;

我正在执行这样的单个简单查询(它们工作正常):

let sql = "SELECT * FROM products WHERE code = ? ;"
let param = [code];
let results = await pool.query(sql, param);

我正在以这种方式开发交易(我认为这是一种完全错误的方法):

try 
    await pool.query('START TRANSACTION');

    sql = "INSERT INTO test (name) VALUES ( ? ) ;"
    param = ['pippo'];
    results = []
    await pool.query(sql, param);

    await pool.query('COMMIT');
 catch (error) 
    await pool.query('ROLLBACK');
    return next(error)

对于事务,我不应该使用pool.query(我认为,每次新连接时都会获取并在查询完成时自动释放它)。

在我看来pool.query 给交易带来了很大的问题: 如果一次只运行一个事务是可以的,但是如果同时运行2个(或更多)事务,那么第二个事务的COMMIT可以COMMIT第一个事务的所有查询只是因为在第一个COMMIT

我认为我应该获得一个新的连接,在整个事务流程中使用该连接并在最后释放它。所以每个事务流都需要一个自己的连接。

但我不知道如何承诺pool.getConnection,因为我承诺pool.query

我正在尝试类似:

pool.getConnection = util.promisify(pool.getConnection).bind(pool)
const conn = await pool.getConnection();

let sql = "SELECT * FROM test ;"
let param = [];
let results = await conn.query(sql); // I don't get here the expected rows 

但它不起作用。我不会成为结果中的行,但如果我 console.log(results) 我有这个:

Query 
  _events: [Object: null prototype] 
    error: [Function],
    packet: [Function],
    timeout: [Function],
    end: [Function]
  ,
  _eventsCount: 4,
  _maxListeners: undefined,
  _callback: undefined,
  _callSite: Error
      at Protocol._enqueue (C:\Users\rocco\wa\ferramenta\server\node_modules\mysql\lib\protocol\Protocol.js:144:48)
      at PoolConnection.query (C:\Users\rocco\wa\ferramenta\server\node_modules\mysql\lib\Connection.js:198:25)
      at C:\Users\rocco\wa\ferramenta\server\routes\imports.js:304:30
      at processTicksAndRejections (internal/process/task_queues.js:97:5),
  _ended: false,
  _timeout: undefined,
  _timer: Timer  _object: [Circular], _timeout: null ,
  sql: 'SELECT * FROM test ; ',
  values: [],
  typeCast: true,
  nestTables: false,
  _resultSet: null,
  _results: [],
  _fields: [],
  _index: 0,
  _loadError: null,
  _connection: PoolConnection 
    _events: [Object: null prototype] 
      end: [Function: _removeFromPool],
      error: [Function]
    ,
    _eventsCount: 2,
    _maxListeners: undefined,
    config: ConnectionConfig 
      host: 'localhost',
      port: '3306',
      localAddress: undefined,
      socketPath: undefined,
      user: 'root',
      password: '---myPassword---',
      database: '---nameOfMyDb---',
      connectTimeout: 10000,
      insecureAuth: false,
      supportBigNumbers: false,
      bigNumberStrings: false,
      dateStrings: false,
      debug: undefined,
      trace: true,
      stringifyObjects: false,
      timezone: 'local',
      flags: '',
      queryFormat: undefined,
      pool: [Pool],
      ssl: false,
      localInfile: true,
      multipleStatements: false,
      typeCast: true,
      maxPacketSize: 0,
      charsetNumber: 33,
      clientFlags: 455631,
      protocol41: true
    ,
    _socket: Socket 
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'localhost',
      _readableState: [ReadableState],
      readable: true,
      _events: [Object: null prototype],
      _eventsCount: 4,
      _maxListeners: undefined,
      _writableState: [WritableState],
      writable: true,
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: null,
      _server: null,
      timeout: 0,
      [Symbol(asyncId)]: 11,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: Timeout 
        _idleTimeout: -1,
        _idlePrev: null,
        _idleNext: null,
        _idleStart: 1284,
        _onTimeout: null,
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: true,
        [Symbol(refed)]: false,
        [Symbol(kHasPrimitive)]: false,
        [Symbol(asyncId)]: 14,
        [Symbol(triggerId)]: 1
      ,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0
    ,
    _protocol: Protocol 
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      readable: true,
      writable: true,
      _config: [ConnectionConfig],
      _connection: [Circular],
      _callback: null,
      _fatalError: null,
      _quitSequence: null,
      _handshake: true,
      _handshaked: true,
      _ended: false,
      _destroyed: false,
      _queue: [Array],
      _handshakeInitializationPacket: [HandshakeInitializationPacket],
      _parser: [Parser],
      [Symbol(kCapture)]: false
    ,
    _connectCalled: true,
    state: 'authenticated',
    threadId: 117,
    _pool: Pool 
      _events: [Object: null prototype] ,
      _eventsCount: 0,
      _maxListeners: undefined,
      config: [PoolConfig],
      _acquiringConnections: [],
      _allConnections: [Array],
      _freeConnections: [],
      _connectionQueue: [],
      _closed: false,
      query: [Function],
      getConnection: [Function: bound ],
      [Symbol(kCapture)]: false
    ,
    [Symbol(kCapture)]: false
  ,
  [Symbol(kCapture)]: false

一些想法? 谢了

【问题讨论】:

您可能希望使用 mysql2 包,它处理 async/await。这个包被写成“匹配流行的 myqljs/mysql”(这是你使用的包)。反正这么说here。 ;) 【参考方案1】:

这是一个关于我如何解决它的简单示例:

pool.getConnection = util.promisify(pool.getConnection)
let conn = await pool.getConnection();
conn.query = util.promisify(conn.query)

sql = "INSERT INTO test (name) VALUES ( ? ) ; ";
param = ['fakename'];
results = [];
results = await conn.query(sql, param)

conn.release(); // is important remember to release the connection

【讨论】:

以上是关于如何在 Node js 中承诺一个 mysql 池连接?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 node.js 中解决可变数量的承诺

Node.js如何使用MySQL的连接池实例

node.js mysql 池 beginTransaction & 连接

如何遍历 node.js 中的一系列承诺?

如何在 node.js 中的特定持续时间后强制解决承诺? [复制]

深入解析Node.js使用MySQL连接池