cockroachdb / cockroach

CockroachDB — the cloud native, distributed SQL database designed for high availability, effortless scale, and control over data placement.
https://www.cockroachlabs.com
Other
29.86k stars 3.77k forks source link

roachtest: implement a pg_isolation_regress runner roachtest #95771

Open nvanbenschoten opened 1 year ago

nvanbenschoten commented 1 year ago

pg_isolation_regress is a multi-connection variant of pg_regress used to test the behavior of concurrent transactions. It contains hundred of test cases for Postgres behavior, each of which exercises a set of ordering permutations.

In https://github.com/cockroachdb/cockroach/issues/95768, we detailed a plan to port pg_regress over to a roachtest. We should do the same for pg_isolation_regress.

Jira issue: CRDB-23727

Epic: CRDB-34183

nvanbenschoten commented 1 year ago

To support pg_isolation_regress, we're going to need to support the pg_catalog.pg_isolation_test_session_is_blocked builtin function, which is used by the test to detect lock contention between sessions.

nvanbenschoten commented 1 year ago

I looked into implementing the pg_catalog.pg_isolation_test_session_is_blocked builtin function. It would be straightforward if https://github.com/cockroachdb/cockroach/issues/98581 was addressed. With that change, we could implement this using a join across crdb_internal.cluster_locks and crdb_internal.cluster_sessions. Something like:

WITH blocked_txn AS (
    SELECT kv_txn::UUID FROM crdb_internal.cluster_sessions WHERE kv_txn IS NOT NULL AND pg_backend_pid = $1
), blocking_txns AS (
    SELECT kv_txn::UUID FROM crdb_internal.cluster_sessions WHERE kv_txn IS NOT NULL AND pg_backend_pid = ANY($2)
), blocked_keys AS (
    SELECT lock_key FROM crdb_internal.cluster_locks WHERE txn_id = (SELECT kv_txn FROM blocked_txn) AND contended AND NOT granted
), blocking_keys AS (
    SELECT lock_key FROM crdb_internal.cluster_locks WHERE txn_id = ANY(SELECT kv_txn FROM blocking_txns) AND contended AND granted
)
SELECT count(*) > 0 FROM blocked_keys JOIN blocking_keys USING (lock_key)
nvanbenschoten commented 8 months ago

Cross-posting from Slack:

