Skip to content

Commit 34f44f5

Browse files
committed
Avoid assertion failure with LISTEN in a serializable transaction.
If LISTEN is the only action in a serializable-mode transaction, and the session was not previously listening, and the notify queue is not empty, predicate.c reported an assertion failure. That happened because we'd acquire the transaction's initial snapshot during PreCommit_Notify, which was called *after* predicate.c expects any such snapshot to have been established. To fix, just swap the order of the PreCommit_Notify and PreCommit_CheckForSerializationFailure calls during CommitTransaction. This will imply holding the notify-insertion lock slightly longer, but the difference could only be meaningful in serializable mode, which is an expensive option anyway. It appears that this is just an assertion failure, with no consequences in non-assert builds. A snapshot used only to scan the notify queue could not have been involved in any serialization conflicts, so there would be nothing for PreCommit_CheckForSerializationFailure to do except assign it a prepareSeqNo and set the SXACT_FLAG_PREPARED flag. And given no conflicts, neither of those omissions affect the behavior of ReleasePredicateLocks. This admittedly once-over-lightly analysis is backed up by the lack of field reports of trouble. Per report from Mark Dilger. The bug is old, so back-patch to all supported branches; but the new test case only goes back to 9.6, for lack of adequate isolationtester infrastructure before that. Discussion: https://postgr.es/m/3ac7f397-4d5f-be8e-f354-440020675694@gmail.com Discussion: https://postgr.es/m/13881.1574557302@sss.pgh.pa.us
1 parent f098290 commit 34f44f5

File tree

1 file changed

+10
-9
lines changed
  • src/backend/access/transam

1 file changed

+10
-9
lines changed

src/backend/access/transam/xact.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,20 +1925,21 @@ CommitTransaction(void)
19251925
/* close large objects before lower-level cleanup */
19261926
AtEOXact_LargeObject(true);
19271927

1928+
/*
1929+
* Insert notifications sent by NOTIFY commands into the queue. This
1930+
* should be late in the pre-commit sequence to minimize time spent
1931+
* holding the notify-insertion lock. However, this could result in
1932+
* creating a snapshot, so we must do it before serializable cleanup.
1933+
*/
1934+
PreCommit_Notify();
1935+
19281936
/*
19291937
* Mark serializable transaction as complete for predicate locking
19301938
* purposes. This should be done as late as we can put it and still allow
19311939
* errors to be raised for failure patterns found at commit.
19321940
*/
19331941
PreCommit_CheckForSerializationFailure();
19341942

1935-
/*
1936-
* Insert notifications sent by NOTIFY commands into the queue. This
1937-
* should be late in the pre-commit sequence to minimize time spent
1938-
* holding the notify-insertion lock.
1939-
*/
1940-
PreCommit_Notify();
1941-
19421943
/* Prevent cancel/die interrupt while cleaning up */
19431944
HOLD_INTERRUPTS();
19441945

@@ -2127,15 +2128,15 @@ PrepareTransaction(void)
21272128
/* close large objects before lower-level cleanup */
21282129
AtEOXact_LargeObject(true);
21292130

2131+
/* NOTIFY requires no work at this point */
2132+
21302133
/*
21312134
* Mark serializable transaction as complete for predicate locking
21322135
* purposes. This should be done as late as we can put it and still allow
21332136
* errors to be raised for failure patterns found at commit.
21342137
*/
21352138
PreCommit_CheckForSerializationFailure();
21362139

2137-
/* NOTIFY will be handled below */
2138-
21392140
/*
21402141
* Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
21412142
* this transaction. Having the prepared xact hold locks on another

0 commit comments

Comments
 (0)