Mysql:在更新查询中使用嵌套的select查询会创建死锁

Mysql:在更新查询中使用嵌套的select查询会创建死锁,mysql,database-deadlocks,nested-queries,Mysql,Database Deadlocks,Nested Queries,我正在尝试根据从同一个表中选择的内容更新列。 查询: 有更多的java线程用于从tasks_queue表中拾取 该表的模式如下所示 CREATE TABLE `tasks_queue` ( `id` bigint(18) NOT NULL, `user_id` bigint(18) NOT NULL, `scheduled_at` bigint(13) NOT NULL, `source_type` tinyint(2) NOT NULL, `source_id`

我正在尝试根据从同一个表中选择的内容更新列。 查询:

有更多的java线程用于从tasks_queue表中拾取

该表的模式如下所示

     CREATE TABLE `tasks_queue` (
  `id` bigint(18) NOT NULL,
  `user_id` bigint(18) NOT NULL,
  `scheduled_at` bigint(13) NOT NULL,
  `source_type` tinyint(2) NOT NULL,
  `source_id` bigint(18) DEFAULT NULL,
  `priority_level` smallint(6) NOT NULL,
  `picked_at` bigint(13) DEFAULT NULL,
  `pickup_id` varchar(45) DEFAULT NULL,
  `raw_data` longtext NOT NULL,
  PRIMARY KEY (`id`),
  KEY `scheduled_picked_at_idx` (`scheduled_at`,`picked_at`),
  KEY `user_id_idx` (`user_id`),
  KEY `pickup_id` (`pickup_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
死锁转储信息

2020-05-27T13:02:53.889027Z 82092 [Note] InnoDB: Transactions deadlock detected, dumping detailed information.
2020-05-27T13:02:53.889048Z 82092 [Note] InnoDB: 
*** (1) TRANSACTION:

TRANSACTION 1394376833, ACTIVE 0 sec fetching rows
mysql tables in use 2, locked 2
LOCK WAIT 18 lock struct(s), heap size 1136, 163 row lock(s)
MySQL thread id 80724, OS thread handle 140642529179392, query id 2122809 ip-172-31-29-45.ap-south-1.compute.internal 172.31.29.45 testuser Creating sort index
update tasks_queue as t1, (select id from tasks_queue where (user_id>=1230000000000000) and (user_id<=1230099999999999) and (scheduled_at <= 1590584573882 and picked_at <= 1590583673882) order by priority_level asc, scheduled_at asc  limit 0, 1  for update) as t2 set pickup_id = '172.31.29.45-1590584573882-2729', picked_at = 1590584573882 where (user_id>=1230000000000000) and (user_id<=1230099999999999) and (scheduled_at <= 1590584573882 and picked_at <= 1590583673882 and t1.id = t2.id)
2020-05-27T13:02:53.889099Z 82092 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 123642 page no 10 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376833 lock_mode X waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 80000000074cf829; asc      L );;
 1: len 6; hex 0000531c807f; asc   S   ;;
 2: len 7; hex c5000001980110; asc        ;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7fb4; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5773fe; asc   ^  Ws ;;
 11: len 30; hex (total 1126 bytes);

2020-05-27T13:02:53.895025Z 82092 [Note] InnoDB: *** (2) TRANSACTION:

TRANSACTION 1394376831, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 82092, OS thread handle 140641975121664, query id 2122814 ip-172-31-29-45.ap-south-1.compute.internal 172.31.29.45 testuser update
insert into tasks_queue (id,user_id,scheduled_at,source_type,source_id,priority_level,raw_data,picked_at) VALUES (-1403646261, 1230000000000001, 1590584573881, 1, 1230001000000109, 100, 'the payload dataa 
2020-05-27T13:02:53.895064Z 82092 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 123642 page no 10 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376831 lock_mode X locks rec but not gap
Record lock, heap no 8 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 80000000074cf829; asc      L );;
 1: len 6; hex 0000531c807f; asc   S   ;;
 2: len 7; hex c5000001980110; asc        ;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7fb4; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5773fe; asc   ^  Ws ;;
 11: len 30; hex test;

2020-05-27T13:02:53.895515Z 82092 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 123642 page no 23 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376831 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 11 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 7fffffffac99114e; asc        N;;
 1: len 6; hex 0000531c807c; asc   S  |;;
 2: len 7; hex c20000c0310266; asc     1 f;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7f93; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5761ef; asc   ^  Wa ;;
 11: len 30; hex 4461696c796f6e6c696e654a6f62733c6e6f2d7265706c79406461696c79; asc Daily<no-reply@daily; (total 1125 bytes);

2020-05-27T13:02:53.896735Z 82092 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (2)
有人能解释一下为什么会出现僵局吗

更新:
由于MySQL索引间隙锁定,出现了死锁。update语句中的嵌套select查询将锁定已扫描的记录索引,并锁定索引间隙。我希望这对某人有帮助

锁定是由于使用FOR UPDATE导致的,如果您这样做了会怎么样

参考:


你能解释一下MySQL在执行你建议的查询时使用的锁吗?我不知道,可能只是更新了记录。。。试着阅读我在回答中提供的链接上的信息,也许他们的内容会对你有所帮助。
     CREATE TABLE `tasks_queue` (
  `id` bigint(18) NOT NULL,
  `user_id` bigint(18) NOT NULL,
  `scheduled_at` bigint(13) NOT NULL,
  `source_type` tinyint(2) NOT NULL,
  `source_id` bigint(18) DEFAULT NULL,
  `priority_level` smallint(6) NOT NULL,
  `picked_at` bigint(13) DEFAULT NULL,
  `pickup_id` varchar(45) DEFAULT NULL,
  `raw_data` longtext NOT NULL,
  PRIMARY KEY (`id`),
  KEY `scheduled_picked_at_idx` (`scheduled_at`,`picked_at`),
  KEY `user_id_idx` (`user_id`),
  KEY `pickup_id` (`pickup_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
2020-05-27T13:02:53.889027Z 82092 [Note] InnoDB: Transactions deadlock detected, dumping detailed information.
2020-05-27T13:02:53.889048Z 82092 [Note] InnoDB: 
*** (1) TRANSACTION:

TRANSACTION 1394376833, ACTIVE 0 sec fetching rows
mysql tables in use 2, locked 2
LOCK WAIT 18 lock struct(s), heap size 1136, 163 row lock(s)
MySQL thread id 80724, OS thread handle 140642529179392, query id 2122809 ip-172-31-29-45.ap-south-1.compute.internal 172.31.29.45 testuser Creating sort index
update tasks_queue as t1, (select id from tasks_queue where (user_id>=1230000000000000) and (user_id<=1230099999999999) and (scheduled_at <= 1590584573882 and picked_at <= 1590583673882) order by priority_level asc, scheduled_at asc  limit 0, 1  for update) as t2 set pickup_id = '172.31.29.45-1590584573882-2729', picked_at = 1590584573882 where (user_id>=1230000000000000) and (user_id<=1230099999999999) and (scheduled_at <= 1590584573882 and picked_at <= 1590583673882 and t1.id = t2.id)
2020-05-27T13:02:53.889099Z 82092 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 123642 page no 10 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376833 lock_mode X waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 80000000074cf829; asc      L );;
 1: len 6; hex 0000531c807f; asc   S   ;;
 2: len 7; hex c5000001980110; asc        ;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7fb4; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5773fe; asc   ^  Ws ;;
 11: len 30; hex (total 1126 bytes);

2020-05-27T13:02:53.895025Z 82092 [Note] InnoDB: *** (2) TRANSACTION:

TRANSACTION 1394376831, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 82092, OS thread handle 140641975121664, query id 2122814 ip-172-31-29-45.ap-south-1.compute.internal 172.31.29.45 testuser update
insert into tasks_queue (id,user_id,scheduled_at,source_type,source_id,priority_level,raw_data,picked_at) VALUES (-1403646261, 1230000000000001, 1590584573881, 1, 1230001000000109, 100, 'the payload dataa 
2020-05-27T13:02:53.895064Z 82092 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 123642 page no 10 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376831 lock_mode X locks rec but not gap
Record lock, heap no 8 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 80000000074cf829; asc      L );;
 1: len 6; hex 0000531c807f; asc   S   ;;
 2: len 7; hex c5000001980110; asc        ;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7fb4; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5773fe; asc   ^  Ws ;;
 11: len 30; hex test;

2020-05-27T13:02:53.895515Z 82092 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 123642 page no 23 n bits 80 index PRIMARY of table `dspace3`.`tasks_queue` trx id 1394376831 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 11 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 8; hex 7fffffffac99114e; asc        N;;
 1: len 6; hex 0000531c807c; asc   S  |;;
 2: len 7; hex c20000c0310266; asc     1 f;;
 3: len 8; hex 80045eadb112e001; asc   ^     ;;
 4: len 8; hex 80000172563a7f93; asc    rV:  ;;
 5: len 1; hex 81; asc  ;;
 6: len 8; hex 80045eadecadaa6d; asc   ^    m;;
 7: len 2; hex 8064; asc  d;;
 8: len 8; hex 8000000000000000; asc         ;;
 9: SQL NULL;
 10: len 8; hex 80045eaded5761ef; asc   ^  Wa ;;
 11: len 30; hex 4461696c796f6e6c696e654a6f62733c6e6f2d7265706c79406461696c79; asc Daily<no-reply@daily; (total 1125 bytes);

2020-05-27T13:02:53.896735Z 82092 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (2)
update 
 tasks_queue t1
set 
 pickup_id = '172.31.29.45-1590584573882-2729',
 picked_at = 1590584573882
where
 (user_id>=1230000000000000) 
and 
 (user_id<=1230099999999999) 
and 
 (scheduled_at <= 1590584573882 and picked_at <= 1590583673882)
and
 t1.id in (
  select
   id
  from
   tasks_queue
  where
   (user_id>=1230000000000000)
  and
   (user_id<=1230099999999999)
  and
   (scheduled_at <= 1590584573882 and picked_at <= 1590583673882)
  order by
   priority_level asc, scheduled_at asc
  limit
   0, 1 
 )