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

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

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

该表有406,733行。


当前回答

查看一下您的数据库是否进行了微调,特别是事务隔离。增加innodb_lock_wait_timeout变量不是一个好主意。

检查MySQL中的数据库事务隔离级别:

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ       | REPEATABLE-READ | REPEATABLE-READ        |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)

您可以通过更改隔离级别来获得改进。使用类似oracle的READ COMMITTED而不是REPEATABLE READ。REPEATABLE READ是InnoDB的默认值。

mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

此外,仅在必要时尝试使用SELECT FOR UPDATE。

其他回答

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

细节:

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

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

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

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

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

在我的实例中,我正在运行一个异常查询来修复数据。如果你在你的查询中锁定了表,那么你将不必处理锁定超时:

LOCK TABLES `customer` WRITE;
update customer set account_import_id = 1;
UNLOCK TABLES;

这对于正常使用可能不是一个好主意。

更多信息请参见:MySQL 8.0参考手册

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

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

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

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

Mysql > set autocommit=0;

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

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

Mysql > set autocommit=1;

您正在使用一个事务;Autocommit不会禁用事务,它只是让它们在语句的末尾自动提交。

可能发生的情况是,其他一些线程在某个记录上持有记录锁(您正在更新表中的每个记录!)太长时间,而您的线程正在超时。或者在一个事务中对同一行运行多个(2+)UPDATE查询。

可以通过发出命令查看事件的更多详细信息

SHOW ENGINE INNODB STATUS

事件发生后(在SQL编辑器中)。理想情况下,在安静的测试机上执行此操作。