sql >> Databasteknik >  >> RDS >> Mysql

Låsning av radnivåer i Mysql

Istället för FOR UPDATE använd LOCK IN SHARE MODE . FOR UPDATE förhindrar att andra transaktioner också läser raden. LOCK IN SHARE MODE tillåter läsning, men förhindrar uppdatering.

Referens:MySQL Manual

------ session 1

START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;

----- session 2 (som inte blockeras längre :) )

START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;

Uppdatering:

Inser att tabellen inte har något indext , jag har följande förklaring:

Först låser transaktion T1 rad 1 i SELECT * FROM test WHERE t=1 FOR UPDATE

Därefter försöker transaktion T2 att utföra UPDATE test SET NAME='irfandd' WHERE t=4 . För att ta reda på vilka rader som berörs måste den skanna alla rader, inklusive rad 1 . Men det är låst, så T2 måste vänta tills T1 är klart. Om det finns någon form av index visas WHERE t=4 kan använda indexet för att avgöra om rad 1 innehåller t=4 eller inte, så du behöver inte vänta.

Alternativ 1: lägg till ett index på test.t så att din uppdatering kan använda den.

Alternativ 2: använd LOCK IN SHARE MODE , som endast är avsedd för att sätta ett läslås. Tyvärr skapar detta alternativ ett dödläge. Intressant nog utförs T2-transaktionen (uppdatering av rad 4) och T1 misslyckas (uppdatering av rad 2). Det verkar som att T1 läslås rad 4 också, och eftersom T2 modifierar det, misslyckas T1 på grund av transaktionsisoleringsnivån (REPETERBAR LÄSNING som standard ). Den slutliga lösningen skulle vara att leka med Transaktionsisoleringsnivåer , med hjälp av READ UNCOMMITTED eller READ COMMITTED transaktionsnivåer.

Det enklaste är Alternativ 1 IMHO, men det är upp till dina möjligheter.



  1. MySQL-datatyper:Lär dig vilka du ska använda och hur

  2. Lägg till år till ett datum i PostgreSQL

  3. Formatera siffror genom att fylla med inledande nollor i SQL Server

  4. TRIGGERS som gör att INSERT misslyckas? Möjlig?