Почему две транзакции с сериализацией изоляции блокируются при записи в разные строки - PullRequest
0 голосов
/ 23 марта 2020

У меня проблема с транзакциями в моем приложении.

Моя первая транзакция:

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM public.owner WHERE id = 15;
UPDATE public.owner SET current_cat = 2 WHERE id = 15;
COMMIT;

Моя вторая транзакция:

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM public.owner WHERE id = 16;
UPDATE public.owner SET current_cat = 4 WHERE id = 16;
COMMIT;

Примерный пример моих таблиц:

CREATE TABLE assortment.cat (
    id int not null,
    name varchar not null
);

CREATE TABLE assortment.owner (
    id int not null,
    fio varchar not null,
    current_cat int not null
);

Владельцы могут поменяться кошками :) Итак, если начинать две транзакции шаг за шагом (начало первой транзакции -> начало второй транзакции -> выбор первой транзакции -> выбор второй транзакции и т.д. c.) Затем завершение первой транзакции прошло успешно, но вторая транзакция не удалась:

не удалось сериализовать доступ из-за зависимостей между операциями чтения / записи. Код причины: Отменено при идентификации как сводной, во время попытки фиксации

Две транзакции изменили разные строки, почему происходит блокировка? Я ожидаю, что обе транзакции будут успешно завершены.

Я буду рад любой помощи! :)

PS Я использую PostgreSQL

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

У вас есть индекс на владельца (id)?

Если я создаю таблицу точно так, как указано выше, я могу воспроизвести проблему:

ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

Но если я создаю ее таким образом:

create table owner
(
id int not null primary key,
fio varchar not null,
current_cat int not null
);

Я не могу воспроизвести проблема.

См. первый ответ в Почему PostgreSQL сериализуемая транзакция воспринимает это как конфликт?

0 голосов
/ 23 марта 2020

Сериализуемый уровень изоляции гарантирует от ложных негативов. Это не гарантирует от ложных срабатываний. Если бы это было необходимо, последнее время и / или использование памяти могло бы взорваться Код, правильно написанный для использования сериализуемой изоляции, всегда должен быть готов повторить транзакции. Поэтому время от времени повторная попытка из-за ложного срабатывания не имеет большого значения, если только это не происходит так часто, как проблема производительности.

Этот тип ложного срабатывания гораздо более вероятен в микроскопических c игрушечных примерах, чем в реальные случаи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...