Предотвращает ли SELECT возвращаемые строки от удаления?
Скажи, что у меня есть:
- T1:
SELECT id FROM x WHERE timestamp < y
(возвратыid = [1, 2, 3]
) - T2:
DELETE FROM x WHERE id = 1
- T1:
SELECT timestamp, value FROM x WHERE id = 1
с READ-COMMITTED
изоляция.
Риск 3 возвращает риск пустого результата, или шаг 1 получает некоторый вид блокировки / снимка, который препятствует шагу 2 изменить результат? (Я предполагаю REPEATABLE-READ
буду делать то, что я хочу, но этот вопрос о READ-COMMITTED
).
Я использую postgresql, но меня интересует независимый от БД ответ. Например, если некоторые базы данных блокируют удаление, а другие нет, я хотел бы знать это. Спасибо.
1 ответ
Дело PostgreSQL:
В PostgreSQL чтение строки не приводит к блокировке, которая препятствует одновременному удалению строки:
Если T2 фиксируется до шага 3, T1 увидит его результаты и вернет пустой набор результатов.
Если шаг 3 выполняется до фиксации T2, результаты T2 еще не видны, и запрос вернет соответствующую строку.
Общий случай:
Система баз данных имеет различные способы обеспечения изоляции транзакций, и поведение будет варьироваться в зависимости от используемого метода.
Некоторые системы баз данных, такие как DB2 или Microsoft SQL Server, блокируют строки при их чтении, чтобы предотвратить одновременное обновление.
В таких системах баз данных
DELETE
будет заблокирован, и строка видна в шаге 3.Большинство систем баз данных используют какое-то мульти-управление версиями, то есть они хранят старые версии строк, пока выполняется транзакция, которая изменяет строку.
В таких системах баз данных
DELETE
не блокируется, и результат шага 3 будет зависеть от того, был ли T2 уже зафиксирован.
Решение:
Если вы ищете решение, которое сделало бы поведение детерминированным во всех системах баз данных, вы можете использовать более высокий уровень изоляции или пессимистическую блокировку, указав FOR UPDATE
в SELECT
оператор в шаге 1. Тогда шаг 2 всегда будет блокироваться.