sql >> Databáze >  >> RDS >> Mysql

Zamykání na úrovni řádků v Mysql

Místo FOR UPDATE použijte LOCK IN SHARE MODE . FOR UPDATE zabrání dalším transakcím číst řádek také. LOCK IN SHARE MODE umožňuje čtení, ale brání aktualizaci.

Odkaz:Příručka MySQL

------ relace 1

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

----- relace 2 (která již není blokována :) )

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

Aktualizace:

Uvědomte si, že tabulka nemá žádný index na t , mám následující vysvětlení:

Nejprve transakce T1 uzamkne řádek 1 v SELECT * FROM test WHERE t=1 FOR UPDATE

Dále se transakce T2 pokusí provést UPDATE test SET NAME='irfandd' WHERE t=4 . Aby zjistil, které řádky jsou ovlivněny, musí prohledat všechny řádky, včetně řádku 1 . Ale to je uzamčeno, takže T2 musí počkat, až T1 skončí. Pokud existuje nějaký druh indexu, WHERE t=4 může použít index k rozhodnutí, zda řádek 1 obsahuje t=4 nebo ne, takže není třeba čekat.

Možnost 1: přidejte index na test.t aby ji vaše aktualizace mohla použít.

Možnost 2: použijte LOCK IN SHARE MODE , který je určen pouze pro vložení zámku pro čtení. Tato možnost bohužel vytváří uváznutí. Zajímavé je, že transakce T2 se provede (aktualizace řádku 4) a T1 selže (aktualizace řádku 2). Zdá se, že T1 blokuje čtení řádku 4 také, a protože to T2 upravuje, T1 selže kvůli úrovni izolace transakcí (Opakovatelné čtení ve výchozím nastavení ). Konečným řešením by bylo hraní s Úrovně izolace transakcí , pomocí READ UNCOMMITTED nebo READ COMMITTED úrovně transakcí.

Nejjednodušší je Možnost 1 IMHO, ale je to na vašich možnostech.



  1. 2 způsoby, jak vložit nový řádek do řetězce v SQLite

  2. Auto Increment varchar v MySQL

  3. Použití proměnné v klauzuli LIMIT v MySQL

  4. Python:použít mysqldb k importu tabulky MySQL jako slovníku?