使用主键IN语句删除Mysql Innodb死锁

时间:2014-05-26 20:22:50

标签: mysql sql multithreading database-deadlocks

寻求帮助,了解为什么会出现这种僵局。我已经阅读了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语句可能有1000个值的上升。如您所见,它正在删除 首要的关键。但是,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行?是否有可能锁定 其他相邻的行由于某种原因?

1 个答案:

答案 0 :(得分:2)

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

BLOG LINK