修复“超过锁定等待超时;尝试重新启动事务”为“卡住”的Mysql表?


131

从脚本中,我将这样的查询发送了数千次到本地数据库:

update some_table set some_column = some_value

我忘了添加where部分,因此同一列被设置为表中所有行的相同值,并且完成了数千次,并且对该列进行了索引,因此相应的索引可能被更新了太多次。

我注意到出了点问题,因为花了太长时间,所以我杀死了脚本。从那以后,我什至重新启动了计算机,但是表中有些东西卡住了,因为简单的查询需要很长时间才能运行,当我尝试删除相关的索引时,它失败并显示以下消息:

Lock wait timeout exceeded; try restarting transaction

这是一个innodb表,因此卡住的事务可能是隐式的。如何修复该表并从中删除卡住的事务?


3
输出是SHOW FULL PROCESSLIST什么?
沃尔夫(Wolph)2010年

它仅显示SHOW FULL PROCESSLIST命令,其他仅显示。这是一个本地开发数据库。什么都没有运行。当我尝试从那里删除索引时,在命令行上收到“锁定等待..”错误消息。
汤姆(Tom)2010年

在这种情况下,您可能在不同的事务中创建2个单独的连接,这些连接必须彼此等待。
Wolph

之后,我没有创建任何交易。我杀死了脚本,重新启动了计算机,并从命令行登录以查看四周。除了mysql命令行客户端外,没有其他使用数据库的数据库,因此表中一定有卡住的东西。
汤姆(Tom),2010年

Answers:


143

我遇到了类似的问题,并通过检查正在运行的线程解决了该问题。要查看正在运行的线程,请在mysql命令行界面中使用以下命令:

SHOW PROCESSLIST;

如果您无权访问mysql命令行界面,也可以从phpMyAdmin发送它。
这将显示具有相应ID和执行时间的线程列表,因此您可以杀死执行时间过多的线程。在phpMyAdmin中,您将拥有一个用于通过使用KILL停止线程的按钮,如果您使用的是命令行界面,则只需使用KILL命令后跟线程ID,如以下示例所示:

KILL 115;

这将终止相应线程的连接。


36
做记录!有人在与此问题相关的众多SO线程之一中提到了这一点:有时,锁定表的进程在进程列表中显示为处于休眠状态!我一直在扯头发,直到杀死所有在数据库中打开的线程,无论它们是否在睡觉。最终,该表解锁了,并让更新查询运行。评论者提到了诸如“有时MySQL线程锁定表,然后在等待与MySQL无关的事件时休眠”之类的内容。
Eric L.

(我说我自己的答案来充实这个想法片段在这里,在一个相关的问题)
埃里克·L.

这对我有帮助。我有几个由PHPStorm数据库管理/查询功能创建的睡眠线程。
Ejaz

大!自5个小时以来,我进行了一个隐藏的过程,可以识别并杀死它。
Aldo Paradiso

2
这不是解决方案,仅是在受感染的伤口上进行导管包扎是一种解决方案。您没有解决根本的根本问题。
user2914191

55

您可以使用以下命令检查当前正在运行的事务

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

您的交易应该是第一笔交易之一,因为它是列表中最古老的交易。现在,只需从中获取值trx_mysql_thread_id并发送KILL命令即可:

KILL 1234;

如果不确定是哪个事务,请经常重复第一个查询,看看哪些事务持续存在。


您可能需要使用root帐户来运行该SQL,以查看实际上哪个事务在阻止其他人访问表
tom10271

40

检查InnoDB状态以获取锁

SHOW ENGINE InnoDB STATUS;

检查MySQL打开表

SHOW OPEN TABLES WHERE In_use > 0;

检查待处理的InnoDB事务

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

检查锁依赖性-什么阻止了什么

SELECT * FROM `information_schema`.`innodb_locks`;

在调查了上面的结果之后,您应该能够看到锁定了什么。

造成此问题的根本原因也可能在您的代码中-如果您使用像Hibernate这样的JPA,请检查相关功能,尤其是注释的相关功能。

例如,如所描述这里,下面标注的滥用可能会导致数据库锁:

@Transactional(propagation = Propagation.REQUIRES_NEW) 

4
非常感谢!运行SELECT * FROM information_schema.innodb_trx t JOIN information_schema.processlist p ON t.trx_mysql_thread_id = p.id揭示了罪魁祸首:锁定线程来自我的IP地址……我忘了关闭在交易过程中留下的调试控制台……
Elias Strehle

40

当我的数据库大小增加并且我正在做很多事务时,这开始发生在我身上。

事实是,可能有某种方法可以优化您的查询或数据库,但是请尝试使用这两个查询来解决此问题。

运行这个:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

然后这个:

SET innodb_lock_wait_timeout = 5000; 


