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

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

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

该表有406,733行。


当前回答

mysql->SHOW PROCESSLIST;
kill xxxx; 

然后杀了睡着的那个。对我来说是2156。

其他回答

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

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

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

SHOW ENGINE INNODB STATUS

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

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

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

例子:

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

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

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

解决方案:

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

小贴士:

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

某些东西阻塞了查询的执行。很可能是另一个查询更新、插入或删除查询中的某个表。你必须找出那是什么:

SHOW PROCESSLIST;

一旦你找到阻塞进程,找到它的id并运行:

KILL {id};

重新运行初始查询。

完全符合MarkR的说法。自动提交使每个语句成为一个语句事务。

SHOW ENGINE INNODB STATUS会给你一些死锁原因的线索。还要仔细查看慢速查询日志,看看还有什么正在查询表,并尝试删除正在执行满表罐操作的任何内容。行级锁定工作得很好,但当您试图锁定所有行的时候就不行了!

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

Innodb_lock_wait_timeout = 50

innodb_rollback_on_timeout = ON

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

显示全局变量:innodb_rollback_on_timeout