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

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

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

该表有406,733行。


当前回答

我来自谷歌,我只是想添加对我有效的解决方案。我的问题是,我试图删除一个大表的记录,它有很多FK级联,所以我得到了与OP相同的错误。

我禁用了自动提交,然后它只在SQL语句的末尾添加COMMIT。据我所知,这将逐位释放缓冲区,而不是在命令结束时等待。

为了保持OP的示例,这应该是有效的:

Mysql > set autocommit=0;

Mysql > update customer set account_import_id = 1;提交;

不要忘记重新激活自动提交,如果你想让MySQL配置和以前一样。

Mysql > set autocommit=1;

其他回答

尝试更新以下两个参数,因为它们必须具有默认值。

Innodb_lock_wait_timeout = 50

innodb_rollback_on_timeout = ON

要检查参数值,可以使用下面的SQL语句。

显示全局变量:innodb_rollback_on_timeout

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

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);

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

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

例子:

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

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

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

解决方案:

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

小贴士:

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

如果您刚刚终止了一个大型查询,那么回滚将需要时间。如果在已终止查询回滚之前发出另一个查询,则可能会得到一个锁定超时错误。这就是我的遭遇。解决办法就是再等一会儿。

细节:

我发出了一个DELETE查询,从大约100万行中删除大约90万行。

我错误地运行了这个(只删除了10%的行): 删除MOD(id,10) = 0的表

而不是这样(删除90%的行): 删除表中MOD(id,10) != 0

我想要删除90%的行,而不是10%。因此,我在MySQL命令行中终止了进程,因为我知道它会回滚到目前为止删除的所有行。

然后我立即运行了正确的命令,并在不久之后得到了一个锁定超时超过错误。我意识到锁实际上可能是被杀死的查询的回滚仍然在后台发生。所以我等了几秒钟,重新运行了查询。

确保数据库表使用InnoDB存储引擎和READ-COMMITTED事务隔离级别。

你可以通过SELECT @@GLOBAL来检查它。tx_isolation @@tx_isolation;在mysql控制台。

如果没有设置为READ-COMMITTED,则必须设置它。在设置之前,请确保您在mysql中拥有SUPER权限。

你可以从http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html上获得帮助。

通过设置这个,我认为你的问题会得到解决。


您可能还希望检查是否试图同时在两个进程中更新此文件。用户(@tala)在这种情况下遇到了类似的错误消息,可能需要仔细检查…