I must be missing something about PostgreSQL and two phase commit with PREPARE TRANSACTION.
The following SQL :
BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
Gives the follwing locks :
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
As soon as the transaction is prepared :
PREPARE TRANSACTION 'TEST'
the lock are gone.
Because there is small delay that occurs between PREPARE and COMMIT, another query could get an older version of the record.
Is there a configuration setting to avoid this behavior or is it by design ?
Thanks in advance.
EDIT : I'm using PostgreSQL 9.2.2 on Windows x64 (PostgreSQL 9.2.2, compiled by Visual C++ build 1600, 64-bit)
EDIT 2 : Following is the full test case :
Issue the following in new session :
BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
PREPARE TRANSACTION 'TEST';
Then in another new session :
SELECT * FROM person.tcities
You'll get the old version of the records.