Proszę, pomóż mi zrozumieć przypadek użycia SELECT ... FOR UPDATE
.
Pytanie 1 : Czy poniższy przykład jest dobrym przykładem, kiedy SELECT ... FOR UPDATE
należy stosować?
Dany:
- pokoje [id]
- tagi [identyfikator, nazwa]
- room_tags [room_id, tag_id]
- room_id i tag_id to klucze obce
Aplikacja chce wyświetlić wszystkie pokoje i ich tagi, ale musi rozróżnić pokoje bez tagów od tych, które zostały usunięte. Jeśli SELECT ... FOR UPDATE nie jest używany, może się zdarzyć:
- Początkowo:
- pokoje zawiera
[id = 1]
- tagi zawiera
[id = 1, name = 'cats']
- room_tags zawiera
[room_id = 1, tag_id = 1]
- pokoje zawiera
- Wątek 1:
SELECT id FROM rooms;
returns [id = 1]
- Wątek 2:
DELETE FROM room_tags WHERE room_id = 1;
- Wątek 2:
DELETE FROM rooms WHERE id = 1;
- Wątek 2: [zatwierdza transakcję]
- Wątek 1:
SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;
- zwraca pustą listę
Teraz wątek 1 uważa, że pokój 1 nie ma tagów, ale w rzeczywistości pokój został usunięty. Aby rozwiązać ten problem, Wątek 1 powinien SELECT id FROM rooms FOR UPDATE
zapobiegać usuwaniu wątku 2 od rooms
momentu zakończenia Wątku 1. Czy to jest poprawne?
Pytanie 2 : Kiedy należy używać SERIALIZABLE
izolacji transakcji, a READ_COMMITTED
kiedy z SELECT ... FOR UPDATE
?
Odpowiedzi powinny być przenośne (nie specyficzne dla bazy danych). Jeśli to niemożliwe, wyjaśnij dlaczego.
REPEATABLE_READ
a READ_COMMITTED
nawet opcje przenośne? Jedyne wyniki, które otrzymuję, dotyczą serwera MSSQL
READ COMMITTED
trybu nie definiuje, czy rzeczywiście zobaczysz rekordy zatwierdzone przez inną transakcję: zapewnia tylko, że nigdy nie zobaczysz niezatwierdzonych rekordów.
select ... for update
Na rooms
wciąż pozwalają room_tags
być usunięte, ponieważ są osobne tabele. Czy chodziło Ci o pytanie, czy for update
klauzula zapobiegnie usunięciom rooms
?