首页 文章

InnoDB何时超时而不是报告死锁?

提问于
浏览
3

我有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 回答

  • 3

    一个提示是你可以使用 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变量的手册:

    InnoDB事务在放弃之前可能等待行锁定的超时时间(以秒为单位) . 默认值为50秒 . 尝试访问由另一个InnoDB事务锁定的行的事务将在发出以下错误之前最多挂起这么多秒:ERROR 1205(HY000):超出锁定等待超时;尝试重新启动事务发生锁定等待超时时,不执行当前语句 . 当前事务未回滚 . (直到MySQL 5.0.13 InnoDB在发生锁等待超时时回滚整个事务 .

    例如,当两个进程都需要锁定由另一个进程锁定的行时,就会发生死锁,并且没有任何等待时间可以解决冲突 .

  • 1

    我设法重现并诊断问题 . 这是涉及MyISAM和InnoDB的僵局 . 它似乎是事务性InnoDB行锁定和非事务性MyISAM表锁定之间的交互 . 我提交了一个错误:http://bugs.mysql.com/bug.php?id=57118 . 无论如何,我相信我最初问题的答案是,InnoDB应该始终检测死锁,除非MySQL中存在错误 . ;-)

相关问题