In plaats van FOR UPDATE
gebruik LOCK IN SHARE MODE
. FOR UPDATE
voorkomt dat andere transacties de rij ook lezen. LOCK IN SHARE MODE
staat lezen toe, maar voorkomt updaten.
Referentie:MySQL-handleiding
------ sessie 1
START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;
----- sessie 2 (die niet meer wordt geblokkeerd :) )
START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;
Bijwerken:
Realiseren dat de tabel geen index heeft op t
, ik heb de volgende uitleg:
Ten eerste vergrendelt transactie T1 de rij 1 in SELECT * FROM test WHERE t=1 FOR UPDATE
Vervolgens probeert transactie T2 UPDATE test SET NAME='irfandd' WHERE t=4
uit te voeren . Om erachter te komen welke rij(en) worden beïnvloed, moet het alle rijen scannen, inclusief rij 1 . Maar dat is vergrendeld, dus T2 moet wachten tot T1 klaar is. Als er een soort index is, de WHERE t=4
kan de index gebruiken om te beslissen of rij 1 bevat t=4
of niet, dus u hoeft niet te wachten.
Optie 1: voeg een index toe op test.t
zodat uw update het kan gebruiken.
Optie 2: gebruik LOCK IN SHARE MODE
, die alleen bedoeld is om een leesvergrendeling te plaatsen. Helaas zorgt deze optie voor een impasse. Interessant is dat de T2-transactie wordt uitgevoerd (rij 4) en T1 mislukt (rij 2). Het lijkt erop dat T1 read-locks rij 4 ook, en aangezien T2 het wijzigt, mislukt T1 vanwege het transactie-isolatieniveau (HERHAALBAAR LEZEN standaard
). De uiteindelijke oplossing zou zijn om te spelen met Transactie-isolatieniveaus , met behulp van READ UNCOMMITTED
of READ COMMITTED
transactieniveaus.
De eenvoudigste is Optie 1 , IMHO, maar het is aan jouw mogelijkheden.