1
我正在运行一个非常繁忙的11GB数据库。这是唯一对我有用的东西,谢谢!
dongemus

如果您不想永远将其保留在那里,只需记住将其更改为以前的值即可。
里卡多·马丁斯

这意味着我的某些用户的体验会更慢,对吗?
阿诺德·罗阿

9

建立事务的连接时,在执行事务之前,您将获得一个锁。如果无法获取锁,则尝试一段时间。如果仍然无法获得锁定,则抛出超出锁定等待时间的错误。为什么无法获取锁的原因是您没有关闭连接。因此,当您第二次尝试获取锁时,由于先前的连接仍未关闭并持有该锁,因此您将无法获得该锁。

解决方案: 关闭连接或setAutoCommit(true)(根据您的设计)释放锁。


7

重新启动MySQL,它工作正常。

但是要注意,如果这样的查询卡住了,那么某个地方就会出现问题:

  • 在您的查询中(放错字符,笛卡尔乘积,...)
  • 大量记录需要编辑
  • 复杂的联接或测试(MD5,子字符串LIKE %...%等)
  • 数据结构问题
  • 外键模型(链/环锁定)
  • 索引错误的数据

就像@syedrakib所说的那样,它可以工作,但这并不是生产的长期解决方案。

当心:重新启动会影响状态不一致的数据。

另外,您可以检查MySQL如何使用EXPLAIN关键字处理查询,并查看那里是否有可能加快查询速度(索引,复杂测试等)。


谢谢。您没有直接解决我的问题,但是我遭受了表锁的困扰,这太糟糕了。这是整个互联网上唯一的帖子,这使我想到了检查外键的想法。因此,我发现主键的键是11,外键的键是10。我不知道这怎么可能发生以及为什么以前一切正常。
EscapeNetscape

@EscapeNetscape不客气,我很高兴这个小回答对您有所帮助:)
Benj

3

mysql中的Goto进程。

因此可以看到仍有任务在工作。

终止特定进程或等待进程完成。


7
它解决了这个问题。但这不能成为LIVE生产服务器的解决方案……我们如何输出这种死锁处理?或者我们如何避免这种僵局的发生?
拉基布2012年

1
好吧,碰巧即使使用格式正确且完全转义的mysql查询(甚至不是由开发人员而是由框架的active-records接口编写的),锁定等待超时问题仍然可能发生。所以我在这里没有写正确的mysql查询是一个因素。
拉基布2012年

1

我在“更新”语句中遇到了同样的问题。我的解决方案是简单地通过表中phpMyAdmin中可用的操作运行。我对表进行了优化,刷新和碎片整理(不按此顺序)。无需删除表并从备份中将其还原。:)


1
它可能会解决问题。但是,每次发生此类错误时都必须执行此操作,这不能成为LIVE生产服务器的解决方案……我们如何输出此死锁处理?或者我们如何避免这种僵局的发生?
拉基布2012年

1

我遇到过同样的问题。我认为这是SQL的死锁问题。您可以从任务管理器强制关闭SQL进程。如果仍不能解决问题,请重新启动计算机。您无需删除表并重新加载数据。


它解决了这个问题。但这不能成为LIVE生产服务器的解决方案……我们如何输出这种死锁处理?或者我们如何避免这种僵局的发生?
拉基布2012年

重新启动Apache及其服务(或至少是MySQL),无需重新启动
Amjo

1

尝试删除某些记录集时(使用MS Access 2007,并通过ODBC连接到Web服务器上的MySQL时出现了此问题)。通常,我会从MySQL删除某些记录,然后用更新的记录替换(级联删除一些相关记录,这简化了删除所有相关记录的操作,从而删除了一条记录)。

我尝试通过phpMyAdmin中的表进行操作(优化,刷新等),但是在尝试刷新时,我需要获得RELOAD错误的权限。由于我的数据库位于Web服务器上,因此无法重新启动数据库。无法从备份还原。

我尝试在网络上的cPanel mySQL访问中针对这组记录运行删除查询。得到了同样的错误信息。

我的解决方案:我使用了Sun(Oracle)的免费MySQL查询浏览器(我以前安装在我的计算机上),并在那里运行了删除查询。它立即起作用,问题解决了。然后,我能够使用ODBC Access to MySQL连接再次使用Access脚本执行该功能。


-2

解决它。

确保在查询中没有不匹配的数据类型插入。我在尝试“用户浏览器代理数据”时VARCHAR(255)遇到了问题,但是将此锁更改为TEXT(255)它已修复。

因此最有可能是数据类型不匹配。


-151

我通过删除表并从备份中恢复来解决了这个问题。


20
顺便说一句,此答案赢得了SO的有史以来最低得分的“已接受”答案的荣誉🏆–
ashleedawg

1
这也是总体上得分最低的答案
Bob Kerman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.