处理innoDB死锁

时间:2011-03-15 15:19:37

标签: php mysql innodb deadlock

我在InnoDB表上遇到Deadlock found when trying to get lock; try restarting transaction错误。这是查询:

UPDATE views 
SET visit_cnt = visit_cnt + 1 
WHERE visit_day = DATE(NOW()) 
AND article_id = '4838'

此查询还通过ON UPDATE触发器触发此操作:

UPDATE articles 
SET views = views + 1 
WHERE id = NEW.article.id

以下是我尝试修复它的方法:

$attempts_left = 5;
do
{
    mysql_query ($query);

    // if we found a deadlock, we will try this query 4 more times   
    if (mysql_errno () == 1213) { // 1213 - deadlock error
        $deadlocked = true;
        $attempts_left --;
    }
    else{
        $deadlocked = false;
    }
}
while($deadlocked && $attempts_left > 0);

我的问题:这是处理死锁的唯一方法吗?我的意思是这很丑陋,无论如何都会不时发生死锁。有没有推荐的修复死锁的方法?

3 个答案:

答案 0 :(得分:2)

以下是有关处理InnoDB deadlocks的详细文档。

PS:我没有更多要添加,所以只是给了你链接。

答案 1 :(得分:2)

您可能必须使用事务隔离/ MVCC功能玩一些游戏

选项1)您可能希望在开始提交块中包围查询

BEGIN;

UPDATE views
SET visit_cnt = visit_cnt + 1
WHERE visit_day = DATE(NOW())
AND article_id = '4838';

< Any actions in the trigger would be part of the transaction >

COMMIT;

选项2)您可能希望禁用会话的自动提交

SET autocommit = 0;

选项3)在启动查询以暴露脏读

之前更改事务隔离

这是一个延伸!!!

SET tx_isolation = READ_COMMITTED;

SET tx_isolation = READ_UNCOMMITTED;

尝试一下,让我们都知道!!!

答案 2 :(得分:2)

这是正确的方式,正如文档所述:

  

通常,您必须编写应用程序,以便在由于死锁而回滚时,它们始终准备重新发出事务。

如果要减少死锁的发生,必须向我们展示表DDL和索引。