Пожалуйста, помогите мне разобраться в сценарии использования 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;
- возвращает пустой список
Теперь поток 1 думает, что у комнаты 1 нет тегов, но на самом деле комната была удалена. Чтобы решить эту проблему, поток 1 должен SELECT id FROM rooms FOR UPDATE
предотвратить удаление потока 2 rooms
до тех пор, пока поток 1 не будет завершен. Это правильно?
Вопрос 2 : Когда следует использовать SERIALIZABLE
изоляцию транзакций, а не READ_COMMITTED
с SELECT ... FOR UPDATE
?
Ожидается, что ответы будут переносимы (не привязаны к базе данных). Если это невозможно, объясните, почему.
REPEATABLE_READ
и READ_COMMITTED
даже переносные варианты? Единственные результаты, которые я получаю для них, относятся к серверу MSSQL
READ COMMITTED
режима не определяет, действительно ли вы будете видеть записи, зафиксированные другой транзакцией: это только гарантирует, что вы никогда не увидите незафиксированные записи.
select ... for update
по- rooms
прежнему можно room_tags
будет удалить, потому что это отдельные таблицы. Вы хотели спросить, for update
предотвратит ли этот пункт удаление из rooms
?