aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xact.c19
-rw-r--r--src/test/isolation/expected/async-notify.out13
-rw-r--r--src/test/isolation/specs/async-notify.spec14
3 files changed, 36 insertions, 10 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index c87524e8fc6..bd396f0f08f 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -2111,6 +2111,14 @@ CommitTransaction(void)
AtEOXact_LargeObject(true);
/*
+ * Insert notifications sent by NOTIFY commands into the queue. This
+ * should be late in the pre-commit sequence to minimize time spent
+ * holding the notify-insertion lock. However, this could result in
+ * creating a snapshot, so we must do it before serializable cleanup.
+ */
+ PreCommit_Notify();
+
+ /*
* Mark serializable transaction as complete for predicate locking
* purposes. This should be done as late as we can put it and still allow
* errors to be raised for failure patterns found at commit. This is not
@@ -2120,13 +2128,6 @@ CommitTransaction(void)
if (!is_parallel_worker)
PreCommit_CheckForSerializationFailure();
- /*
- * Insert notifications sent by NOTIFY commands into the queue. This
- * should be late in the pre-commit sequence to minimize time spent
- * holding the notify-insertion lock.
- */
- PreCommit_Notify();
-
/* Prevent cancel/die interrupt while cleaning up */
HOLD_INTERRUPTS();
@@ -2342,6 +2343,8 @@ PrepareTransaction(void)
/* close large objects before lower-level cleanup */
AtEOXact_LargeObject(true);
+ /* NOTIFY requires no work at this point */
+
/*
* Mark serializable transaction as complete for predicate locking
* purposes. This should be done as late as we can put it and still allow
@@ -2349,8 +2352,6 @@ PrepareTransaction(void)
*/
PreCommit_CheckForSerializationFailure();
- /* NOTIFY will be handled below */
-
/*
* Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
* this transaction. Having the prepared xact hold locks on another
diff --git a/src/test/isolation/expected/async-notify.out b/src/test/isolation/expected/async-notify.out
index 60ba50658dd..3a9bf3c3107 100644
--- a/src/test/isolation/expected/async-notify.out
+++ b/src/test/isolation/expected/async-notify.out
@@ -1,4 +1,4 @@
-Parsed test spec with 2 sessions
+Parsed test spec with 3 sessions
starting permutation: listenc notify1 notify2 notify3 notifyf
step listenc: LISTEN c1; LISTEN c2;
@@ -85,6 +85,17 @@ listener: NOTIFY "c1" with payload "" from notifier
listener: NOTIFY "c2" with payload "payload" from notifier
listener: NOTIFY "c2" with payload "" from notifier
+starting permutation: l2listen l2begin notify1 lbegins llisten lcommit l2commit l2stop
+step l2listen: LISTEN c1;
+step l2begin: BEGIN;
+step notify1: NOTIFY c1;
+step lbegins: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step llisten: LISTEN c1; LISTEN c2;
+step lcommit: COMMIT;
+step l2commit: COMMIT;
+listener2: NOTIFY "c1" with payload "" from notifier
+step l2stop: UNLISTEN *;
+
starting permutation: llisten lbegin usage bignotify usage
step llisten: LISTEN c1; LISTEN c2;
step lbegin: BEGIN;
diff --git a/src/test/isolation/specs/async-notify.spec b/src/test/isolation/specs/async-notify.spec
index daf7bef903c..a7b2600d25c 100644
--- a/src/test/isolation/specs/async-notify.spec
+++ b/src/test/isolation/specs/async-notify.spec
@@ -41,8 +41,18 @@ session "listener"
step "llisten" { LISTEN c1; LISTEN c2; }
step "lcheck" { SELECT 1 AS x; }
step "lbegin" { BEGIN; }
+step "lbegins" { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step "lcommit" { COMMIT; }
teardown { UNLISTEN *; }
+# In some tests we need a second listener, just to block the queue.
+
+session "listener2"
+step "l2listen" { LISTEN c1; }
+step "l2begin" { BEGIN; }
+step "l2commit" { COMMIT; }
+step "l2stop" { UNLISTEN *; }
+
# Trivial cases.
permutation "listenc" "notify1" "notify2" "notify3" "notifyf"
@@ -59,6 +69,10 @@ permutation "llisten" "notify1" "notify2" "notify3" "notifyf" "lcheck"
# Again, with local delivery too.
permutation "listenc" "llisten" "notify1" "notify2" "notify3" "notifyf" "lcheck"
+# Check for bug when initial listen is only action in a serializable xact,
+# and notify queue is not empty
+permutation "l2listen" "l2begin" "notify1" "lbegins" "llisten" "lcommit" "l2commit" "l2stop"
+
# Verify that pg_notification_queue_usage correctly reports a non-zero result,
# after submitting notifications while another connection is listening for
# those notifications and waiting inside an active transaction. We have to