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

6
我们在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 时是否存在某些不稳定性或需要考虑的特殊事项?
谢谢!
1个回答

10

我也遇到了同样的问题,我的问题是未处理的async/await。 请检查是否有一些promise对象没有被处理。 如果您使用了async关键字,则必须使用await关键字处理所有异步函数。 同时,不要忘记调用jest的done方法。


1
他的问题与数据库锁有关,所以我不认为它与async/await有任何关系。 - Sagi Rika
1
我曾经遇到过同样的问题,错误提示为“连接池已关闭”,原因是我忘记了使用await关键字。因此,在函数执行实际结束之前,连接就被关闭了。 - WhiteAngel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接