sql >> Database >  >> RDS >> Mysql

Deadlock met SELECT ... FOR UPDATE in MySQL

Wat werkt en wat niet

Een manier om beide transacties zonder een impasse te laten verlopen, is door de isolatieniveau om TOEVOEGD TE LEZEN (of LEES NIET-TOEGANG ) in beide verbindingen:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

(vóór start transaction ).

Waarschijnlijk zou het voldoende zijn om het in te stellen in t2 , maar voor de zekerheid voor het voorbeeld, stel het in op beide.

Het wijzigen van het isolatieniveau van transacties introduceert enkele bijwerkingen, waarover men moet informeren over in de handleiding voordat u dit wijzigt in een productieomgeving.

Statusinformatie met betrekking tot impasse

------------------------
LATEST DETECTED DEADLOCK
------------------------
140424  8:45:46
*** (1) TRANSACTION:
TRANSACTION B6F18A3, ACTIVE 5 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 13885, OS thread handle 0x7f8b1dbd2700, query id 901012
 localhost root statistics
SELECT * FROM t WHERE id = 1 FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A3 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** (2) TRANSACTION:
TRANSACTION B6F18A2, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 13888, OS thread handle 0x7f8b1f64d700, query id 901068
 localhost root Updating
UPDATE t SET `descc` = 'Hello from t1'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A2 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A2 lock_mode X waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** WE ROLL BACK TRANSACTION (1)

Uitleg

Zoals a_horse_with_no_name al zei, lijkt dit een bug in MySQL. Transactie (2) wil een gap-lock verkrijgen op dezelfde rij waar al een X-lock staat. Transactie (1) wacht op een non-gap X lock op deze rij. Het is mij niet duidelijk waarom deze verzoeken zouden moeten conflicteren. Het isolatieniveau instellen op READ COMMITTED schakelt gap-locking uit. Aangezien het voorbeeld dan werkt, is dit een hint dat gap locking hier inderdaad het probleem is.




  1. ClusterControl - Geavanceerd back-upbeheer - mariabackup deel III

  2. CSV importeren om slechts één kolom in tabel bij te werken

  3. SQLiteDatabase-fout, nutteloos logboek

  4. SQL Fiddle-uitvoerfout