Postgres Serializable 似乎不像描述的那样工作

Posted

技术标签:

【中文标题】Postgres Serializable 似乎不像描述的那样工作【英文标题】:Postgres Serializable does not seem to work as described 【发布时间】:2020-04-04 00:57:54 【问题描述】:

我是 Postgres 的新手,过去没有仔细研究过事务隔离。但是,根据 Postgres 文档,我没有看到我期望的行为。特别是,我似乎没有收到过时读取预期的错误。这是针对 Postgres 12 的。

假设一个表如下

CREATE TABLE public.transactiontest (id int8 NULL, col_a varchar NULL);
INSERT INTO public.transactiontest (id, col_a) VALUES (1, 'aaa'), (2, 'bbb');

在两个会话上执行...

--Session 1
START TRANSACTION ISOLATION LEVEL SERIALIZABLE; --1
SELECT id, col_a FROM public.transactiontest; --2

--Session 2
START TRANSACTION ISOLATION LEVEL SERIALIZABLE; --3
SELECT id, col_a FROM public.transactiontest; --4

--Session 1
UPDATE public.transactiontest SET col_a = 'ccc' where id = 1; --5
COMMIT; --6

--Session 2
COMMIT; --7

我原以为我会在第 7 行得到一个错误,但那里的提交通过了。看来这会违反文档

好像交易是一个接一个地,连续地执行, 而不是同时进行。

因为将会话 1 然后 2 排序会在第 4 行给出不同的结果,而不是排序 2 然后 1。

我不明白什么?

【问题讨论】:

【参考方案1】:

如果会话 2 在会话 1 之前运行,结果将是相同的。

因此,“第一个 session2,然后是 session 1”的执行是工作负载的序列化

这意味着工作负载是可序列化的。

实际上会话 1 在会话 2 之前开始并不重要。只要有等效的串行执行,我们就很好。

【讨论】:

是的,抱歉,我在更新声明中出错了。我已经修复了它,所以现在值从初始值改变了。这将如何影响您的解释? 没有区别。自己尝试一下:首先就像您在问题中所做的那样,然后序列化(首先是会话 2 中的所有语句,然后是会话 1 中的所有语句)。你会看到两种情况下的结果是一样的。 如果我在会话 2 之前运行会话 1,我将在会话 2 中读取的值将是“ccc”。做相反的事情,我会读“aaa”。 没错。它与所有串行执行不不一致,因为它与一个串行执行一致。 当“Heureka”来袭时,看到那道闪光总是很高兴。值得努力:^)

以上是关于Postgres Serializable 似乎不像描述的那样工作的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 左外连接似乎没有使用表索引

Postgres:当公共模式上存在表时,关系不存在错误

无法公开 AWS Aurora Postgres RDS

Postgres 物化视图或 CREATE TABLE AS 如果不增量更新?

不同步时如何重置postgres的主键序列?

不同步时如何重置postgres的主键序列?