We were hoping to use pg_isolation_regress (#95771) to test Read Committed and ensure our error handling and blocking behavior is consistent with PG’s. It turns out that the test suite is more of a stress test of PG and CRDB’s Serializable implementation than it is of weaker isolation levels. And beyond isolation, it’s a great test of PG compatibility. There is still some coverage of RC and Snapshot, and we seem to do well on all of those tests, but they’re not exhaustive.

The cases that are tripping us up are:

  • inconsistent error messaging compared to PG
  • missing deadlock_timeout variable (#116305)
  • detecting serializable conflicts lazily at commit time vs. eagerly
  • releasing locks immediacy on serializable conflict vs. on abort
  • table locks / advisory locks
  • triggers / notify / partitions
  • MERGE statement

For future reference, the changes I ran with to get this far were:

PR 1: https://github.com/cockroachdb/cockroach/pull/116673 PR 2: https://github.com/cockroachdb/cockroach/pull/116708

cockroach diff ``` diff --git a/pkg/kv/kvpb/errors.go b/pkg/kv/kvpb/errors.go index 1b84842a465..6a2acb6411c 100644 --- a/pkg/kv/kvpb/errors.go +++ b/pkg/kv/kvpb/errors.go @@ -773,6 +773,10 @@ func NewTransactionRetryWithProtoRefreshError( } func (e *TransactionRetryWithProtoRefreshError) SafeFormatError(p errors.Printer) (next error) { + if true { + p.Printf("could not serialize access due to read/write dependencies among transactions") + return nil + } if e.MsgRedactable != "" { p.Printf("TransactionRetryWithProtoRefreshError: %s", e.MsgRedactable) } else { diff --git a/pkg/kv/kvserver/txnwait/queue.go b/pkg/kv/kvserver/txnwait/queue.go index d3f19f97c63..bf53a97959b 100644 --- a/pkg/kv/kvserver/txnwait/queue.go +++ b/pkg/kv/kvserver/txnwait/queue.go @@ -127,7 +127,7 @@ func CanPushWithPriority( (pusherIso.ToleratesWriteSkew() && pusherPri >= pusheePri) || // Otherwise, if neither transaction tolerates write skew, let the // PUSH_TIMESTAMP proceed only if the pusher has a higher priority. - (pusherPri > pusheePri) + (pusherPri >= pusheePri) case kvpb.PUSH_TOUCH: return true default: diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go index 657af74d4d3..dbc590ff84a 100644 --- a/pkg/sql/exec_util.go +++ b/pkg/sql/exec_util.go @@ -3320,6 +3320,10 @@ func (m *sessionDataMutator) SetLockTimeout(timeout time.Duration) { m.data.LockTimeout = timeout } +func (m *sessionDataMutator) SetDeadlockTimeout(timeout time.Duration) { + //m.data.LockTimeout = timeout +} + func (m *sessionDataMutator) SetIdleInSessionTimeout(timeout time.Duration) { m.data.IdleInSessionTimeout = timeout } diff --git a/pkg/sql/pgwire/pgerror/flatten.go b/pkg/sql/pgwire/pgerror/flatten.go index 9d321d9ee55..bc3273dcc33 100644 --- a/pkg/sql/pgwire/pgerror/flatten.go +++ b/pkg/sql/pgwire/pgerror/flatten.go @@ -83,9 +83,9 @@ func Flatten(err error) *Error { // TODO(knz): investigate whether 3rd party frameworks parse this // string instead of using the pg code to determine whether to // retry. - if !strings.HasPrefix(resErr.Message, TxnRetryMsgPrefix) { - resErr.Message = TxnRetryMsgPrefix + ": " + resErr.Message - } + //if !strings.HasPrefix(resErr.Message, TxnRetryMsgPrefix) { + // resErr.Message = TxnRetryMsgPrefix + ": " + resErr.Message + //} } return resErr diff --git a/pkg/sql/set_var.go b/pkg/sql/set_var.go index f9e3a644a7d..8cd6c5aeb93 100644 --- a/pkg/sql/set_var.go +++ b/pkg/sql/set_var.go @@ -430,6 +430,20 @@ func lockTimeoutVarSet(ctx context.Context, m sessionDataMutator, s string) erro return nil } +func deadlockTimeoutVarSet(ctx context.Context, m sessionDataMutator, s string) error { + timeout, err := validateTimeoutVar( + m.data.GetIntervalStyle(), + s, + "deadlock_timeout", + ) + if err != nil { + return err + } + + m.SetDeadlockTimeout(timeout) + return nil +} + func idleInSessionTimeoutVarSet(ctx context.Context, m sessionDataMutator, s string) error { timeout, err := validateTimeoutVar( m.data.GetIntervalStyle(), diff --git a/pkg/sql/unsupported_vars.go b/pkg/sql/unsupported_vars.go index b72c5771efa..837df46ba82 100644 --- a/pkg/sql/unsupported_vars.go +++ b/pkg/sql/unsupported_vars.go @@ -78,7 +78,7 @@ var UnsupportedVars = func(ss ...string) map[string]struct{} { "cpu_operator_cost", "cpu_tuple_cost", "cursor_tuple_fraction", - "deadlock_timeout", + // "deadlock_timeout", "debug_deadlocks", "debug_pretty_print", "debug_print_parse", diff --git a/pkg/sql/vars.go b/pkg/sql/vars.go index 25ff977fdbf..ba5afecd267 100644 --- a/pkg/sql/vars.go +++ b/pkg/sql/vars.go @@ -1103,6 +1103,18 @@ var varGen = map[string]sessionVar{ }, }, + // See https://www.postgresql.org/docs/10/runtime-config-locks.html#GUC-DEADLOCK-TIMEOUT + `deadlock_timeout`: { + GetStringVal: makeTimeoutVarGetter(`deadlock_timeout`), + Set: deadlockTimeoutVarSet, + Get: func(evalCtx *extendedEvalContext, _ *kv.Txn) (string, error) { + return "0s", nil + }, + GlobalDefault: func(sv *settings.Values) string { + return "0s" + }, + }, + // See https://www.postgresql.org/docs/12/runtime-config-client.html. `default_table_access_method`: makeCompatStringVar(`default_table_access_method`, `heap`), ```
postgres diff ``` diff --git a/src/test/isolation/expected/nowait-2.out b/src/test/isolation/expected/nowait-2.out index ba18fa77d4..1dc6e1d296 100644 --- a/src/test/isolation/expected/nowait-2.out +++ b/src/test/isolation/expected/nowait-2.out @@ -14,7 +14,7 @@ id|data (1 row) step s2b: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2c: COMMIT; @@ -32,7 +32,7 @@ id|data (1 row) step s2b: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2c: COMMIT; @@ -50,6 +50,6 @@ id|data (1 row) step s1a: SELECT * FROM foo FOR SHARE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2c: COMMIT; diff --git a/src/test/isolation/expected/nowait-3.out b/src/test/isolation/expected/nowait-3.out index 19a5b680bc..0c4797aba8 100644 --- a/src/test/isolation/expected/nowait-3.out +++ b/src/test/isolation/expected/nowait-3.out @@ -9,7 +9,7 @@ id|data step s2a: SELECT * FROM foo FOR UPDATE; step s3a: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2a: <... completed> id|data diff --git a/src/test/isolation/expected/nowait.out b/src/test/isolation/expected/nowait.out index ea1cdf012a..2321a8dde5 100644 --- a/src/test/isolation/expected/nowait.out +++ b/src/test/isolation/expected/nowait.out @@ -24,7 +24,7 @@ id|data (1 row) step s2a: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2b: COMMIT; @@ -36,7 +36,7 @@ id|data (1 row) step s2a: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s2b: COMMIT; step s1b: COMMIT; @@ -48,7 +48,7 @@ id|data (1 row) step s1a: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s1b: COMMIT; step s2b: COMMIT; @@ -60,7 +60,7 @@ id|data (1 row) step s1a: SELECT * FROM foo FOR UPDATE NOWAIT; -ERROR: could not obtain lock on row in relation "foo" +ERROR: could not obtain lock on row (id)=(1) in foo@foo_pkey step s2b: COMMIT; step s1b: COMMIT; diff --git a/src/test/isolation/expected/read-only-anomaly-2.out b/src/test/isolation/expected/read-only-anomaly-2.out index 543ae89747..68eca94a90 100644 --- a/src/test/isolation/expected/read-only-anomaly-2.out +++ b/src/test/isolation/expected/read-only-anomaly-2.out @@ -25,7 +25,7 @@ step s2wx: UPDATE bank_account SET balance = -11 WHERE id = 'X'; step s2c: COMMIT; step s3c: COMMIT; -starting permutation: s2rx s2ry s1ry s1wy s1c s3r s3c s2wx +starting permutation: s2rx s2ry s1ry s1wy s1c s3r s3c s2wx s2c step s2rx: SELECT balance FROM bank_account WHERE id = 'X'; balance ------- @@ -55,4 +55,5 @@ Y | 20 step s3c: COMMIT; step s2wx: UPDATE bank_account SET balance = -11 WHERE id = 'X'; +step s2c: COMMIT; ERROR: could not serialize access due to read/write dependencies among transactions diff --git a/src/test/isolation/expected/simple-write-skew.out b/src/test/isolation/expected/simple-write-skew.out index 835500de6d..5d7680029a 100644 --- a/src/test/isolation/expected/simple-write-skew.out +++ b/src/test/isolation/expected/simple-write-skew.out @@ -39,3 +39,4 @@ step rwx2: UPDATE test SET t = 'pear' WHERE t = 'apple' step c2: COMMIT; step rwx1: UPDATE test SET t = 'apple' WHERE t = 'pear'; step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 4fc56ae99c..f40d7da512 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -1,112 +1,112 @@ test: read-only-anomaly test: read-only-anomaly-2 -test: read-only-anomaly-3 +# test: read-only-anomaly-3 test: read-write-unique test: read-write-unique-2 -test: read-write-unique-3 -test: read-write-unique-4 +# test: read-write-unique-3 +# test: read-write-unique-4 test: simple-write-skew -test: receipt-report -test: temporal-range-integrity -test: project-manager -test: classroom-scheduling -test: total-cash -test: referential-integrity -test: ri-trigger -test: partial-index -test: two-ids -test: multiple-row-versions -test: index-only-scan -test: predicate-lock-hot-tuple -test: update-conflict-out -test: deadlock-simple -test: deadlock-hard -test: deadlock-soft -test: deadlock-soft-2 -test: deadlock-parallel -test: detach-partition-concurrently-1 -test: detach-partition-concurrently-2 -test: detach-partition-concurrently-3 -test: detach-partition-concurrently-4 +# test: receipt-report +# test: temporal-range-integrity +# test: project-manager +# test: classroom-scheduling +# test: total-cash +# test: referential-integrity +# test: ri-trigger +# test: partial-index +# test: two-ids +# test: multiple-row-versions +# test: index-only-scan +# test: predicate-lock-hot-tuple +# test: update-conflict-out +# test: deadlock-simple +# test: deadlock-hard +# test: deadlock-soft +# test: deadlock-soft-2 +# test: deadlock-parallel +# test: detach-partition-concurrently-1 +# test: detach-partition-concurrently-2 +# test: detach-partition-concurrently-3 +# test: detach-partition-concurrently-4 test: fk-contention -test: fk-deadlock +# test: fk-deadlock test: fk-deadlock2 -test: fk-partitioned-1 -test: fk-partitioned-2 -test: fk-snapshot -test: subxid-overflow -test: eval-plan-qual -test: eval-plan-qual-trigger -test: lock-update-delete -test: lock-update-traversal -test: inherit-temp -test: temp-schema-cleanup +# test: fk-partitioned-1 +# test: fk-partitioned-2 +# test: fk-snapshot +# test: subxid-overflow +# test: eval-plan-qual +# test: eval-plan-qual-trigger +# test: lock-update-delete +# test: lock-update-traversal +# test: inherit-temp +# test: temp-schema-cleanup test: insert-conflict-do-nothing -test: insert-conflict-do-nothing-2 +# test: insert-conflict-do-nothing-2 test: insert-conflict-do-update -test: insert-conflict-do-update-2 -test: insert-conflict-do-update-3 -test: insert-conflict-specconflict -test: merge-insert-update -test: merge-delete -test: merge-update -test: merge-match-recheck -test: delete-abort-savept -test: delete-abort-savept-2 -test: aborted-keyrevoke +# test: insert-conflict-do-update-2 +# test: insert-conflict-do-update-3 +# test: insert-conflict-specconflict +# test: merge-insert-update +# test: merge-delete +# test: merge-update +# test: merge-match-recheck +# test: delete-abort-savept +# test: delete-abort-savept-2 +# test: aborted-keyrevoke test: multixact-no-deadlock -test: multixact-no-forget -test: lock-committed-update -test: lock-committed-keyupdate -test: update-locked-tuple -test: reindex-concurrently -test: reindex-concurrently-toast -test: reindex-schema -test: propagate-lock-delete -test: tuplelock-conflict -test: tuplelock-update -test: tuplelock-upgrade-no-deadlock -test: tuplelock-partition -test: freeze-the-dead +# test: multixact-no-forget +# test: lock-committed-update +# test: lock-committed-keyupdate +# test: update-locked-tuple +# test: reindex-concurrently +# test: reindex-concurrently-toast +# test: reindex-schema +# test: propagate-lock-delete +# test: tuplelock-conflict +# test: tuplelock-update +# test: tuplelock-upgrade-no-deadlock +# test: tuplelock-partition +# test: freeze-the-dead test: nowait test: nowait-2 test: nowait-3 -test: nowait-4 -test: nowait-5 +# test: nowait-4 +# test: nowait-5 test: skip-locked -test: skip-locked-2 -test: skip-locked-3 -test: skip-locked-4 -test: drop-index-concurrently-1 -test: multiple-cic -test: alter-table-1 -test: alter-table-2 -test: alter-table-3 -test: alter-table-4 -test: create-trigger -test: sequence-ddl -test: async-notify -test: vacuum-no-cleanup-lock -test: timeouts -test: vacuum-concurrent-drop -test: vacuum-conflict -test: vacuum-skip-locked -test: stats -test: horizons -test: predicate-hash -test: predicate-gist -test: predicate-gin -test: partition-concurrent-attach -test: partition-drop-index-locking -test: partition-key-update-1 -test: partition-key-update-2 -test: partition-key-update-3 -test: partition-key-update-4 -test: plpgsql-toast -test: cluster-conflict -test: cluster-conflict-partition -test: truncate-conflict -test: serializable-parallel -test: serializable-parallel-2 -test: serializable-parallel-3 -test: matview-write-skew +# test: skip-locked-2 +# test: skip-locked-3 +# test: skip-locked-4 +# test: drop-index-concurrently-1 +# test: multiple-cic +# test: alter-table-1 +# test: alter-table-2 +# test: alter-table-3 +# test: alter-table-4 +# test: create-trigger +# test: sequence-ddl +# test: async-notify +# test: vacuum-no-cleanup-lock +# test: timeouts +# test: vacuum-concurrent-drop +# test: vacuum-conflict +# test: vacuum-skip-locked +# test: stats +# test: horizons +# test: predicate-hash +# test: predicate-gist +# test: predicate-gin +# test: partition-concurrent-attach +# test: partition-drop-index-locking +# test: partition-key-update-1 +# test: partition-key-update-2 +# test: partition-key-update-3 +# test: partition-key-update-4 +# test: plpgsql-toast +# test: cluster-conflict +# test: cluster-conflict-partition +# test: truncate-conflict +# test: serializable-parallel +# test: serializable-parallel-2 +# test: serializable-parallel-3 +# test: matview-write-skew diff --git a/src/test/isolation/specs/fk-deadlock.spec b/src/test/isolation/specs/fk-deadlock.spec index b4970dd06f..e4ab11399b 100644 --- a/src/test/isolation/specs/fk-deadlock.spec +++ b/src/test/isolation/specs/fk-deadlock.spec @@ -19,13 +19,13 @@ teardown } session s1 -setup { BEGIN; SET deadlock_timeout = '100ms'; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; SET deadlock_timeout = '100ms'; } step s1i { INSERT INTO child VALUES (1, 1); } step s1u { UPDATE parent SET aux = 'bar'; } step s1c { COMMIT; } session s2 -setup { BEGIN; SET deadlock_timeout = '10s'; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; SET deadlock_timeout = '10s'; } step s2i { INSERT INTO child VALUES (2, 1); } step s2u { UPDATE parent SET aux = 'baz'; } step s2c { COMMIT; } diff --git a/src/test/isolation/specs/fk-deadlock2.spec b/src/test/isolation/specs/fk-deadlock2.spec index c8e0e4eb19..792fd88646 100644 --- a/src/test/isolation/specs/fk-deadlock2.spec +++ b/src/test/isolation/specs/fk-deadlock2.spec @@ -24,13 +24,13 @@ teardown } session s1 -setup { BEGIN; SET deadlock_timeout = '100ms'; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; SET deadlock_timeout = '100ms'; } step s1u1 { UPDATE A SET Col1 = 1 WHERE AID = 1; } step s1u2 { UPDATE B SET Col2 = 1 WHERE BID = 2; } step s1c { COMMIT; } session s2 -setup { BEGIN; SET deadlock_timeout = '10s'; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; SET deadlock_timeout = '10s'; } step s2u1 { UPDATE B SET Col2 = 1 WHERE BID = 2; } step s2u2 { UPDATE B SET Col2 = 1 WHERE BID = 2; } step s2c { COMMIT; } diff --git a/src/test/isolation/specs/insert-conflict-do-nothing-2.spec b/src/test/isolation/specs/insert-conflict-do-nothing-2.spec index 825b7d6490..43176fc8ce 100644 --- a/src/test/isolation/specs/insert-conflict-do-nothing-2.spec +++ b/src/test/isolation/specs/insert-conflict-do-nothing-2.spec @@ -3,7 +3,7 @@ setup { - CREATE TABLE ints (key int, val text, PRIMARY KEY (key) INCLUDE (val)); + CREATE TABLE ints (key int, val text, PRIMARY KEY (key)); } teardown diff --git a/src/test/isolation/specs/lock-update-traversal.spec b/src/test/isolation/specs/lock-update-traversal.spec index 9d3d32de42..7beaf09560 100644 --- a/src/test/isolation/specs/lock-update-traversal.spec +++ b/src/test/isolation/specs/lock-update-traversal.spec @@ -9,7 +9,7 @@ setup CREATE TABLE foo ( key int, value int, - PRIMARY KEY (key) INCLUDE (value) + PRIMARY KEY (key) ); INSERT INTO foo VALUES (1, 1); @@ -27,7 +27,7 @@ step s1l { SELECT * FROM foo FOR KEY SHARE; } # obtain lock step s1c { COMMIT; } session s2 -step s2b { BEGIN; } +step s2b { BEGIN ISOLATION LEVEL READ COMMITTED; } step s2u { UPDATE foo SET value = 2 WHERE key = 1; } step s2c { COMMIT; } step s2d1 { DELETE FROM foo WHERE key = 1; } diff --git a/src/test/isolation/specs/multixact-no-deadlock.spec b/src/test/isolation/specs/multixact-no-deadlock.spec index a8af724e58..1659f549db 100644 --- a/src/test/isolation/specs/multixact-no-deadlock.spec +++ b/src/test/isolation/specs/multixact-no-deadlock.spec @@ -16,19 +16,19 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1lock { SELECT * FROM justthis FOR SHARE; } step s1svpt { SAVEPOINT foo; } step s1lock2 { SELECT * FROM justthis FOR SHARE; } step s1c { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2lock { SELECT * FROM justthis FOR SHARE; } # ensure it's a multi step s2c { COMMIT; } session s3 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s3lock { SELECT * FROM justthis FOR UPDATE; } step s3c { COMMIT; } diff --git a/src/test/isolation/specs/multixact-no-forget.spec b/src/test/isolation/specs/multixact-no-forget.spec index 7f8a38b51b..16f5aae3c7 100644 --- a/src/test/isolation/specs/multixact-no-forget.spec +++ b/src/test/isolation/specs/multixact-no-forget.spec @@ -15,13 +15,13 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1_show { SELECT current_setting('default_transaction_isolation') <> 'read committed'; } step s1_lock { SELECT * FROM dont_forget FOR KEY SHARE; } step s1_commit { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2_update { UPDATE dont_forget SET value = 2; } step s2_abort { ROLLBACK; } step s2_commit { COMMIT; } diff --git a/src/test/isolation/specs/nowait-2.spec b/src/test/isolation/specs/nowait-2.spec index cf892f2cbe..45b76786ec 100644 --- a/src/test/isolation/specs/nowait-2.spec +++ b/src/test/isolation/specs/nowait-2.spec @@ -15,12 +15,12 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1a { SELECT * FROM foo FOR SHARE NOWAIT; } step s1b { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2a { SELECT * FROM foo FOR SHARE NOWAIT; } step s2b { SELECT * FROM foo FOR UPDATE NOWAIT; } step s2c { COMMIT; } diff --git a/src/test/isolation/specs/nowait-3.spec b/src/test/isolation/specs/nowait-3.spec index 06fb7624c3..f4c6eed4e1 100644 --- a/src/test/isolation/specs/nowait-3.spec +++ b/src/test/isolation/specs/nowait-3.spec @@ -15,17 +15,17 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1a { SELECT * FROM foo FOR UPDATE; } step s1b { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2a { SELECT * FROM foo FOR UPDATE; } step s2b { COMMIT; } session s3 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s3a { SELECT * FROM foo FOR UPDATE NOWAIT; } step s3b { COMMIT; } diff --git a/src/test/isolation/specs/nowait.spec b/src/test/isolation/specs/nowait.spec index a75e54cc67..eff082e9ce 100644 --- a/src/test/isolation/specs/nowait.spec +++ b/src/test/isolation/specs/nowait.spec @@ -15,11 +15,11 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1a { SELECT * FROM foo FOR UPDATE NOWAIT; } step s1b { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2a { SELECT * FROM foo FOR UPDATE NOWAIT; } step s2b { COMMIT; } diff --git a/src/test/isolation/specs/read-only-anomaly-2.spec b/src/test/isolation/specs/read-only-anomaly-2.spec index 6b579a60c5..91ae262fbc 100644 --- a/src/test/isolation/specs/read-only-anomaly-2.spec +++ b/src/test/isolation/specs/read-only-anomaly-2.spec @@ -39,4 +39,4 @@ step s3c { COMMIT; } permutation s2rx s2ry s1ry s1wy s1c s2wx s2c s3c # once s3 observes the data committed by s1, a cycle is created and s2 aborts -permutation s2rx s2ry s1ry s1wy s1c s3r s3c s2wx +permutation s2rx s2ry s1ry s1wy s1c s3r s3c s2wx s2c diff --git a/src/test/isolation/specs/skip-locked-2.spec b/src/test/isolation/specs/skip-locked-2.spec index cfdaa93878..47fd1f36cb 100644 --- a/src/test/isolation/specs/skip-locked-2.spec +++ b/src/test/isolation/specs/skip-locked-2.spec @@ -16,12 +16,12 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1a { SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; } step s1b { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2a { SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; } step s2b { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } step s2c { COMMIT; } diff --git a/src/test/isolation/specs/skip-locked.spec b/src/test/isolation/specs/skip-locked.spec index 12168f8f8a..01f4915e7d 100644 --- a/src/test/isolation/specs/skip-locked.spec +++ b/src/test/isolation/specs/skip-locked.spec @@ -16,13 +16,13 @@ teardown } session s1 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s1a { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } step s1b { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } step s1c { COMMIT; } session s2 -setup { BEGIN; } +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } step s2a { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } step s2b { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } step s2c { COMMIT; } diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 7b23cc80dc..1fac717b8e 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -616,25 +616,6 @@ initialize_environment(void) * Set timezone and datestyle for datetime-related tests */ setenv("PGTZ", "PST8PDT", 1); - setenv("PGDATESTYLE", "Postgres, MDY", 1); - - /* - * Likewise set intervalstyle to ensure consistent results. This is a bit - * more painful because we must use PGOPTIONS, and we want to preserve the - * user's ability to set other variables through that. - */ - { - const char *my_pgoptions = "-c intervalstyle=postgres_verbose"; - const char *old_pgoptions = getenv("PGOPTIONS"); - char *new_pgoptions; - - if (!old_pgoptions) - old_pgoptions = ""; - new_pgoptions = psprintf("%s %s", - old_pgoptions, my_pgoptions); - setenv("PGOPTIONS", new_pgoptions, 1); - free(new_pgoptions); - } if (temp_instance) { @@ -1883,14 +1864,6 @@ create_database(const char *dbname) else psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname, (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : ""); - psql_add_command(buf, - "ALTER DATABASE \"%s\" SET lc_messages TO 'C';" - "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';" - "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';" - "ALTER DATABASE \"%s\" SET lc_time TO 'C';" - "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';" - "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';", - dbname, dbname, dbname, dbname, dbname, dbname); psql_end_command(buf, "postgres"); /* ```

This allowed 14 of the 112 tests to pass with no or only minor tweaks:

➜ ./pg_isolation_regress --host=localhost --port=26257 --user=root --schedule=./isolation_schedule
(using postmaster on localhost, port 26257)
============== dropping database "isolation_regression" ==============
SET
DROP DATABASE
============== creating database "isolation_regression" ==============
CREATE DATABASE
============== running regression test queries        ==============
test read-only-anomaly            ... ok          360 ms
test read-only-anomaly-2          ... ok          721 ms
test read-write-unique            ... ok          732 ms
test read-write-unique-2          ... ok          690 ms
test simple-write-skew            ... ok         2050 ms
test fk-contention                ... ok         1078 ms
test fk-deadlock2                 ... ok         4695 ms
test insert-conflict-do-nothing   ... ok          783 ms
test insert-conflict-do-update    ... ok          765 ms
test multixact-no-deadlock        ... ok          523 ms
test nowait                       ... ok         1909 ms
test nowait-2                     ... ok          969 ms
test nowait-3                     ... ok          458 ms
test skip-locked                  ... ok         6924 ms

======================
 All 14 tests passed.
======================