两次锁定相同行的 MySQL 5.6 死锁?

标签 mysql deadlock database-deadlocks percona

我看到 MySQL 5.6 出现死锁,因为似乎试图锁定同一行两次。

在下面的代码片段中,id = (11, 12, 13, 14, 15) 的行已经有一个锁。当另一个事务试图获取这些锁时,MySQL 使事务检测到死锁失败。

我的解读正确吗?如果是这样,MySQL 5.6 中有什么可以克服这个问题的吗? FWIW,5.5 中的相同代码运行良好(数百次迭代)。

------------------------
LATEST DETECTED DEADLOCK
------------------------
2013-07-25 11:46:05 13a515000
*** (1) TRANSACTION:
TRANSACTION 2333130, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 31 lock struct(s), heap size 6960, 6 row lock(s)
MySQL thread id 2944, OS thread handle 0x13ae88000, query id 184533 localhost 127.0.0.1 root Sending data
SELECT id FROM table_meta WHERE id IN (11, 12, 13, 14, 15) FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 128954 page no 5 n bits 176 index `PRIMARY` of table `db_test1`.`table_meta` trx id 2333130 lock_mode X locks rec but not gap waiting
*** (2) TRANSACTION:
TRANSACTION 2333255, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1248, 11 row lock(s)
MySQL thread id 2927, OS thread handle 0x13a515000, query id 186769 localhost 127.0.0.1 root Sending data
SELECT id FROM table_meta WHERE id IN (1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15) FOR UPDATE
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 128954 page no 5 n bits 176 index `PRIMARY` of table `db_test1`.`table_meta` trx id 2333255 lock_mode X locks rec but not gap
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 128954 page no 5 n bits 176 index `PRIMARY` of table `db_test1`.`table_meta` trx id 2333255 lock_mode X locks rec but not gap waiting
*** WE ROLL BACK TRANSACTION (2)

最佳答案

当然,

刚刚在 5.6 中为我的一位客户整理了这个。实际上这些是 innodb 死锁,select 之后是导致死锁的更新。请更新查询并进行单独更新。

你有从属服务器吗?

还有一件事需要考虑——INSERT … SELECT 也在锁定模式下执行读取,因此部分绕过版本控制并检索最新提交的行。所以即使你在 REPEATABLE-READ 模式下操作,这个操作也会在 READ-COMMITTED 模式下执行 模式,与纯 SELECT 给出的结果相比,可能给出不同的结果。顺便说一下,这也适用于 SELECT .. LOCK IN SHARE MODE 和 SELECT … FOR UPDATE。 我的一个问题是,如果我不使用复制并禁用我的二进制日志怎么办?如果不使用复制,您可以启用 innodb_locks_unsafe_for_binlog 选项,这将放松 Innodb 在语句执行时设置的锁,这通常会提供更好的并发性。然而,顾名思义,它会使锁在复制和时间点恢复之前变得不安全,因此请谨慎使用 innodb_locks_unsafe_for_binlog 选项。

关于两次锁定相同行的 MySQL 5.6 死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17892184/

相关文章:

mysql - Laravel 的 ORM 如何指定数据的排序值?

java - 为什么这不会导致死锁

c++ - 为什么我的 DCOM 客户端会锁定对 SendMessage 的调用?

mysql - 如何并行写入 MySQL 中的同一行?

php - while 中的变量数组

Mysql查询从表中获取客户数量

mysql - 如何避免mysql死锁?

mysql - 使用 SELECT/LIMIT 1/FOR UPDATE 时避免死锁的最佳方法是什么?

MySQL获取不同时间跨度和组的结果

multithreading - 如何解除阻塞等待信号量的所有线程?