Mysql Innodb Deadlock on delete with Primary Keys IN 语句

Posted

技术标签:

【中文标题】Mysql Innodb Deadlock on delete with Primary Keys IN 语句【英文标题】:Mysql Innodb Deadlock on delete with Primary Keys IN statement 【发布时间】:2014-05-26 20:22:50 【问题描述】:

寻求帮助以了解为什么会发生这种死锁。我已经阅读了 mysql 文档和许多关于死锁相关问题的 SO 问题,但我显然遗漏了一些东西。

这是有问题的表格:

CREATE TABLE `table_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB ;

它有一大堆其他列已被删除以保持简单(没有一个 是外键)。

两个或多个线程正在执行以下查询:

DELETE q  FROM table_queue q WHERE q.id IN(165765,165770,165782,165787,165791 .. );

IN 语句可能有 1,000 个值。如您所见,它正在删除 首要的关键。但是,innodb 状态输出显示一个线程正在等待锁定 在甚至不在其删除列表中的记录上(在 IN 子句中)。

SHOW ENGINE INNODB 输出:

------------------------
LATEST DETECTED DEADLOCK
------------------------
140526 15:54:03
*** (1) TRANSACTION:
TRANSACTION A841, ACTIVE 1 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 36 lock struct(s), heap size 2496, 882 row lock(s), undo log entries 70
MySQL thread id 59, OS thread handle 0xa69d9b40, query id 40446 localhost 127.0.0.1 localhost Sending data
DELETE q  FROM table_queue q WHERE q.id IN(165765,165770,165782,165787, ...
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 4653 n bits 216 index `PRIMARY` of table `maildb`.`table_queue` trx id A841 lock_mode X waiting
Record lock, heap no 67 PHYSICAL RECORD: n_fields 20; compact format; info bits 0
 0: len 4; hex 800288fb; asc     ;;
 1: len 6; hex 00000000a82d; asc      -;;
 2: len 7; hex a2000001e83a9e; asc      : ;;
 3: len 4; hex 80000001; asc     ;;
 4: len 4; hex 80000002; asc     ;;
 5: len 11; hex 6361726c6f732b36313535; asc jsmith+6155;;
 6: len 5; hex 536d697468; asc Smith;;
 7: len 22; hex 6361726c6f732b3631353540636f6d6d65722e636f6d; asc jsmith+6155@domain.com;;
 8: len 4; hex 8000180b; asc     ;;
 9: len 8; hex 43617465676f7279; asc Category;;
 10: len 4; hex 80000000; asc     ;;
 11: len 4; hex 80000000; asc     ;;
 12: len 4; hex 80000000; asc     ;;
 13: len 4; hex 80000000; asc     ;;
 14: SQL NULL;
 15: SQL NULL;
 16: len 1; hex 91; asc  ;;
 17: SQL NULL;
 18: SQL NULL;
 19: SQL NULL;

*** (2) TRANSACTION:
TRANSACTION A844, ACTIVE 1 sec starting index read
mysql tables in use 1, locked 1
30 lock struct(s), heap size 2496, 646 row lock(s)
MySQL thread id 60, OS thread handle 0xa69a8b40, query id 40453 localhost 127.0.0.1 localhost Sending data
DELETE q  FROM table_queue q WHERE q.id IN(166139,166146,166162,166166,166171,166175,166177,....
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 4653 n bits 216 index `PRIMARY` of table `maildb`.`table_queue` trx id A844 lock mode S locks rec but not gap
Record lock, heap no 67 PHYSICAL RECORD: n_fields 20; compact format; info bits 0
 0: len 4; hex 800288fb; asc     ;;
 1: len 6; hex 00000000a82d; asc      -;;
 2: len 7; hex a2000001e83a9e; asc      : ;;
 3: len 4; hex 80000001; asc     ;;
 4: len 4; hex 80000002; asc     ;;
 5: len 11; hex 6361726c6f732b36313535; asc jsmith+6155;;
 6: len 5; hex 536d697468; asc Smith;;
 7: len 22; hex 6361726c6f732b3631353540636f6d6d65722e636f6d; asc jsmith+6155@domain.com;;
 8: len 4; hex 8000180b; asc     ;;
 9: len 8; hex 43617465676f7279; asc Category;;
 10: len 4; hex 80000000; asc     ;;
 11: len 4; hex 80000000; asc     ;;
 12: len 4; hex 80000000; asc     ;;
 13: len 4; hex 80000000; asc     ;;
 14: SQL NULL;
 15: SQL NULL;
 16: len 1; hex 91; asc  ;;
 17: SQL NULL;
 18: SQL NULL;
 19: SQL NULL;

Record lock, heap no 74 PHYSICAL RECORD: n_fields 20; compact format; info bits 0
 0: len 4; hex 80028902; asc     ;;
 1: len 6; hex 00000000a82d; asc      -;;
 2: len 7; hex a2000001e83af9; asc      : ;;
 3: len 4; hex 80000001; asc     ;;
 4: len 4; hex 80000001; asc     ;;
 5: len 11; hex 6361726c6f732b36313632; asc jsmith+6162;;
 6: len 5; hex 536d697468; asc Smith;;
 7: len 22; hex 6361726c6f732b3631363240636f6d6d65722e636f6d; asc jsmith+6162@domain.com;;
 8: len 4; hex 80001812; asc     ;;
 9: len 8; hex 43617465676f7279; asc Category;;
 10: len 4; hex 80000000; asc     ;;
 11: len 4; hex 80000000; asc     ;;
 12: len 4; hex 80000000; asc     ;;
 13: len 4; hex 80000000; asc     ;;
 14: SQL NULL;
 15: SQL NULL;
 16: len 1; hex 94; asc  ;;
 17: SQL NULL;
 18: SQL NULL;
 19: SQL NULL;
...
...

据我了解,事务 A841 想要获得某条记录的排他锁。在这种情况下,我可以 告诉记录有 id = 166139。查看应用程序日志,我可以看出事务/线程在其 DELETE IN 子句中没有 id 166139 那么为什么它需要对该记录进行锁定?

我是否误解了,如果您使用主键明确指定要删除的行,MySQL 应该只锁定那些匹配的 PK 行?有没有可能被锁定 由于某种原因,其他相邻的行?

【问题讨论】:

如果 id 的列表非常大,MySQL 可以决定锁定整个表而不是锁定每条记录更高效。 【参考方案1】:

Innodb 锁定所有需要扫描的行以防删除操作.. 通过阅读以下博客,您可以更好地理解:

BLOG LINK

【讨论】:

我也有同样的问题。我刚刚在我的表上添加了建议的索引。

以上是关于Mysql Innodb Deadlock on delete with Primary Keys IN 语句的主要内容,如果未能解决你的问题,请参考以下文章

mysql死锁com.mysql.cj.jdbc.exception.MYSQLTransactionRollbackException Deadlock found when trying to g

04. pt-deadlock-logger

innodb_locks_unsafe_for_binlog参数解析

innodb_locks_unsafe_for_binlog参数解析

MySQL数据库innodb_rollback_on_timeout参数

mysql数据库崩溃:InnoDB: Database page corruption on disk or a failed