首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Postgres SSI行为

Postgres SSI行为
EN

Stack Overflow用户
提问于 2019-09-03 18:22:25
回答 1查看 293关注 0票数 2

我试图了解SSI在Postgres中的实际行为。我的理解是,如果有两个事务与同一个表交互,但这些事务没有与表中的相同行交互,那么也不会出现任何例外。

但是,我正在运行以下测试,其中事务一执行以下操作:

代码语言:javascript
复制
cur = engine.cursor()
cur.execute('SELECT SUM(value) FROM mytab WHERE class = 1')
s = cur.fetchall()[0][0]
print('retrieved sum is...')
print(s)
print('sleeping....')
time.sleep(10)
cur.execute('INSERT INTO mytab (class, value) VALUES (%s, %s)', (1, s))
engine.commit()

当上面的第一个事务处于休眠状态时,我运行第二个事务:

代码语言:javascript
复制
cur = engine.cursor()
cur.execute('SELECT SUM(value) FROM mytab WHERE class = 2')
s = cur.fetchall()[0][0]
print('retrieved sum is...')
print(s)
cur.execute('INSERT INTO mytab (class, value) VALUES (%s, %s)', (2, s))
engine.commit()

在这种情况下,第二个事务只接触类= 2的行,而第一个事务只接触类= 1的行。但是,这会导致第一个事务失败,但有以下例外:

代码语言:javascript
复制
could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during write.
HINT:  The transaction might succeed if retried.

作为参考,mytab非常简单,如下所示:

代码语言:javascript
复制
class   value
1   10
1   20
2   100
2   200

除了标准的engine = psycopg2.connect设置之外,在运行上面的代码之前,我还将使用这一行设置事务隔离级别:

代码语言:javascript
复制
engine.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-05 01:23:46

您的理解几乎是正确的,但是SSI算法并不完美,因此总是存在一些错误的风险(例如,正如文档中所指出的,行锁可能被组合成一个页面锁,从而以牺牲精度为代价优化内存)。

这里的行为是谓词锁定实现的一个限制,即:

对于表扫描,整个关系将被锁定。

基本上,在运行第一个查询WHERE class = 1之后,需要检查来自其他事务的未来插入,以确定如果它们是可见的,它们是否满足此条件。实际上,除了最简单的条件外,执行此检查是不实际的或不可能的,因此为了谨慎起见,应该在整个表上使用谓词锁。

细粒度的谓词锁实现是基于索引,因为从B树范围的角度来考虑关系的受影响子集比使用任意WHERE约束要容易得多。

换句话说,如果您在class列上有一个索引--并且您的表中有足够的记录供规划者实际使用--您应该得到您期望的行为。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57776922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档