Допоможіть мені, будь ласка, зрозуміти приклад використання SELECT ... FOR UPDATE
.
Запитання 1 : Чи наведений нижче приклад, коли SELECT ... FOR UPDATE
слід використовувати?
Подано:
- кімнати [ід]
- теги [id, ім'я]
- 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
?