我试图了解 SSI 在 Postgres 中的实际行为方式。我的理解是,如果我有两个事务与同一个表交互,但事务没有与表中的相同行交互,那么不会发生异常。
但是,我正在运行以下测试,其中事务一执行以下操作:
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()
当上面的第一个事务处于休眠状态时,我运行第二个事务:
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()
在这种情况下,第二个事务只涉及 class = 2 的行,而第一个事务只涉及 class = 1 的行。但这会导致第一个事务失败,并出现以下异常:
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
非常简单,如下所示:
class value
1 10
1 20
2 100
2 200
除了标准engine = psycopg2.connect
设置之外,我还在运行上述代码之前使用此行设置事务隔离级别:
engine.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE)