【发布时间】:2020-12-28 20:00:22
【问题描述】:
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 是否存在一些不稳定因素或我们在使用它时需要考虑的一些特定事项?
谢谢!
【问题讨论】: