Ich habe eine Java-Anwendung, und es tritt Deadlock Ausnahme auf der sql unten: insert into voucher ( id, order_id, voucher_code ) SELECT #{id}, #{orderId}, #{voucherCode} FROM DUAL WHERE NOT EXISTS (SELECT id FROM voucher where order_id = #{orderId})
Die "order_id" ist eindeutiger Schlüssel. Und ich bin sicher, dass es blockiert wird, wenn der SQL-Server im Parallelbetrieb ausgeführt wird. Allerdings habe ich keine Berechtigung, um show engine innodb status
auszuführen, damit ich Informationen über die Deadlock-Ausnahme nicht abrufen kann.mysql innodb Deadlock Grund finden auf INSERT INTO SELECT
Ich versuche, das Problem in einer Laborumgebung zu reproduzieren. Tabellentest ist unten: Create Table: CREATE TABLE `test` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `info` varchar(128) NOT NULL DEFAULT '', `order_id` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `uni_order_id` (`order_id`) ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8
und führe ich zwei sqls in zwei verschiedenen Sitzungen:
insert into test(info,order_id) select '12345',sleep(10) from dual where not exists (select info from test where info='12345');
insert into test(info,order_id) select '12345',234 from dual where not exists (select info from test where info='12345');
Deadlock log unten:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2016-06-20 17:26:54 700000a83000
*** (1) TRANSACTION:
TRANSACTION 2321, ACTIVE 9 sec inserting
mysql tables in use 2, locked 2
LOCK WAIT 5 lock struct(s), heap size 1184, 2 row lock(s)
MySQL thread id 1, OS thread handle 0x700000a3f000, query id 29 localhost root executing
insert into test(info,order_id) select '12345',234 from dual where not exists (select info from test where info='12345')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 9 page no 3 n bits 72 index `PRIMARY` of table `test`.`test` trx id 2321 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) TRANSACTION:
TRANSACTION 2320, ACTIVE 10 sec setting auto-inc lock
mysql tables in use 2, locked 2
3 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 2, OS thread handle 0x700000a83000, query id 28 localhost root User sleep
insert into test(info,order_id) select '12345',sleep(10) from dual where not exists (select info from test where info='12345')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 9 page no 3 n bits 72 index `PRIMARY` of table `test`.`test` trx id 2320 lock mode S
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
TABLE LOCK table `test`.`test` trx id 2320 lock mode AUTO-INC waiting
*** WE ROLL BACK TRANSACTION (2)
ich angenommen, dass die Unterabfrage select info from test where info=‘12345’
Slock halten kann und insert into … select
wollen XLock. Aber ich finde das offizielle Dokument nicht, um meinen Standpunkt zu unterstützen.
Also meine Frage ist unten:
1. ist mein reproduzieren Design richtig?
2. ist mein Vorschlag (die Unterabfrage select info from test where info=‘12345’
kann SLock halten) richtig? Jedes offizielle Dokument kann meinen Vorschlag unterstützen?
Ich möchte den Grund für den Deadlock in diesem Fall anstelle der Lösung finden. – FatGhosta