为什么两个具有隔离可序列化的事务在写入不同行时被阻塞

Why two transactions with isolation serializable are blocked when writing to different lines

我的应用程序有交易问题。

我的第一笔交易:

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
);

所有者可以交换猫 :) 因此,如果可以当前逐步开始两个交易(第一个交易开始 -> 第二个交易开始 -> 第一个交易的 select -> select第二笔交易等)然后第一笔交易结束成功但第二笔交易将失败:

could not serialize access due to read/write dependencies among transactions. Reason code: Canceled on identification as a pivot, during commit attempt

两笔交易换了不同的线路,为什么会出现阻塞?我希望这两项交易都能成功完成。

我会很乐意提供任何帮助! :)

P.S。我正在使用 PostgreSQL

可序列化的隔离级别保证不会出现漏报。它不保证不会出现误报。如果它必须执行后者,时间 and/or 内存使用量可能会爆炸。为使用可序列化隔离而正确编写的代码必须始终准备好重试事务。因此,偶尔由于误报而重试并不是什么大问题,除非它经常发生以致于成为性能问题。

这种类型的误报在微型玩具示例中比在现实世界中更容易发生。

你有 owner(id) 的索引吗?

如果我完全按照上面给出的方式创建 table,我可以重现问题:

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
);

我无法重现该问题。

查看第一个答案