postgres тупик без явной блокировки
Я использую PostgreSQL 9.2 и не использую явную блокировку нигде, ни LOCK
заявление ни SELECT ... FOR UPDATE
, Однако недавно я получил ERROR: 40P01: deadlock detected
, Запрос, в котором была обнаружена взаимоблокировка, помещается в блок транзакции. Во всяком случае, как это получается?
2 ответа
Вам не нужно никаких явных LOCK
зайти в тупик. Вот очень простая демонстрация с нуля только с ВСТАВКАМИ:
create table a(i int primary key);
create table b(i int primary key);
Сессия № 1 делает:
begin;
insert into a values(1);
Затем сессия № 2 делает:
begin;
insert into b values(1);
insert into a values(1);
-- here it goes into waiting for session #1 to finish its transaction
Затем сессия № 1 делает:
insert into b values(1);
И тогда возникает тупик:
ОШИБКА: обнаружен тупик
ДЕТАЛИ: Процесс 9571 ожидает ShareLock для транзакции 4150; заблокирован процессом 9501.
Процесс 9501 ожидает ShareLock для транзакции 4149; заблокирован процессом 9571.
СОВЕТ: см. Журнал сервера для деталей запроса.
То же самое может случиться с простыми ОБНОВЛЕНИЯМИ или комбинацией ОБНОВЛЕНИЙ и ВСТАВКИ. Эти операции принимают неявные блокировки, и если они происходят в разных сеансах в разных порядках, они могут зайти в тупик.
Я бы сначала заподозрил хеш-индексы.
- Переключить любой
hash
Индексам нужноB-tree
- использование
Serializable
уровень изоляции, если это кажется целесообразным.