10

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

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

我对此的解读是否正确?如果是这样,MySQL 5.6 中有什么可以解决这个问题吗?FWIW,5.5 中的相同代码工作得很好(数百次迭代)。

----------------------
最新检测到的死锁
----------------------
2013-07-25 11:46:05 13a515000
*** (1) 交易:
TRANSACTION 2333130,ACTIVE 0 秒获取行
mysql 表正在使用 1,锁定 1
LOCK WAIT 31 个锁结构,堆大小 6960,6 行锁
MySQL 线程 id 2944,OS 线程句柄 0x13ae88000,查询 id 184533 localhost 127.0.0.1 root 发送数据
SELECT id FROM table_meta WHERE id IN (11, 12, 13, 14, 15) FOR UPDATE
*** (1) 等待授予此锁定:
RECORD LOCKS 空间 id 128954 页号 5 n 位 176 表 `db_test1`.`table_meta` 的索引 `PRIMARY` trx id 2333130 lock_mode X 锁定记录但不锁定间隙等待
*** (2) 交易:
TRANSACTION 2333255,ACTIVE 0 秒开始索引读取
mysql 表正在使用 1,锁定 1
3 个锁结构,堆大小 1248,11 行锁
MySQL 线程 id 2927,OS 线程句柄 0x13a515000,查询 id 186769 localhost 127.0.0.1 root 发送数据
SELECT id FROM table_meta WHERE id IN (1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15) 进行更新
*** (2) 持有锁:
记录锁空间 id 128954 页号 5 n 位 176 表 `db_test1`.`table_meta` 的索引 `PRIMARY` trx id 2333255 lock_mode X 锁定记录但不锁定间隙
*** (2) 等待授予此锁定:
RECORD LOCKS 空间 id 128954 页号 5 n 位 176 表 `db_test1`.`table_meta` 的索引 `PRIMARY` trx id 2333255 lock_mode X 锁定记录但不锁定间隙等待
*** 我们回滚交易 (2)
4

3 回答 3

1

当然,

刚刚在 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 选项。

于 2013-10-01T12:37:56.113 回答
0

简单的方法;

  1. 尝试找出死锁案例中涉及的表;
  2. 确定哪个表在 INSERT/UPDATE/DELETE 方面应优先于其他表;
  3. 只需使用 LOCK TABLES...UNLOCK TABLES 语句包装相关查询(如果存在,您应该使用别名)

希望不是所有的语句/表格都需要这个总结,只有关键的一个。

于 2021-07-12T19:11:17.213 回答
0

我们需要更好地了解整个事务
(尤其是从 1 到 15 的一个锁定行)才能给您一个具体的答案。
好像你有这个事务锁定表一次,然后在同一个事务中再次锁定它。
您必须在同一事务的两个 SELECT FOR UPDATE 之间提交。

于 2021-12-07T13:11:04.620 回答