Тупик при вставке на дубликат обновления ключа sql с использованием уникального ключа - PullRequest
0 голосов
/ 06 декабря 2018

Является ли sql как вставка ... при обновлении дублированного ключа будет генерировать блокировки пробела для каждого индекса уникального ключа / первичного ключа, неупорядоченно, когда строки нет в таблице?

Я обнаружил, что при использовании нескольких транзакцийвыполнить вставку при обновлении дубликата ключа sql для таблицы с более чем одним уникальным ключом может вызвать взаимоблокировку.

Моя таблица была похожа на:

| Table | Create Table                                                                                                                                                                                                                
| test | CREATE TABLE `test1` (
  `c1` int(11) NOT NULL,
  `c2` int(11) DEFAULT NULL,
  `c3` int(11) DEFAULT NULL,
  PRIMARY KEY (`c1`),
  UNIQUE KEY `uk` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 

После возникновения тупика lock Я получил состояние innodb движка:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-12-06 20:01:57 0x70000ee06000
*** (1) TRANSACTION:
TRANSACTION 2219555, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 6686, OS thread handle 123145569476608, query id 6114936 localhost 127.0.0.1 root update
INSERT INTO test1 (`c1`, `c2`, `c3`) VALUES (15538, 1213457428, 30) ON DUPLICATE KEY UPDATE `c3` = VALUES(`c3`)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 65 page no 29 n bits 848 index cc of table `compare_db`.`test1` trx id 2219555 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 749 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex c88c97bb; asc     ;;
 1: len 4; hex 80002c42; asc   ,B;;

*** (2) TRANSACTION:
TRANSACTION 2219538, 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 6631, OS thread handle 123145551896576, query id 6114889 localhost 127.0.0.1 root update
INSERT INTO test1 (`c1`, `c2`, `c3`) VALUES (535, 1215380840, 30) ON DUPLICATE KEY UPDATE `c3` = VALUES(`c3`)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 65 page no 29 n bits 840 index cc of table `compare_db`.`test1` trx id 2219538 lock_mode X locks gap before rec
Record lock, heap no 749 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex c88c97bb; asc     ;;
 1: len 4; hex 80002c42; asc   ,B;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 65 page no 29 n bits 848 index cc of table `compare_db`.`test1` trx id 2219538 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 749 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex c88c97bb; asc     ;;
 1: len 4; hex 80002c42; asc   ,B;;

*** WE ROLL BACK TRANSACTION (1)

Было бы просто хорошо, если вставлять напрямую.Так что я подумал, потому что оба сеанса оказались заблокированными пробелом (a, b) на uk и (c, d) на первичном ключе, когда возникла взаимоблокировка, но с другим порядком.Кто-нибудь знает настоящую причину?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...