Рассмотрим следующую схему в mysql:
create table foo(
id int not null primary key auto_increment,
name varchar(32) not null,
unique key(name)
);
И в таблице есть запись с именем "abc".
У меня есть транзакция (RC):
start transaction;
delete from foo where name = "abc";
insert into foo(name) values("abc");
commit;
Если есть две параллельные транзакции, будет иметь место мертвая блокировка.
| TX A | TX B
---------------------------------------------------------------------
Step 1 | start transaction; |
| delete name="abc"; |
---------------------------------------------------------------------
Step 2 | | start transaction;
| | delete name="abc";
| | <wait for lock>
---------------------------------------------------------------------
Step 3 | insert name="abc"; | <deadlock detected, exit>
---------------------------------------------------------------------
Step 4 | commit; |
---------------------------------------------------------------------
Мне интересно, почему эта последовательность вызывает тупик.
В документе mysql сказано(https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html)
Если возникает ошибка с дублирующимся ключом, устанавливается общая блокировка для записи дублирующегося индекса. Такое использование общей блокировки может привести к взаимоблокировке, если существует несколько сеансов, пытающихся вставитьта же строка, если другой сеанс уже имеет монопольную блокировку. Это может произойти, если другой сеанс удаляет строку.
Я полагаю, что когда транзакция A выполняет оператор "delete", она получает блокировку Xзапись "abc". Когда выполняется оператор "insert", он пытается получить блокировку S из-за "ошибки дублированного ключа". Разве он не должен получить блокировку S, поскольку он получил блокировку X той же записи? Почему тупик случаетсяздесь?