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

Kdy použít SELECT... FOR UPDATE?

Jediný přenosný způsob, jak dosáhnout konzistence mezi místnostmi a štítky a zajistit, aby se místnosti po smazání nikdy nevrátily, je uzamknout je pomocí SELECT FOR UPDATE .

V některých systémech je však zamykání vedlejším efektem kontroly souběžnosti a stejných výsledků dosáhnete bez zadání FOR UPDATE explicitně.

K vyřešení tohoto problému by vlákno 1 mělo SELECT id FROM rooms FOR UPDATE , čímž zabrání vláknu 2 ve smazání z rooms dokud nebude vlákno 1 hotové. Je to správně?

To závisí na kontrole souběžnosti, kterou váš databázový systém používá.

  • MyISAM v MySQL (a několik dalších starých systémů) uzamkne celou tabulku po dobu trvání dotazu.

  • V SQL Server , SELECT dotazy umísťují sdílené zámky na záznamy / stránky / tabulky, které zkoumaly, zatímco DML dotazy umísťují aktualizační zámky (které budou později povýšeny na exkluzivní nebo sníženy na sdílené zámky). Exkluzivní zámky jsou nekompatibilní se sdílenými zámky, takže buď SELECT nebo DELETE dotaz se uzamkne, dokud nebude potvrzena další relace.

  • V databázích, které používají MVCC (jako Oracle , PostgreSQL , MySQL s InnoDB ), DML dotaz vytvoří kopii záznamu (tak či onak) a obecně čtečky neblokují pisatele a naopak. Pro tyto databáze SELECT FOR UPDATE by se hodilo:uzamklo by to buď SELECT nebo DELETE dotazovat, dokud se nepotvrdí další relace, stejně jako SQL Server ano.

Kdy byste měli použít REPEATABLE_READ izolace transakce versus READ_COMMITTED pomocí SELECT ... FOR UPDATE ?

Obecně REPEATABLE READ nezakazuje fiktivní řádky (řádky, které se objevily nebo zmizely v jiné transakci, místo aby byly upraveny)

  • V Oracle a dřívější PostgreSQL verze, REPEATABLE READ je ve skutečnosti synonymem pro SERIALIZABLE . V zásadě to znamená, že transakce po jejím spuštění neuvidí provedené změny. V tomto nastavení tedy poslední Thread 1 dotaz vrátí místnost, jako by nikdy nebyla smazána (což může nebo nemusí být to, co jste chtěli). Pokud nechcete pokoje po smazání zobrazovat, měli byste řádky uzamknout pomocí SELECT FOR UPDATE

  • V InnoDB , REPEATABLE READ a SERIALIZABLE jsou různé věci:čtečky v SERIALIZABLE režim nastavil zámky další klávesy na záznamech, které vyhodnocují, čímž účinně zabrání souběžnému DML na ně. Nepotřebujete tedy SELECT FOR UPDATE v serializovatelném režimu, ale potřebujete je v REPEATABLE READ nebo READ COMMITED .

Všimněte si, že standard pro režimy izolace předepisuje, že ve svých dotazech nevidíte určité zvláštnosti, ale nedefinuje jak (se zamykáním nebo pomocí MVCC nebo jinak).

Když řeknu „nepotřebujete SELECT FOR UPDATE " Opravdu jsem měl přidat "kvůli vedlejším účinkům určité implementace databázového stroje".



  1. 'IF' v příkazu 'SELECT' - zvolte výstupní hodnotu na základě hodnot sloupců

  2. Úvod do SQL Server Identity

  3. Výkon operátora MySQL IN na (velkém?) počtu hodnot

  4. Jak nainstalovat, zabezpečit a vyladit výkon databázového serveru MariaDB