为什么两个具有隔离可序列化的事务在写入不同行时被阻塞
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
);
我无法重现该问题。
查看第一个答案
我的应用程序有交易问题。
我的第一笔交易:
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
);
我无法重现该问题。
查看第一个答案