且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

具有多个查询的NodeJS mysql连接池

更新时间:2023-02-06 21:04:08

您的连接流程很好.如果仅执行1个查询,则实际上不需要执行任何步骤,您可以直接在池上调用 .query().(其余的都在引擎盖下).

Your connection flow is fine. If you only do 1 query, you don't actually need to do any of the steps and you can just call .query() on the pool directly. (Which does the rest under the hood).

大多数情况下,您需要在1个事务中执行多个查询,但是我会添加事务支持:

The situation where you need to do multiple queries in 1 transaction is mostly, but I would add transaction support:

  • 创建连接池
  • 当您需要执行许多查询时:
  • 从池中获取getConnection()
  • 开始交易
  • 重复需要查询的项目
  • 执行查询
  • 如果有任何失败,请停止并回滚
  • 如果全部成功,则提交
  • .release()连接

如果所有查询都已完成",则您知道何时释放连接.您怎么知道它完成了?有不止一种方法.我建议您使用Promise API,所以它看起来可能像这样:

You know when to release the connection if all the queries are 'done'. How do you know it's done? There's more than one way. I would recommend you use the promise API, so it might look like this:

async function doStuff(items) {

  try { 
    const connection = await pool.getConnection();
    await connection.beginTransaction();
    for(const item of items) {
      await connection.query('....');
    }
    await connection.commit();
  } catch (e) {
    await connection.rollback();
    throw e;
  } finally {
    await connection.release();
  }

}

此模式有一些优点:

  1. 它将正确报告错误
  2. 它将在成功和错误时释放连接.
  3. 它要么完全失败,要么完全成功.在这里没有半招半招.

如果您不关心交易,可以将其简化:

If you don't care about transactions, this can be simplified:

async function doStuff(items) {

  try { 
    const connection = await pool.getConnection();
    for(const item of items) {
      await connection.query('....');
    }
  } finally {
    await connection.release();
  }

}

与此相关的问题是,您可以获得部分成功,这通常是不希望的,尤其是对于API而言.但是,如果对您来说足够好,那就足够了.

The issue with this is that you can get partial successes, which is often not desirable, especially for APIs. However, if it's good enough for you, it's good enough.

如果您不愿意进行任何交易,从理论上讲,您可以完全跳过 getConnection 步骤:

And if you are comfortable not having transactions, you can in theory completely skip the getConnection step:

async function doStuff(items) {
  for(const item of items) {
    await pool.query('....');
  }
}

含义是所有查询都可能在不同的连接上执行.这可能会给您带来较差的性能,但会使代码更简单.

The implication is that all your queries might execute on different connections. This may give you worse performance, but makes for simpler code.

如何启用承诺?

这有点争议.为此,您可能需要切换mysql软件包.有一个 mysql2 软件包,它具有一个非常出色的 mysql2/promise 导入(并且实际上与更流行的 mysql 软件包共享代码).超级建议切换到此.

Well this is a bit controversial. To do this, you might need to switch mysql packages. There is a mysql2 package that has a mysql2/promise import that's really excellent (and actually shares code with the more popular mysql package). It's super recommended to switch to this.

如果我不想切换软件包怎么办?

嗯,这个的回调版本要痛苦得多.在这种情况下,我建议您仍然使用Promise,但可以将您的回调转换为Promise模式,也许使用"promisify".

Well, the callback version of this is a lot more painful. I would in this case recommend still using promises but converting your callbacks to a promise pattern, perhaps using 'promisify'.

如果您真的不希望在任何地方做出承诺,则基本上必须将我的示例转换为基于回调的示例,这看起来会更加痛苦.

If you really don't want promises anywhere, you basically have to convert my examples to callback-based ones, which is going to look a lot more painful.