php - 避免 MySQL 'Deadlock found when trying to get lock; try restarting transaction'

标签 php mysql deadlock database-deadlocks

我有时会收到 mysql 死锁错误:

'Deadlock found when trying to get lock; try restarting transaction'

我有一个队列表,其中多个 php 进程同时运行,从表中选择行。但是,对于每个进程,我希望它在每次提取时都抓取一批唯一的行,这样我就不会选择任何重叠的行。

所以我运行这个查询:(这是我遇到死锁错误的查询)

    $this->db->query("START TRANSACTION;");

    $sql = "   SELECT   mailer_queue_id
                FROM    mailer_queues
                WHERE   process_id IS NULL
                LIMIT   250 
                FOR UPDATE;";
    ...


    $sql = "UPDATE  mailer_queues
            SET     process_id = 33044,
                    status = 'COMPLETED'
            WHERE   mailer_queue_id 
                IN  (1,2,3...);";

    ...

    if($this->db->affected_rows() > 0) {
        $this->db->query("COMMIT;");       
    } else{
        $this->db->query("ROLLBACK;");      
    }

我也是:

同时向表中插入行(没有事务/锁)

同时更新表中的行(没有事务/锁)

同时从表中删除行(没有事务/锁)

同样,我的更新和删除仅更新和删除分配了 process_id 的行...以及我执行“SELECT rows ... FOR UPDATE”事务的位置 process_id = null。理论上它们不应该重叠。

我想知道是否有适当的方法来避免这些死锁?

是否会发生死锁,因为一个事务在选择/更新表时锁定表的时间太长,而另一个进程正在尝试执行相同的事务并且只是超时?

非常感谢任何帮助

最佳答案

当两个或多个进程请求锁定时,被锁定的资源重叠,但发生顺序不同,因此每个进程都在等待另一个进程锁定的资源,而另一个进程正在等待,就会发生死锁对于原始进程已打开的锁。

在现实世界中,考虑一个建筑工地:您有一把 Screwdriver 和一个螺丝。需要两个 worker 来拧螺丝。 worker #1 拿着 Screwdriver , worker #2 拿着螺丝。 worker #1 也去拿螺丝,但不能,因为它被 worker #2 拿着。 worker #2 需要 Screwdriver ,但拿不到它,因为 worker #1 拿着它。所以现在他们陷入了僵局,无法继续进行,因为他们已经获得了所需的 2 种资源中的一种,而且他们都不会客气地“退后一步”。

鉴于您发生了事务外更改,您的一个(或多个)更新/删除可能会与您在事务中保留的锁定区域重叠。

关于php - 避免 MySQL 'Deadlock found when trying to get lock; try restarting transaction',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8039173/

相关文章:

PHP 将 MySQL 导出为 CSV - 结果显示为 HTML

php - 将 13 小时添加到时间戳

php - 极慢的 MySQL 查询

c# - 如何优化这个表达式? LINQ?

c# - 如何解决这个僵局呢?

objective-c - existingObjectWithID 死锁与 NSPrivateQueueConcurrencyType

php JQuery ajax 实现

sql - Django/SQL : what's most efficient, 更多列或更多表?

mysql - hibernate和mysql分区

从另一个 python 脚本调用 python 脚本时,Python 日志记录挂起