2010-06-19 87 views
1

很多时候我的服务器挂起和MySQL显示如下进程列表:奇怪锁问题在MySQL

流程1: 时间:24 用户:工人 状态:锁定 信息:LOCK TABLES tRatings WRITE,tUsers WRITE

过程2: 时间:24 用户:工人 状态:更新 信息:UPDATE SET tUsers fGender = '1' WHERE FID = 232049

流程3: 时间:24 用户:工人 状态:锁定 信息:LOCK TABLES tClients READ,tUsers微安READ,tUsers AB READ,tNexts阅读

所有的表InnoDB和我使用显式LOCK TABLES来防止发生InnoDB死锁。

我的问题是,我根本不明白这里出了什么问题!可以请别人解释一下,为什么他只是在对方之后没有进行手术?相反,对于(在本例中)24秒,所有进程都不做任何事情。

感谢,

+0

我假设你使用php + pdo? – 2010-06-19 11:00:19

回答

1

很多时候我的服务器挂起[...]所有的表InnoDB和我使用显式LOCK TABLES防止死锁的InnoDB的发生。

你没有防止死锁。您正在阻止自动死锁检测。让我解释一下:

当两个(或多个)进程争用相同的资源但按不同的顺序时,会发生死锁。例如:

  • 进程A需要资源2,则资源1.在成功抢夺资源2 ...
  • 但后来有一个上下文切换!进程B出现并获取资源1,然后尝试获取资源2,但不能因为A已将其保留(无论是在事务中还是在锁中),所以B被搁置。
  • 上下文切换! A再次出现并试图获取资源1,但它由进程B保存。
  • A现在正在等待B,B现在正在等待A.这是一个死锁。

在事务内部发生这种情况时,数据库引擎可以检测到发生了死锁并终止其中一个负责连接,从而允许另一个连接继续。

当您使用LOCK TABLES时,您不允许数据库引擎执行死锁检测,因此死锁会一直存在,直到您手动出现并杀死其中一个死锁进程。更糟糕的是,LOCK TABLES也可以防止读取,并且可以很容易地将您的整个应用程序暂停。

停止使用LOCK TABLES

在需要事务完整性的代码区域开始使用事务。做不是无处不在。

如果您正在接收死锁,您可能有不同的代码路径,以不同的顺序执行相关数据位的相关操作,您没有在正确的位置使用事务。

还有其他的选择。一种是设计你的数据库例程,以便它们检测死锁发生的时间,并开始重新播放所需的事件,以便再次进行。换句话说,你会回滚,重新启动交易,并尝试再次做同样的事情。有可能当时导致僵局的情况已经解决,所以你可能会好起来的。不幸的是,死锁中涉及的其他进程可能会改变您正在使用的一些数据,因此在复杂的一方重新启动可能会有点麻烦。

最后,另一种选择是根本不使用事务或锁。你不是在处理金钱,是吗?看起来你正在处理用户和评级。这是相当简单的数据。没有人会关心或注意,如果当前的评级缺少在某人做出导致评级被重新计算的事情之后立即注册的投票。