Пожалуйста, помогите мне разобраться в сценарии использования 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?