Hi,
Prompted by Andres Freund's comments on my Freezing without Write I/O
patch, I realized that there's there's an existing bug in the way
predicate locking handles freezing (or rather, it doesn't handle it).
When a tuple is predicate-locked, the key of the lock is ctid+xmin.
However, when a tuple is frozen, its xmin is changed to FrozenXid. That
effectively invalidates any predicate lock on the tuple, as checking for
a lock on the same tuple later won't find it as the xmin is different.
Attached is an isolationtester spec to demonstrate this.
- Heikki
# Test predicate locks with freezing
#
# This test has two serializable transactions. Both select two rows
# from the table, and then update one of them.
# If these were serialized (run one at a time), the transaction that
# runs later would see one of the rows to be updated.
#
# Any overlap between the transactions must cause a serialization failure.
#
# Normally that works, but freezing a tuple screws up predicate locking.
# After freezing a tuple, any predicate locks on it are effectively lost.
setup
{
CREATE TABLE test (i int PRIMARY KEY, t text);
INSERT INTO test VALUES (5, 'apple'), (7, 'pear'), (11, 'banana');
}
teardown
{
DROP TABLE test;
}
session "s1"
setup { BEGIN ISOLATION LEVEL SERIALIZABLE; set enable_seqscan=off;}
step "r1" { SELECT * FROM test WHERE i IN (5, 7) }
step "w1" { UPDATE test SET t = 'pear_xact1' WHERE i = 7 }
step "c1" { COMMIT; }
session "s2"
setup { BEGIN ISOLATION LEVEL SERIALIZABLE; set enable_seqscan=off;}
step "r2" { SELECT * FROM test WHERE i IN (5, 7) }
step "w2" { UPDATE test SET t = 'apple_xact2' WHERE i = 5 }
step "c2" { COMMIT; }
session "freezer"
step "freeze" { VACUUM FREEZE test; }
# This should cause an serialization error - and it does if you remove the
# "freeze" step.
permutation "r1" "r2" "freeze" "w1" "w2" "c1" "c2"
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers