sql >> Databáze >  >> RDS >> Oracle

Zabraňuje SELECT FOR UPDATE vkládání dalších připojení, když řádek není přítomen?

MySQL

VYBERTE... PRO AKTUALIZACI pomocí AKTUALIZACE

Pomocí transakcí s InnoDB (automatické potvrzení vypnuto) a SELECT ... FOR UPDATE umožňuje jedné relaci dočasně uzamknout určitý záznam (nebo záznamy), aby jej žádná jiná relace nemohla aktualizovat. Potom v rámci stejné transakce může relace skutečně provést UPDATE na stejném záznamu a transakci potvrdit nebo vrátit zpět. To by vám umožnilo uzamknout záznam, aby jej žádná jiná relace nemohla aktualizovat, zatímco vy možná budete dělat nějakou jinou obchodní logiku.

Toho se dosáhne zamykáním. InnoDB využívá indexy pro zamykání záznamů, takže uzamčení existujícího záznamu se zdá snadné – jednoduše uzamkněte index pro daný záznam.

VLOŽTE... PRO AKTUALIZACI pomocí INSERT

Chcete-li však použít SELECT ... FOR UPDATE pomocí INSERT , jak zamknete index pro záznam, který ještě neexistuje? Pokud používáte výchozí úroveň izolace REPEATABLE READ , InnoDB bude také využívat mezera zámky. Pokud znáte id (nebo dokonce rozsah id) k uzamčení, pak InnoDB může uzamknout mezeru, takže do této mezery nelze vložit žádný další záznam, dokud s tím neskončíme.

Pokud vaše id sloupec byl sloupec s automatickým přírůstkem, pak SELECT ... FOR UPDATE pomocí INSERT INTO by bylo problematické, protože byste nevěděli, co je nové id byl, dokud jste jej nevložili. Protože však znáte id které si přejete vložit, SELECT ... FOR UPDATE pomocí INSERT bude fungovat.

UPOZORNĚNÍ

Na výchozí úrovni izolace SELECT ... FOR UPDATE na neexistujícím záznamu ne blokovat další transakce. Pokud tedy dvě transakce provedou obě SELECT ... FOR UPDATE na stejném neexistujícím záznamu indexu, oba získají zámek a žádná transakce nebude moci záznam aktualizovat. Ve skutečnosti, pokud se o to pokusí, bude detekováno uváznutí.

Pokud se tedy nechcete vypořádat se zablokováním, můžete udělat následující:

INSERT DO...

Zahajte transakci a proveďte INSERT . Proveďte svou obchodní logiku a transakci buď potvrďte, nebo vraťte zpět. Jakmile provedete INSERT na neexistujícím indexu záznamu při první transakci se všechny ostatní transakce zablokují, pokud se pokusí INSERT záznam se stejným jedinečným indexem. Pokud se druhá transakce pokusí vložit záznam se stejným indexem poté, co první transakce potvrdí vložení, zobrazí se chyba "duplicitní klíč". Zacházejte podle toho.

VYBRAT... ZAMKNOUT V REŽIMU SDÍLENÍ

Pokud vyberete pomocí LOCK IN SHARE MODE před INSERT , pokud předchozí transakce vložila tento záznam, ale ještě nebyla potvrzena, SELECT ... LOCK IN SHARE MODE se zablokuje, dokud nebude dokončena předchozí transakce.

Chcete-li tedy snížit možnost duplicitních chyb klíčů, zejména pokud zámky na chvíli podržíte při provádění obchodní logiky, než je provedete nebo je vrátíte zpět:

  1. SELECT bar FROM FooBar WHERE foo = ? LOCK FOR UPDATE
  2. Pokud se nevrátily žádné záznamy, pak
  3. INSERT INTO FooBar (foo, bar) VALUES (?, ?)


  1. Funkce hodnocení v SQL Server

  2. programově kontroluje otevřené připojení v JDBC

  3. Android Room:Jak migrovat přejmenování sloupců?

  4. FORMAT() je hezké, ale…