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í zroomsdokud nebude vlákno 1 hotové. Je to správně?
To závisí na kontrole souběžnosti, kterou váš databázový systém používá.
-
MyISAMvMySQL(a několik dalších starých systémů) uzamkne celou tabulku po dobu trvání dotazu. -
V
SQL Server,SELECTdotazy umísťují sdílené zámky na záznamy / stránky / tabulky, které zkoumaly, zatímcoDMLdotazy 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ďSELECTneboDELETEdotaz se uzamkne, dokud nebude potvrzena další relace. -
V databázích, které používají
MVCC(jakoOracle,PostgreSQL,MySQLsInnoDB),DMLdotaz vytvoří kopii záznamu (tak či onak) a obecně čtečky neblokují pisatele a naopak. Pro tyto databázeSELECT FOR UPDATEby se hodilo:uzamklo by to buďSELECTneboDELETEdotazovat, dokud se nepotvrdí další relace, stejně jakoSQL Serverano.
Kdy byste měli použít
REPEATABLE_READizolace transakce versusREAD_COMMITTEDpomocíSELECT ... FOR UPDATE?
Obecně REPEATABLE READ nezakazuje fiktivní řádky (řádky, které se objevily nebo zmizely v jiné transakci, místo aby byly upraveny)
-
V
Oraclea dřívějšíPostgreSQLverze,REPEATABLE READje ve skutečnosti synonymem proSERIALIZABLE. V zásadě to znamená, že transakce po jejím spuštění neuvidí provedené změny. V tomto nastavení tedy posledníThread 1dotaz 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 READaSERIALIZABLEjsou různé věci:čtečky vSERIALIZABLErežim nastavil zámky další klávesy na záznamech, které vyhodnocují, čímž účinně zabrání souběžnémuDMLna ně. Nepotřebujete tedySELECT FOR UPDATEv serializovatelném režimu, ale potřebujete je vREPEATABLE READneboREAD 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".