我有MySQL的“锁定等待超时超时”错误,我无法重现或诊断 . 我确定它是死锁(相反于一个事务 grab 一个锁然后翻转它的拇指),因为我的日志显示另一个进程同时启动,也挂起,然后在第一次超时时继续 . 但通常情况下,InnoDB会在没有超时的情况下检测到死锁 . 所以我试图理解为什么没有检测到这种死锁 .
两个事务都使用隔离级别可序列化 . (我对此隔离级别的InnoDB锁定有一个公平的理解 . )在事务中使用了一个非InnoDB(MyISAM)表,我将其插入并更新 . 但是,我不明白它是如何参与死锁的,因为我相信MyISAM只是在插入和更新期间进行表锁定(然后立即释放它,因为MyISAM不是事务性的),因此没有其他锁定桌锁是举行的 .
所以我确信死锁只涉及InnoDB表,这让我回到了为什么没有检测到它的问题 . MySQL文档(http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlock-detection.html)暗示死锁检测几乎总是有效 . 我在搜索时发现的问题涉及显式“锁表”,“alter table”和“insert delayed”等问题 . 我没有做任何这些事情,只是插入,更新和选择(我的一些选择是“更新”) .
我尝试通过创建一个MyISAM表和几个InnoDB表并在MyISAM中执行各种插入和更新序列以及在InnoDB中“选择更新”来重现 . 但每次我发生僵局,InnoDB立即报告 . 我无法重现超时 .
诊断这个的任何其他技巧?我正在使用mysql 5.1.49 .
2 回答
一个提示是你可以使用
SHOW INNODB STATUS
,你猜对了,显示了InnoDB引擎的状态 .它返回的信息(一大块文本)包括当前表锁的信息,以及最后检测到的死锁(在 Headers
"LATEST DETECTED DEADLOCK"
下),所以这个技巧不会发生 .mysqladmin debug
还可以打印有用的锁定调试信息 .第三个技巧是创建一个名为
innodb_lock_monitor
的神奇命名表,如http://dev.mysql.com/doc/refman/5.1/en/innodb-monitors.html所述,它提供了更详细的锁定调试 .HTH!
更新:
它可能没有检测到死锁,因为它实际上并不是死锁,但更有可能是一个进程正在等待另一个进程锁定的行上的行锁定 . 从innodb_lock_wait_timeout变量的手册:
例如,当两个进程都需要锁定由另一个进程锁定的行时,就会发生死锁,并且没有任何等待时间可以解决冲突 .
我设法重现并诊断问题 . 这是涉及MyISAM和InnoDB的僵局 . 它似乎是事务性InnoDB行锁定和非事务性MyISAM表锁定之间的交互 . 我提交了一个错误:http://bugs.mysql.com/bug.php?id=57118 . 无论如何,我相信我最初问题的答案是,InnoDB应该始终检测死锁,除非MySQL中存在错误 . ;-)