Postgresql 准备事务释放锁?
我一定是遗漏了一些关于PostgreSQL和带PREPARE事务的两阶段提交的内容 以下SQL语句: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
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:你说得对,这与准备好的事务无关。我说锁不见了是不对的。它们不再出现在“锁定服务器状态”窗口中。