Процедура взаимоблокировки MySQL: три вставки транзакции имеют один откат

MySQL

Это очень классический сценарий.Поиск взаимоблокировки, вызванной вставкой блокировок намерений в Интернете, в основном укажет на этот пример.

Структура таблицы

CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` varchar(5),
  `b` varchar(5),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name` (`a`,`b`)
);

Операторы вставки трех транзакций:insert ignore into t1(a, b)values("1", "1");

Шаги для воспроизведения следующие:

t1 t2 t3 Примечание
begin begin begin
insert успех
insert Продвигайте неявный замок T1 до блокировки X, T2 входит в блокировку S и ждет
insert t3 Войти в ожидание блокировки S
rollback; После отката t1 блокировка X снимается, а t2 и t3 одновременно получают блокировку S.
ok deadlock И t2, и t3 хотят получить блокировку X блокировки намерения вставки, что приводит к тупиковой ситуации.

Журнал взаимоблокировок выглядит следующим образом

------------------------
LATEST DETECTED DEADLOCK
------------------------
181101 23:22:59
*** (1) TRANSACTION:
TRANSACTION 5032, ACTIVE 11 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 5, OS thread handle 0x70000d736000, query id 125 localhost root update
insert ignore into t1(a, b)values("1", "1")
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 56 page no 4 n bits 584 index `uk_name` of table `d1`.`t1` trx id 5032 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 139 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 3; hex 313031; asc 101;;
 1: len 3; hex 313031; asc 101;;
 2: len 4; hex 800007b1; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 5033, ACTIVE 6 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 6, OS thread handle 0x70000d779000, query id 126 localhost root update
insert ignore into t1(a, b)values("1", "1")
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 56 page no 4 n bits 584 index `uk_name` of table `d1`.`t1` trx id 5033 lock mode S locks gap before rec
Record lock, heap no 139 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 3; hex 313031; asc 101;;
 1: len 3; hex 313031; asc 101;;
 2: len 4; hex 800007b1; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 56 page no 4 n bits 584 index `uk_name` of table `d1`.`t1` trx id 5033 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 139 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 3; hex 313031; asc 101;;
 1: len 3; hex 313031; asc 101;;
 2: len 4; hex 800007b1; asc     ;;

*** WE ROLL BACK TRANSACTION (2)

Здесь мы впервые упомянули вставить блокировку намерения (вставить блокировку намерения)

вставить блокировку намерения Для модификации и удаления существующих строк данных необходимо усилить блокировку взаимного исключения X. Необходима ли такая сильная блокировка для вставки данных для реализации взаимного исключения? Вставьте замок намерения, задуманный и рожденный. Блокировка намерения вставки является разновидностью гэп-блокировки (Gap Locks), она специально разработана для операции вставки, а также является одним из немногих случаев, когда Gap-блокировки генерируются на уровне RC.