我正在运行以下MySQL UPDATE语句:

mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

我没有使用事务,为什么会得到这个错误?我甚至尝试重新启动我的MySQL服务器,它没有帮助。

该表有406,733行。


当前回答

迟到的派对(像往常一样),但我的问题是我写了一些糟糕的SQL(作为一个新手)和几个进程对记录有一个锁<-不确定适当的措辞。我最终不得不:SHOW PROCESSLIST,然后使用kill <id>杀死id

其他回答

在我们的案例中,这个问题与锁本身没有太大关系。

问题是我们的一个应用程序端点需要并行打开2个连接来处理单个请求。

例子:

打开第一个连接 开始事务1 锁定表1中的一行 打开第二个连接 启动事务2 锁定表2中的一行 提交事务2 释放第二个连接 提交事务1 释放第一个连接

我们的应用程序的连接池限制为10个连接。

不幸的是,在负载下,一旦所有连接都被使用,应用程序就停止工作,我们开始遇到这个问题。 我们有几个请求需要打开第二个连接才能完成,但由于连接池的限制而无法完成。因此,这些请求长时间保持对table1行的锁定,导致接下来需要锁定同一行的请求抛出此错误。

解决方案:

在短期内,我们通过增加连接池限制修补了这个问题。 从长远来看,我们删除了所有嵌套连接,以完全解决问题。

小贴士:

您可以通过尝试将连接池限制降低到1并测试应用程序来轻松检查是否有嵌套连接。

您是否可以更新这个表中的任何其他记录,或者这个表是否被大量使用?我想的是,当它试图获得一个锁,它需要更新这条记录时,设置的超时已经超时。你可以延长时间,这可能会有所帮助。

行数并不大……如果account_import_id不是主键,则在它上创建一个索引。

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);

我们昨天遇到了这个问题,在仔细研究了这里的每一个建议的解决方案,以及其他答案/论坛的其他几个解决方案后,我们最终在意识到实际问题时解决了它。

由于一些糟糕的计划,我们的数据库存储在一个挂载的卷上,该卷也接收我们的常规自动备份。该容量已达到最大容量。

一旦我们清理了一些空间并重新启动,这个错误就被解决了。

注意,我们也手动终止了几个进程:kill <process_id>;所以这仍然是必要的。

总的来说,我们的结论是,令人难以置信的是,我们的日志或警告都没有直接提到磁盘空间不足,但这似乎确实是根本原因。

我有2个Doctrine DBAL连接,其中一个是非事务性的(用于重要日志),它们旨在并行运行,而不是相互依赖。

CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery()
)

我的集成测试被包装到事务中,以便在每次测试后进行数据回滚。

beginTransaction()
CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery() // CONFLICT
)
rollBack()

我的解决方案是在这些测试中禁用包装事务,并以另一种方式重置db数据。