Postgresql 准备事务释放锁?

Postgresql 准备事务释放锁?,postgresql,transactions,msdtc,2phase-commit,Postgresql,Transactions,Msdtc,2phase Commit,我一定是遗漏了一些关于PostgreSQL和带PREPARE事务的两阶段提交的内容 以下SQL语句: BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1 提供以下锁: 4092 Private 329373 acc 15/53295 RowExclus

我一定是遗漏了一些关于PostgreSQL和带PREPARE事务的两阶段提交的内容

以下SQL语句:

BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
提供以下锁:

4092    Private 329373  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092    Private 329369  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092    Private 328704  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092    Private 327169  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092            acc 15/53295    15/53295    ExclusiveLock   Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092    Private 329377  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092            acc     15/53295    ExclusiveLock   Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
一旦交易准备就绪:

PREPARE TRANSACTION 'TEST'
锁不见了

因为在准备和提交之间有很小的延迟,所以另一个查询可能会获得旧版本的记录

是否有一个配置设置来避免这种行为,还是出于设计

提前谢谢

<> > >编辑< /St>:我在Windows X64(PostgreSQL 1600, 64)上使用PostgreSQL 92.2(VisualC++构建Buffice) 编辑2:以下是完整的测试用例:

在新一届会议上发布以下内容:

BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
PREPARE TRANSACTION 'TEST';
SELECT * FROM person.tcities
然后在另一个新的会议上:

BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
PREPARE TRANSACTION 'TEST';
SELECT * FROM person.tcities

您将获得旧版本的记录。

我无法在PostgreSQL 9.2上重现所描述的行为:

 CREATE TABLE prep_test AS SELECT generate_series(1,10) AS x;

 BEGIN;
 UPDATE prep_test SET x = x*10;
 PREPARE TRANSACTION 'test';
然后在第二次会议上:

 UPDATE prep_test SET x = x*20;
块,如预期的那样,直到我
提交准备好的“测试”
回滚准备好的“测试”

在测试可序列化隔离时,我也得到了预期的结果:

A# BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
B# BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
A# INSERT INTO prep_test(x) VALUES (42);
B# INSERT INTO prep_test(x) VALUES (43);
A# SELECT count(x) FROM prep_test;
B# SELECT count(x) FROM prep_test;
A# PREPARE TRANSACTION 'test';
B# COMMIT;
B
失败,出现可序列化错误,与预期完全一致。如果B尝试
准备事务
也会发生同样的情况

使用测试用例更新问题后

您的测试用例在我看来很好(它应该完全按照描述的那样运行,并且执行时不会出错)

准备事务
不是提交。您仍然可以
准备回滚
。因此,PostgreSQL无法显示更改的行,除非您执行最后的
提交准备
,否则,如果您读取行,然后执行
回滚准备
,则会出现脏读异常

如果在运行第二个命令之前没有在第一个会话中
准备事务
,那么您的测试CAE将得到相同的结果。它与准备好的交易无关。您只是没有看到行被未提交的事务更改,这是完全正常的


如果两个事务都是可序列化的,那么仍然可以。可序列化性要求存在一个有效的顺序,在该顺序中并发事务可以连续发生以产生相同的结果。在这里,这是显而易见的:首先是
选择
,然后是
更新
。当
SELECT
发生时,事务仍同时发生,因为使用
PREPARE transaction
准备的事务在提交或回滚之前仍处于打开状态。

PostgreSQL版本?有没有可能您使用的是旧版本?@Graig Ringer:我已经在Windows上更新了我的问题=>9.2.2。@Graig Ringer:更新块,但不选择。@omatrot请在您的问题中显示完整的测试用例,因为这里的测试都很好。更新后请在这里发表评论,我会看一看。我已经添加了完整的测试用例。我也理解了为什么这种行为是这样的:PostgreSQL使用的MVCC锁定模型。我以前主要使用MS Sql Server,所以这对我来说是新的。@Graig Ringer:你说得对,这与准备好的事务无关。我说锁不见了是不对的。它们不再出现在“锁定服务器状态”窗口中。