TypeORM 与 MySQL 错误:池已关闭。调用数据库时测试卡住了

问题描述 投票:0回答:2

我们在 TypeORM 方面遇到了一个奇怪的问题,特别是在 Jest 方面(可能相关,也可能无关)。某个测试完全卡住/挂起,我们很难找出问题所在。

就堆栈而言:

Typescript, NodeJS, Apollo Graphql, Jest, MySQL
。 该测试实际上是使用 Apollo 集成测试框架的集成测试。

首先发生的是一个特定的测试完全卡住了,几分钟后控制台中抛出一个错误:

QueryFailedError: ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction

试图查明问题,让我找到了我们在

afterEach
上运行的一个函数,该函数“破坏”了数据库。它最初运行:

await queryRunner.query('DELETE FROM Table1');
await queryRunner.query('DELETE FROM Table2');
...

在我将其从

queryRunner
更改为
queryBuilder
后,错误和“死锁”最初得到修复:

await queryBuilder.delete().from('Table1').execute();
...

这是在与

SHOW PROCESSLIST;
SHOW ENGINE InnoDB STATUS;
坐立不安并尝试弄清楚发生了什么之后完成的。我还将事务隔离更改为 READ-COMMITTED 但无济于事。除了将其从
queryRunner
更改为
queryBuilder
之外,没有什么真正有效的。

这工作了一段时间,但现在测试似乎再次陷入困境(测试没有改变,但正在测试的代码)。现在,测试挂起后,我们收到此错误:

Error: Pool is closed
。之后测试被“发布”,所有测试都开始一一失败。

我们发现这是导致测试卡住的事件序列:

1. open a transaction with queryRunner
2. perform a read query
3. then perform a write
4. commit the transaction and release the queryRunner
5. delete the DB
6. perform a write - deadlock

此外,我们还注意到以下几点:

如果我们确保只使用 queryRunner 进行更新,而不使用 对于查询,则不会发生死锁。

更改代码,以便我们首先使用常规连接进行所有读取查询 对象(不是 queryRunner)只有那时如果我们连接

queryRunner
并进行所有写入 - 那么死锁就不会发生。

有人对可能发生的事情有任何见解吗? queryRunner 是否存在一些不稳定因素或者我们在使用它时需要考虑的一些具体事项?

谢谢!

mysql node.js typeorm
2个回答
11
投票

我遇到了同样的问题,我的问题是未处理的异步/等待。 检查某些 Promise 对象是否未处理。 如果使用async关键字,则必须使用await关键字处理所有异步函数。 另外不要忘记调用

jest
done 方法。


0
投票

在我的例子中,我只使用了

mysql2
而没有承诺(因此没有使用`mysql2/promise),我现在很后悔。我应该从第一天起就使用 Promise。

无论如何,很可能你确实有一个引发条件,即在 Jest 完成时你的数据库仍然打开(而不是关闭)。

例如,如果您有一个正在执行快速

getConnection
方法的测试用例。喜欢:

this.dbPool.getConnection((err, conn) => {
  if (err) {
    debug('server')('There is a database connection problem, error: ' + err.message + ' (code: ' + err.errno + ').')
    console.error(err)
  }
  if (conn) {
    conn.release()
  }
})

这会导致问题。在您的所有(单元)测试完成并且 Jest 可以完成之后,同时此回调方法仍在运行。因此,我提到最好转向

mysql2/promise
并在生产代码中使用
await
。诗。 Jest 测试代码中的承诺/回调也是如此。

© www.soinside.com 2019 - 2024. All rights reserved.