Пожалуйста, помогите мне понять прецедент за SELECT ... FOR UPDATE
.
Вопрос 1: Является ли следующий пример хорошим, когда SELECT ... FOR UPDATE
следует использовать?
Дано:
- номера [ID]
- теги [id, name]
- room_tags [room_id, tag_id]
- room_id и tag_id являются внешними ключами
Приложение хочет перечислить все номера и их теги, но необходимо различать номера без тегов и удаленных номеров. Если SELECT... FOR UPDATE не используется, может произойти следующее:
- Первоначально:
- номера содержат
[id = 1]
- содержит
[id = 1, name = 'cats']
- room_tags содержит
[room_id = 1, tag_id = 1]
- номера содержат
- Тема 1:
SELECT id FROM rooms;
-
returns [id = 1]
-
- Тема 2:
DELETE FROM room_tags WHERE room_id = 1;
- Тема 2:
DELETE FROM rooms WHERE id = 1;
- Тема 2: [совершает транзакцию]
- Тема 1:
SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;
- возвращает пустой список
Теперь Thread 1 считает, что в комнате 1 нет тегов, но на самом деле комната была удалена. Чтобы решить эту проблему, Thread 1 должен SELECT id FROM rooms FOR UPDATE
, тем самым предотвращая удаление Thread 2 с rooms
до тех пор, пока не будет завершен Thread 1. Это правильно?
Вопрос 2. Когда следует использовать транзакционную изоляцию SERIALIZABLE
по сравнению с READ_COMMITTED
с SELECT ... FOR UPDATE
?
Ожидается, что ответы будут переносимыми (не специфичными для конкретной базы данных). Если это невозможно, объясните, почему.