From: Alvaro Herrera Date: Fri, 4 Oct 2013 17:24:46 +0000 (-0300) Subject: Make some isolationtester specs more complete X-Git-Tag: REL9_3_1~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ac659d4a5a57278cc6c840d4ae64e8e142714e3;p=postgresql Make some isolationtester specs more complete Also, make sure they pass on all transaction isolation levels. --- diff --git a/src/test/isolation/expected/fk-deadlock2_1.out b/src/test/isolation/expected/fk-deadlock2_1.out index 382734811c..384bb9d742 100644 --- a/src/test/isolation/expected/fk-deadlock2_1.out +++ b/src/test/isolation/expected/fk-deadlock2_1.out @@ -19,6 +19,31 @@ step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: current transaction is aborted, commands ignored until end of transaction block step s2c: COMMIT; +starting permutation: s1u1 s1u2 s2u1 s2u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s1u2 s2u1 s2u2 s2c s1c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s2u1 s1u2 s1c s2u2 s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s2u1 s1u2 s2u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s1u1 s2u1 s1u2 s2u2 s2c s1c step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; @@ -29,6 +54,13 @@ step s1u2: <... completed> error in steps s2c s1u2: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s1u1 s2u1 s2u2 s1u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s1u1 s2u1 s2u2 s1u2 s2c s1c step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; @@ -48,6 +80,19 @@ step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: could not serialize access due to read/write dependencies among transactions step s1c: COMMIT; +starting permutation: s2u1 s1u1 s1u2 s1c s2u2 s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s2u1 s1u1 s1u2 s2u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s1u1 s1u2 s2u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; @@ -58,6 +103,13 @@ step s1u2: <... completed> error in steps s2c s1u2: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s2u1 s1u1 s2u2 s1u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s1u1 s2u2 s1u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; @@ -77,6 +129,13 @@ step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: could not serialize access due to read/write dependencies among transactions step s1c: COMMIT; +starting permutation: s2u1 s2u2 s1u1 s1u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s2u2 s1u1 s1u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; diff --git a/src/test/isolation/expected/fk-deadlock2_2.out b/src/test/isolation/expected/fk-deadlock2_2.out index b6be4b9892..b6538a5751 100644 --- a/src/test/isolation/expected/fk-deadlock2_2.out +++ b/src/test/isolation/expected/fk-deadlock2_2.out @@ -19,6 +19,31 @@ step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: current transaction is aborted, commands ignored until end of transaction block step s2c: COMMIT; +starting permutation: s1u1 s1u2 s2u1 s2u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s1u2 s2u1 s2u2 s2c s1c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s2u1 s1u2 s1c s2u2 s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s1u1 s2u1 s1u2 s2u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s1u1 s2u1 s1u2 s2u2 s2c s1c step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; @@ -29,6 +54,13 @@ step s1u2: <... completed> error in steps s2c s1u2: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s1u1 s2u1 s2u2 s1u2 s1c s2c +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s1u1 s2u1 s2u2 s1u2 s2c s1c step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; @@ -48,6 +80,19 @@ step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s2u1 s1u1 s1u2 s1c s2u2 s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + +starting permutation: s2u1 s1u1 s1u2 s2u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s1u1 s1u2 s2u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; @@ -58,6 +103,13 @@ step s1u2: <... completed> error in steps s2c s1u2: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s2u1 s1u1 s2u2 s1u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s1u1 s2u2 s1u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; @@ -77,6 +129,13 @@ step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s2u1 s2u2 s1u1 s1u2 s1c s2c +step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +step s1u1: UPDATE A SET Col1 = 1 WHERE AID = 1; +step s1u2: UPDATE B SET Col2 = 1 WHERE BID = 2; +invalid permutation detected + starting permutation: s2u1 s2u2 s1u1 s1u2 s2c s1c step s2u1: UPDATE B SET Col2 = 1 WHERE BID = 2; step s2u2: UPDATE B SET Col2 = 1 WHERE BID = 2; diff --git a/src/test/isolation/expected/fk-deadlock_1.out b/src/test/isolation/expected/fk-deadlock_1.out index d648e48c48..6687505b59 100644 --- a/src/test/isolation/expected/fk-deadlock_1.out +++ b/src/test/isolation/expected/fk-deadlock_1.out @@ -14,7 +14,33 @@ step s1u: UPDATE parent SET aux = 'bar'; step s2i: INSERT INTO child VALUES (2, 1); step s1c: COMMIT; step s2u: UPDATE parent SET aux = 'baz'; -ERROR: could not serialize access due to read/write dependencies among transactions +ERROR: could not serialize access due to concurrent update +step s2c: COMMIT; + +starting permutation: s1i s1u s2i s2u s1c s2c +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s1c: COMMIT; +step s2u: <... completed> +error in steps s1c s2u: ERROR: could not serialize access due to concurrent update +step s2c: COMMIT; + +starting permutation: s1i s1u s2i s2u s2c s1c +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +invalid permutation detected + +starting permutation: s1i s2i s1u s1c s2u s2c +step s1i: INSERT INTO child VALUES (1, 1); +step s2i: INSERT INTO child VALUES (2, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s1c: COMMIT; +step s2u: UPDATE parent SET aux = 'baz'; +ERROR: could not serialize access due to concurrent update step s2c: COMMIT; starting permutation: s1i s2i s1u s2u s1c s2c @@ -27,6 +53,20 @@ step s2u: <... completed> error in steps s1c s2u: ERROR: could not serialize access due to concurrent update step s2c: COMMIT; +starting permutation: s1i s2i s1u s2u s2c s1c +step s1i: INSERT INTO child VALUES (1, 1); +step s2i: INSERT INTO child VALUES (2, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s2u: UPDATE parent SET aux = 'baz'; +invalid permutation detected + +starting permutation: s1i s2i s2u s1u s1c s2c +step s1i: INSERT INTO child VALUES (1, 1); +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s1u: UPDATE parent SET aux = 'bar'; +invalid permutation detected + starting permutation: s1i s2i s2u s1u s2c s1c step s1i: INSERT INTO child VALUES (1, 1); step s2i: INSERT INTO child VALUES (2, 1); @@ -37,6 +77,24 @@ step s1u: <... completed> error in steps s2c s1u: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s1i s2i s2u s2c s1u s1c +step s1i: INSERT INTO child VALUES (1, 1); +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s2c: COMMIT; +step s1u: UPDATE parent SET aux = 'bar'; +ERROR: could not serialize access due to concurrent update +step s1c: COMMIT; + +starting permutation: s2i s1i s1u s1c s2u s2c +step s2i: INSERT INTO child VALUES (2, 1); +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s1c: COMMIT; +step s2u: UPDATE parent SET aux = 'baz'; +ERROR: could not serialize access due to concurrent update +step s2c: COMMIT; + starting permutation: s2i s1i s1u s2u s1c s2c step s2i: INSERT INTO child VALUES (2, 1); step s1i: INSERT INTO child VALUES (1, 1); @@ -47,6 +105,20 @@ step s2u: <... completed> error in steps s1c s2u: ERROR: could not serialize access due to concurrent update step s2c: COMMIT; +starting permutation: s2i s1i s1u s2u s2c s1c +step s2i: INSERT INTO child VALUES (2, 1); +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s2u: UPDATE parent SET aux = 'baz'; +invalid permutation detected + +starting permutation: s2i s1i s2u s1u s1c s2c +step s2i: INSERT INTO child VALUES (2, 1); +step s1i: INSERT INTO child VALUES (1, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s1u: UPDATE parent SET aux = 'bar'; +invalid permutation detected + starting permutation: s2i s1i s2u s1u s2c s1c step s2i: INSERT INTO child VALUES (2, 1); step s1i: INSERT INTO child VALUES (1, 1); @@ -57,11 +129,45 @@ step s1u: <... completed> error in steps s2c s1u: ERROR: could not serialize access due to concurrent update step s1c: COMMIT; +starting permutation: s2i s1i s2u s2c s1u s1c +step s2i: INSERT INTO child VALUES (2, 1); +step s1i: INSERT INTO child VALUES (1, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s2c: COMMIT; +step s1u: UPDATE parent SET aux = 'bar'; +ERROR: could not serialize access due to concurrent update +step s1c: COMMIT; + +starting permutation: s2i s2u s1i s1u s1c s2c +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +invalid permutation detected + +starting permutation: s2i s2u s1i s1u s2c s1c +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; +step s2c: COMMIT; +step s1u: <... completed> +error in steps s2c s1u: ERROR: could not serialize access due to concurrent update +step s1c: COMMIT; + starting permutation: s2i s2u s1i s2c s1u s1c step s2i: INSERT INTO child VALUES (2, 1); step s2u: UPDATE parent SET aux = 'baz'; step s1i: INSERT INTO child VALUES (1, 1); step s2c: COMMIT; step s1u: UPDATE parent SET aux = 'bar'; -ERROR: could not serialize access due to read/write dependencies among transactions +ERROR: could not serialize access due to concurrent update +step s1c: COMMIT; + +starting permutation: s2i s2u s2c s1i s1u s1c +step s2i: INSERT INTO child VALUES (2, 1); +step s2u: UPDATE parent SET aux = 'baz'; +step s2c: COMMIT; +step s1i: INSERT INTO child VALUES (1, 1); +step s1u: UPDATE parent SET aux = 'bar'; step s1c: COMMIT; diff --git a/src/test/isolation/expected/fk-deadlock_2.out b/src/test/isolation/expected/fk-deadlock_2.out deleted file mode 100644 index 503a7d2823..0000000000 --- a/src/test/isolation/expected/fk-deadlock_2.out +++ /dev/null @@ -1,67 +0,0 @@ -Parsed test spec with 2 sessions - -starting permutation: s1i s1u s1c s2i s2u s2c -step s1i: INSERT INTO child VALUES (1, 1); -step s1u: UPDATE parent SET aux = 'bar'; -step s1c: COMMIT; -step s2i: INSERT INTO child VALUES (2, 1); -step s2u: UPDATE parent SET aux = 'baz'; -step s2c: COMMIT; - -starting permutation: s1i s1u s2i s1c s2u s2c -step s1i: INSERT INTO child VALUES (1, 1); -step s1u: UPDATE parent SET aux = 'bar'; -step s2i: INSERT INTO child VALUES (2, 1); -step s1c: COMMIT; -step s2u: UPDATE parent SET aux = 'baz'; -ERROR: could not serialize access due to concurrent update -step s2c: COMMIT; - -starting permutation: s1i s2i s1u s2u s1c s2c -step s1i: INSERT INTO child VALUES (1, 1); -step s2i: INSERT INTO child VALUES (2, 1); -step s1u: UPDATE parent SET aux = 'bar'; -step s2u: UPDATE parent SET aux = 'baz'; -step s1c: COMMIT; -step s2u: <... completed> -error in steps s1c s2u: ERROR: could not serialize access due to concurrent update -step s2c: COMMIT; - -starting permutation: s1i s2i s2u s1u s2c s1c -step s1i: INSERT INTO child VALUES (1, 1); -step s2i: INSERT INTO child VALUES (2, 1); -step s2u: UPDATE parent SET aux = 'baz'; -step s1u: UPDATE parent SET aux = 'bar'; -step s2c: COMMIT; -step s1u: <... completed> -error in steps s2c s1u: ERROR: could not serialize access due to concurrent update -step s1c: COMMIT; - -starting permutation: s2i s1i s1u s2u s1c s2c -step s2i: INSERT INTO child VALUES (2, 1); -step s1i: INSERT INTO child VALUES (1, 1); -step s1u: UPDATE parent SET aux = 'bar'; -step s2u: UPDATE parent SET aux = 'baz'; -step s1c: COMMIT; -step s2u: <... completed> -error in steps s1c s2u: ERROR: could not serialize access due to concurrent update -step s2c: COMMIT; - -starting permutation: s2i s1i s2u s1u s2c s1c -step s2i: INSERT INTO child VALUES (2, 1); -step s1i: INSERT INTO child VALUES (1, 1); -step s2u: UPDATE parent SET aux = 'baz'; -step s1u: UPDATE parent SET aux = 'bar'; -step s2c: COMMIT; -step s1u: <... completed> -error in steps s2c s1u: ERROR: could not serialize access due to concurrent update -step s1c: COMMIT; - -starting permutation: s2i s2u s1i s2c s1u s1c -step s2i: INSERT INTO child VALUES (2, 1); -step s2u: UPDATE parent SET aux = 'baz'; -step s1i: INSERT INTO child VALUES (1, 1); -step s2c: COMMIT; -step s1u: UPDATE parent SET aux = 'bar'; -ERROR: could not serialize access due to concurrent update -step s1c: COMMIT; diff --git a/src/test/isolation/expected/lock-update-delete.out b/src/test/isolation/expected/lock-update-delete.out index c4248657df..344a6ecb9a 100644 --- a/src/test/isolation/expected/lock-update-delete.out +++ b/src/test/isolation/expected/lock-update-delete.out @@ -1,65 +1,213 @@ Parsed test spec with 2 sessions -starting permutation: s1b s2b s1s s2u s2d s1l s2c s1c -step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; +starting permutation: s2b s1l s2u s2_blocker1 s2_unlock s2c +pg_advisory_lock + + step s2b: BEGIN; -step s1s: SELECT * FROM foo; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2c: COMMIT; +step s1l: <... completed> key value -1 1 + +starting permutation: s2b s1l s2u s2_blocker2 s2_unlock s2c +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; step s2u: UPDATE foo SET value = 2 WHERE key = 1; -step s2d: DELETE FROM foo; -step s1l: SELECT * FROM foo FOR KEY SHARE; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t step s2c: COMMIT; step s1l: <... completed> -error in steps s2c s1l: ERROR: could not serialize access due to concurrent update -step s1c: COMMIT; +key value + + +starting permutation: s2b s1l s2u s2_blocker3 s2_unlock s2c +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 +step s2c: COMMIT; + +starting permutation: s2b s1l s2u s2_blocker1 s2_unlock s2r +pg_advisory_lock -starting permutation: s1b s2b s1s s2u s2d s1l s2r s1c -step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; + step s2b: BEGIN; -step s1s: SELECT * FROM foo; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2r: ROLLBACK; +step s1l: <... completed> key value 1 1 + +starting permutation: s2b s1l s2u s2_blocker2 s2_unlock s2r +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; step s2u: UPDATE foo SET value = 2 WHERE key = 1; -step s2d: DELETE FROM foo; -step s1l: SELECT * FROM foo FOR KEY SHARE; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t step s2r: ROLLBACK; step s1l: <... completed> key value 1 1 -step s1c: COMMIT; -starting permutation: s1b s2b s1s s2u s2u2 s1l s2c s1c -step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; +starting permutation: s2b s1l s2u s2_blocker3 s2_unlock s2r +pg_advisory_lock + + step s2b: BEGIN; -step s1s: SELECT * FROM foo; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> key value 1 1 +step s2r: ROLLBACK; + +starting permutation: s2b s1l s2u s2_blocker1 s2c s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; step s2u: UPDATE foo SET value = 2 WHERE key = 1; -step s2u2: UPDATE foo SET key = 2 WHERE key = 1; -step s1l: SELECT * FROM foo FOR KEY SHARE; +step s2_blocker1: DELETE FROM foo; step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t step s1l: <... completed> -error in steps s2c s1l: ERROR: could not serialize access due to concurrent update -step s1c: COMMIT; +key value + + +starting permutation: s2b s1l s2u s2_blocker2 s2c s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value -starting permutation: s1b s2b s1s s2u s2u2 s1l s2r s1c -step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; + +starting permutation: s2b s1l s2u s2_blocker3 s2c s2_unlock +pg_advisory_lock + + step s2b: BEGIN; -step s1s: SELECT * FROM foo; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 2 + +starting permutation: s2b s1l s2u s2_blocker1 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> key value 1 1 + +starting permutation: s2b s1l s2u s2_blocker2 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; step s2u: UPDATE foo SET value = 2 WHERE key = 1; -step s2u2: UPDATE foo SET key = 2 WHERE key = 1; -step s1l: SELECT * FROM foo FOR KEY SHARE; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 + +starting permutation: s2b s1l s2u s2_blocker3 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t step s1l: <... completed> key value 1 1 -step s1c: COMMIT; diff --git a/src/test/isolation/expected/lock-update-delete_1.out b/src/test/isolation/expected/lock-update-delete_1.out new file mode 100644 index 0000000000..4203573b9c --- /dev/null +++ b/src/test/isolation/expected/lock-update-delete_1.out @@ -0,0 +1,207 @@ +Parsed test spec with 2 sessions + +starting permutation: s2b s1l s2u s2_blocker1 s2_unlock s2c +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2c: COMMIT; +step s1l: <... completed> +error in steps s2c s1l: ERROR: could not serialize access due to concurrent update + +starting permutation: s2b s1l s2u s2_blocker2 s2_unlock s2c +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2c: COMMIT; +step s1l: <... completed> +error in steps s2c s1l: ERROR: could not serialize access due to concurrent update + +starting permutation: s2b s1l s2u s2_blocker3 s2_unlock s2c +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 +step s2c: COMMIT; + +starting permutation: s2b s1l s2u s2_blocker1 s2_unlock s2r +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2r: ROLLBACK; +step s1l: <... completed> +key value + +1 1 + +starting permutation: s2b s1l s2u s2_blocker2 s2_unlock s2r +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s2r: ROLLBACK; +step s1l: <... completed> +key value + +1 1 + +starting permutation: s2b s1l s2u s2_blocker3 s2_unlock s2r +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 +step s2r: ROLLBACK; + +starting permutation: s2b s1l s2u s2_blocker1 s2c s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +error in steps s2_unlock s1l: ERROR: could not serialize access due to concurrent update + +starting permutation: s2b s1l s2u s2_blocker2 s2c s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +error in steps s2_unlock s1l: ERROR: could not serialize access due to concurrent update + +starting permutation: s2b s1l s2u s2_blocker3 s2c s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2c: COMMIT; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +error in steps s2_unlock s1l: ERROR: could not serialize access due to concurrent update + +starting permutation: s2b s1l s2u s2_blocker1 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker1: DELETE FROM foo; +step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 + +starting permutation: s2b s1l s2u s2_blocker2 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker2: UPDATE foo SET key = 2 WHERE key = 1; +step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 + +starting permutation: s2b s1l s2u s2_blocker3 s2r s2_unlock +pg_advisory_lock + + +step s2b: BEGIN; +step s1l: SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s2_blocker3: UPDATE foo SET value = 2 WHERE key = 1; +step s2r: ROLLBACK; +step s2_unlock: SELECT pg_advisory_unlock(0); +pg_advisory_unlock + +t +step s1l: <... completed> +key value + +1 1 diff --git a/src/test/isolation/expected/lock-update-traversal.out b/src/test/isolation/expected/lock-update-traversal.out index c8e90661b2..e4e6405757 100644 --- a/src/test/isolation/expected/lock-update-traversal.out +++ b/src/test/isolation/expected/lock-update-traversal.out @@ -1,6 +1,6 @@ Parsed test spec with 2 sessions -starting permutation: s1b s2b s1s s2u s1l s2c s2d s1c +starting permutation: s1b s2b s1s s2u s1l s2c s2d1 s1c step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; step s2b: BEGIN; step s1s: SELECT * FROM foo; @@ -13,6 +13,39 @@ key value 1 1 step s2c: COMMIT; -step s2d: DELETE FROM foo WHERE key = 1; +step s2d1: DELETE FROM foo WHERE key = 1; +step s1c: COMMIT; +step s2d1: <... completed> + +starting permutation: s1b s2b s1s s2u s1l s2c s2d2 s1c +step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s2b: BEGIN; +step s1s: SELECT * FROM foo; +key value + +1 1 +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s1l: SELECT * FROM foo FOR KEY SHARE; +key value + +1 1 +step s2c: COMMIT; +step s2d2: UPDATE foo SET key = 3 WHERE key = 1; +step s1c: COMMIT; +step s2d2: <... completed> + +starting permutation: s1b s2b s1s s2u s1l s2c s2d3 s1c +step s1b: BEGIN ISOLATION LEVEL REPEATABLE READ; +step s2b: BEGIN; +step s1s: SELECT * FROM foo; +key value + +1 1 +step s2u: UPDATE foo SET value = 2 WHERE key = 1; +step s1l: SELECT * FROM foo FOR KEY SHARE; +key value + +1 1 +step s2c: COMMIT; +step s2d3: UPDATE foo SET value = 3 WHERE key = 1; step s1c: COMMIT; -step s2d: <... completed> diff --git a/src/test/isolation/specs/lock-update-delete.spec b/src/test/isolation/specs/lock-update-delete.spec index 4b9a5a64ed..b7b796fc01 100644 --- a/src/test/isolation/specs/lock-update-delete.spec +++ b/src/test/isolation/specs/lock-update-delete.spec @@ -1,10 +1,23 @@ -# If we update a tuple, and then delete (or update that touches the key) it, -# and later somebody tries to come along and traverse that update chain, -# he should get an error when locking the latest version, if the delete -# committed; or succeed, when the deleting transaction rolls back. +# This test verifies behavior when traversing an update chain during +# locking an old version of the tuple. There are three tests here: +# 1. update the tuple, then delete it; a second transaction locks the +# first version. This should raise an error if the DELETE succeeds, +# but be allowed to continue if it aborts. +# 2. Same as (1), except that instead of deleting the tuple, we merely +# update its key. The behavior should be the same as for (1). +# 3. Same as (2), except that we update the tuple without modifying its +# key. In this case, no error should be raised. +# When run in REPEATABLE READ or SERIALIZABLE transaction isolation levels, all +# permutations that commit s2 cause a serializability error; all permutations +# that rollback s2 can get through. +# +# We use an advisory lock (which is locked during s1's setup) to let s2 obtain +# its snapshot early and only allow it to actually traverse the update chain +# when s1 is done creating it. setup { + DROP TABLE IF EXISTS foo; CREATE TABLE foo ( key int PRIMARY KEY, value int @@ -19,20 +32,30 @@ teardown } session "s1" -step "s1b" { BEGIN ISOLATION LEVEL REPEATABLE READ; } -step "s1s" { SELECT * FROM foo; } # obtain snapshot -step "s1l" { SELECT * FROM foo FOR KEY SHARE; } # obtain lock -step "s1c" { COMMIT; } +# obtain lock on the tuple, traversing its update chain +step "s1l" { SELECT * FROM foo WHERE pg_advisory_xact_lock(0) IS NOT NULL AND key = 1 FOR KEY SHARE; } session "s2" +setup { SELECT pg_advisory_lock(0); } step "s2b" { BEGIN; } step "s2u" { UPDATE foo SET value = 2 WHERE key = 1; } -step "s2d" { DELETE FROM foo; } -step "s2u2" { UPDATE foo SET key = 2 WHERE key = 1; } +step "s2_blocker1" { DELETE FROM foo; } +step "s2_blocker2" { UPDATE foo SET key = 2 WHERE key = 1; } +step "s2_blocker3" { UPDATE foo SET value = 2 WHERE key = 1; } +step "s2_unlock" { SELECT pg_advisory_unlock(0); } step "s2c" { COMMIT; } step "s2r" { ROLLBACK; } -permutation "s1b" "s2b" "s1s" "s2u" "s2d" "s1l" "s2c" "s1c" -permutation "s1b" "s2b" "s1s" "s2u" "s2d" "s1l" "s2r" "s1c" -permutation "s1b" "s2b" "s1s" "s2u" "s2u2" "s1l" "s2c" "s1c" -permutation "s1b" "s2b" "s1s" "s2u" "s2u2" "s1l" "s2r" "s1c" +permutation "s2b" "s1l" "s2u" "s2_blocker1" "s2_unlock" "s2c" +permutation "s2b" "s1l" "s2u" "s2_blocker2" "s2_unlock" "s2c" +permutation "s2b" "s1l" "s2u" "s2_blocker3" "s2_unlock" "s2c" +permutation "s2b" "s1l" "s2u" "s2_blocker1" "s2_unlock" "s2r" +permutation "s2b" "s1l" "s2u" "s2_blocker2" "s2_unlock" "s2r" +permutation "s2b" "s1l" "s2u" "s2_blocker3" "s2_unlock" "s2r" + +permutation "s2b" "s1l" "s2u" "s2_blocker1" "s2c" "s2_unlock" +permutation "s2b" "s1l" "s2u" "s2_blocker2" "s2c" "s2_unlock" +permutation "s2b" "s1l" "s2u" "s2_blocker3" "s2c" "s2_unlock" +permutation "s2b" "s1l" "s2u" "s2_blocker1" "s2r" "s2_unlock" +permutation "s2b" "s1l" "s2u" "s2_blocker2" "s2r" "s2_unlock" +permutation "s2b" "s1l" "s2u" "s2_blocker3" "s2r" "s2_unlock" diff --git a/src/test/isolation/specs/lock-update-traversal.spec b/src/test/isolation/specs/lock-update-traversal.spec index 6c6c805d50..7042b9399c 100644 --- a/src/test/isolation/specs/lock-update-traversal.spec +++ b/src/test/isolation/specs/lock-update-traversal.spec @@ -1,6 +1,8 @@ -# When a tuple that has been updated is locked, the locking command -# should traverse the update chain; thus, a DELETE should not be able -# to proceed until the lock has been released. +# When a tuple that has been updated is locked, the locking command must +# traverse the update chain; thus, a DELETE (on the newer version of the tuple) +# should not be able to proceed until the lock has been released. An UPDATE +# that changes the key should not be allowed to continue either; but an UPDATE +# that doesn't modify the key should be able to continue immediately. setup { @@ -27,6 +29,10 @@ session "s2" step "s2b" { BEGIN; } step "s2u" { UPDATE foo SET value = 2 WHERE key = 1; } step "s2c" { COMMIT; } -step "s2d" { DELETE FROM foo WHERE key = 1; } +step "s2d1" { DELETE FROM foo WHERE key = 1; } +step "s2d2" { UPDATE foo SET key = 3 WHERE key = 1; } +step "s2d3" { UPDATE foo SET value = 3 WHERE key = 1; } -permutation "s1b" "s2b" "s1s" "s2u" "s1l" "s2c" "s2d" "s1c" +permutation "s1b" "s2b" "s1s" "s2u" "s1l" "s2c" "s2d1" "s1c" +permutation "s1b" "s2b" "s1s" "s2u" "s1l" "s2c" "s2d2" "s1c" +permutation "s1b" "s2b" "s1s" "s2u" "s1l" "s2c" "s2d3" "s1c"