我的服务器常常挂起,MySQL会显示以下进程列表:
流程1: 时间:24 用户:工人 状态:已锁定 信息:LOCK TABLES tRatings WRITE,tUsers WRITE
流程2: 时间:24 用户:工人 状态:正在更新 信息:UPDATE tUsers SET fGender ='1'WERE fID = 232049
流程3: 时间:24 用户:工人 状态:已锁定 信息:LOCK TABLES tClients READ,tUsers uA READ,tUsers aB READ,tNexts READ
所有表都是InnoDB,我使用显式的LOCK TABLES来防止InnoDB死锁发生。
我的问题是我根本不明白这里出了什么问题!可以请有人解释一下,为什么他只是在接下来的操作上没有表现?相反,所有进程都不会(在此示例中)24秒内无效。
谢谢,
乔
答案 0 :(得分:1)
我的服务器常常挂起[...]所有表都是InnoDB,我使用显式
LOCK TABLES
来阻止InnoDB死锁发生。
你没有阻止死锁。您正在阻止自动死锁检测。让我解释一下:
当您有两个(或更多)进程争用同一资源但以不同顺序竞争时,会发生死锁。例如:
当在事务中发生这种情况时,数据库引擎可以检测到正在发生死锁并终止其中一个负责连接,允许另一个继续。
当您使用LOCK TABLES
时,您不允许数据库引擎执行死锁检测,因此死锁会一直存在,直到您手动进入并终止其中一个死锁进程。更糟糕的是,LOCK TABLES
也可以防止读取,并且可以轻松地使整个应用程序戛然而止。
停止使用LOCK TABLES
。
开始在需要事务完整性的代码区域中使用事务。 不在任何地方添加它们。
如果您收到死锁,很可能您有不同的代码路径,以不同的顺序对相关的数据位执行相关操作,或您没有在正确的位置使用事务。
还有其他选择。一种是设计数据库例程,以便它们检测何时发生死锁,并开始重新播放所需的事件,以便再次进行。换句话说,您将回滚,重新启动事务,并尝试再次执行相同的操作。有可能导致死锁的条件已经解决,所以你可能没问题。不幸的是,死锁中涉及的其他进程可能已经改变了您正在使用的一些数据,因此重新启动可能有点复杂。
最后,另一种选择是根本不使用事务或锁。你不是在处理钱,是吗?看起来你正在处理用户和评级。这是非常简单的数据。没有人会关心或注意到当前评级是否缺少在有人做了导致重新计算评级的事情之后立即注册的投票。