De enige draagbare manier om consistentie tussen kamers en tags te bereiken en ervoor te zorgen dat kamers nooit worden geretourneerd nadat ze zijn verwijderd, is ze te vergrendelen met SELECT FOR UPDATE
.
In sommige systemen is vergrendeling echter een neveneffect van gelijktijdigheidscontrole en bereikt u dezelfde resultaten zonder FOR UPDATE
op te geven. expliciet.
Om dit probleem op te lossen, moet Thread 1 SELECT id FROM rooms FOR UPDATE
, waardoor wordt voorkomen dat Thread 2 wordt verwijderd uit rooms
totdat draad 1 klaar is. Klopt dat?
Dit hangt af van het gelijktijdigheidsbeheer dat uw databasesysteem gebruikt.
-
MyISAM
inMySQL
(en verschillende andere oude systemen) vergrendelt de hele tabel voor de duur van een zoekopdracht. -
In
SQL Server
,SELECT
query's plaatsen gedeelde vergrendelingen op de records / pagina's / tabellen die ze hebben onderzocht, terwijlDML
query's plaatsen updatevergrendelingen (die later worden gepromoveerd tot exclusieve of gedegradeerd tot gedeelde vergrendelingen). Exclusieve sloten zijn niet compatibel met gedeelde sloten, dus ofwelSELECT
ofDELETE
query wordt vergrendeld totdat een andere sessie wordt vastgelegd. -
In databases die
MVCC
. gebruiken (zoalsOracle
,PostgreSQL
,MySQL
metInnoDB
), eenDML
query maakt een kopie van het record (op de een of andere manier) en over het algemeen blokkeren lezers geen schrijvers en vice versa. Voor deze databases, eenSELECT FOR UPDATE
zou handig zijn:het zou ofwelSELECT
. vergrendelen of deDELETE
query totdat een andere sessie zich commit, net alsSQL Server
doet.
Wanneer moet men REPEATABLE_READ
gebruiken? transactie-isolatie versus READ_COMMITTED
met SELECT ... FOR UPDATE
?
Over het algemeen REPEATABLE READ
verbiedt geen fantoomrijen (rijen die zijn verschenen of verdwenen in een andere transactie, in plaats van te worden gewijzigd)
-
In
Oracle
en eerderPostgreSQL
versies,REPEATABLE READ
is eigenlijk een synoniem voorSERIALIZABLE
. Kort gezegd betekent dit dat de transactie geen wijzigingen meer ziet die zijn aangebracht nadat deze is gestart. Dus in deze opstelling is de laatsteThread 1
query zal de kamer retourneren alsof deze nooit is verwijderd (wat al dan niet is wat je wilde). Als je de kamers niet wilt tonen nadat ze zijn verwijderd, moet je de rijen vergrendelen metSELECT FOR UPDATE
-
In
InnoDB
,REPEATABLE READ
enSERIALIZABLE
zijn verschillende dingen:lezers inSERIALIZABLE
mode zet next-key locks op de records die ze evalueren, waardoor de gelijktijdigeDML
effectief wordt voorkomen op hen. Je hebt dus geenSELECT FOR UPDATE
nodig in serialiseerbare modus, maar heb ze wel nodig inREPEATABLE READ
ofREAD COMMITED
.
Merk op dat de standaard over isolatiemodi voorschrijft dat u bepaalde eigenaardigheden niet in uw zoekopdrachten ziet, maar niet definieert hoe (met vergrendeling of met MVCC
of anderszins).
Als ik zeg "je hebt SELECT FOR UPDATE
niet nodig" " Ik had eigenlijk moeten toevoegen "vanwege bijwerkingen van bepaalde database-engine-implementaties".