Jedynym przenośnym sposobem na osiągnięcie spójności między pokojami i tagami oraz upewnienie się, że pokoje nigdy nie zostaną zwrócone po ich usunięciu, jest zablokowanie ich za pomocą SELECT FOR UPDATE .
Jednak w niektórych systemach blokowanie jest efektem ubocznym kontroli współbieżności i uzyskuje się te same wyniki bez określenia FOR UPDATE wyraźnie.
Aby rozwiązać ten problem, wątek 1 powinien SELECT id FROM rooms FOR UPDATE , zapobiegając w ten sposób usuwaniu wątku 2 z rooms aż do zakończenia wątku 1. Czy to prawda?
Zależy to od kontroli współbieżności używanej przez system bazy danych.
-
MyISAMwMySQL(i kilka innych starych systemów) blokuje całą tabelę na czas trwania zapytania. -
W
SQL Server,SELECTzapytania umieszczają blokady współdzielone na przebadanych rekordach / stronach / tabelach, podczas gdyDMLkwerendy umieszczają blokady aktualizacji (które później są awansowane na blokady wyłączne lub zdegradowane do blokad współdzielonych). Blokady na wyłączność są niekompatybilne z blokadami współdzielonymi, więc alboSELECTlubDELETEzapytanie zostanie zablokowane do czasu zatwierdzenia kolejnej sesji. -
W bazach danych używających
MVCC(jakOracle,PostgreSQL,MySQLzInnoDB),DMLzapytanie tworzy kopię rekordu (w taki czy inny sposób) i generalnie czytelnicy nie blokują autorów i odwrotnie. W przypadku tych baz danychSELECT FOR UPDATEprzydałoby się:zablokowałoby alboSELECTlubDELETEzapytanie, aż kolejna sesja zostanie zatwierdzona, tak jakSQL Servertak.
Kiedy należy użyć REPEATABLE_READ izolacja transakcji a READ_COMMITTED z SELECT ... FOR UPDATE ?
Ogólnie REPEATABLE READ nie zabrania wierszy fantomowych (wiersze, które pojawiły się lub zniknęły w innej transakcji, zamiast być modyfikowane)
-
W
Oraclei wcześniejszePostgreSQLwersje,REPEATABLE READjest właściwie synonimemSERIALIZABLE. Zasadniczo oznacza to, że transakcja nie widzi zmian wprowadzonych po jej rozpoczęciu. Tak więc w tej konfiguracji ostatniThread 1zapytanie zwróci pokój tak, jakby nigdy nie został usunięty (co może, ale nie musi, być tym, czego chciałeś). Jeśli nie chcesz pokazywać pokoi po ich usunięciu, powinieneś zablokować wiersze za pomocąSELECT FOR UPDATE -
W
InnoDB,REPEATABLE READiSERIALIZABLEsą różne rzeczy:czytniki wSERIALIZABLEtryb ustawia blokady następnego klawisza na rekordach, które oceniają, skutecznie zapobiegając współbieżnemuDMLna nich. Więc nie potrzebujeszSELECT FOR UPDATEw trybie serializowalnym, ale potrzebujesz ich wREPEATABLE READlubREAD COMMITED.
Zwróć uwagę, że standard trybów izolacji nakazuje, że nie widzisz pewnych dziwactw w zapytaniach, ale nie definiuje, jak (z blokowaniem lub z MVCC lub inaczej).
Kiedy mówię „nie potrzebujesz SELECT FOR UPDATE „Naprawdę powinienem był dodać „ze względu na skutki uboczne implementacji określonego silnika bazy danych”.