Когда использовать ВЫБЕРИТЕ… ДЛЯ ОБНОВЛЕНИЯ?

Пожалуйста, помогите мне понять вариант использования SELECT ... FOR UPDATE.

Вопрос 1: Является ли следующий пример хорошим примером того, когда следует использовать SELECT ... FOR UPDATE?

Дано:

  • room[id]
  • tags[id, name]
  • room_tags[room_id, tag_id]
    • room_id и tag_id являются внешними ключами.

Приложение хочет получить список всех комнат и их меток, но должно отличать комнаты без меток от комнат, которые были удалены. Если ВЫБРАТЬ...FOR UPDATE не используется, что может произойти:

  • Изначально:
    • rooms содержит [id = 1]
    • tags содержит [id = 1, name = 'cats']
    • room_tags содержит [room_id = 1, tag_id = 1]
  • Тема 1: SELECT id FROM room;
    • возвращает [id = 1]
  • Тема 2: УДАЛИТЬ ИЗ room_tags WHERE room_id = 1;
  • Тема 2: УДАЛИТЬ ИЗ комнат, ГДЕ id = 1;
  • Поток 2: [совершает транзакцию]
  • Поток 1: ВЫБЕРИТЕ tags.name ИЗ room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;
    • возвращает пустой список

Теперь поток 1 считает, что у комнаты 1 нет тегов, но на самом деле комната была удалена. Чтобы решить эту проблему, поток 1 должен SELECT id FROM room FOR UPDATE, тем самым предотвращая удаление потоком 2 из roomдо тех пор, пока поток 1 не завершит работу. Это правильно?

Вопрос 2: Когда следует использовать SERIALIZABLEизоляцию транзакций по сравнению с READ_COMMITTEDс SELECT ... FOR UPDATE?

Ожидается, что ответы будут переносимыми (не зависят от базы данных). Если это невозможно, объясните, почему.

106
задан Laurenz Albe 18 February 2019 в 17:32
поделиться