Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd670765

Browse files
committed
Reconsider when to wait for WAL flushes/syncrep during commit.
Up to now RecordTransactionCommit() waited for WAL to be flushed (ifsynchronous_commit != off) and to be synchronously replicated (ifenabled), even if a transaction did not have a xid assigned. The primaryreason for that is that sequence's nextval() did not assign a xid, butare worthwhile to wait for on commit.This can be problematic because sometimes read only transactions dowrite WAL, e.g. HOT page prune records. That then could lead to read onlytransactions having to wait during commit. Not something people expectin a read only transaction.This lead to such strange symptoms as backends being seemingly stuckduring connection establishment when all synchronous replicas aredown. Especially annoying when said stuck connection is the standbytrying to reconnect to allow syncrep again...This behavior also is involved in a rather complicated <= 9.4 bug wherethe transaction started by catchup interrupt processing waited forsyncrep using latches, but didn't get the wakeup because it was alreadyrunning inside the same overloaded signal handler. Fix the issue heredoesn't properly solve that issue, merely papers over the problems. In9.5 catchup interrupts aren't processed out of signal handlers anymore.To fix all this, make nextval() acquire a top level xid, and only wait fortransaction commit if a transaction both acquired a xid and emitted WALrecords. If only a xid has been assigned we don't uselessly want towait just because of writes to temporary/unlogged tables; if only WALhas been written we don't want to wait just because of HOT prunes.The xid assignment in nextval() is unlikely to cause overhead inreal-world workloads. For one it only happens SEQ_LOG_VALS/32 valuesanyway, for another only usage of nextval() without using the result inan insert or similar is affected.Discussion: 20150223165359.GF30784@awork2.anarazel.de, 369698E947874884A77849D8FE3680C2@maumau, 5CF4ABBA67674088B3941894E22A0D25@maumauPer complaint from maumau and Thom BrownBackpatch all the way back; 9.0 doesn't have syncrep, but it seemsbetter to be consistent behavior across all maintained branches.
1 parentd7083cc commitd670765

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -994,10 +994,9 @@ RecordTransactionCommit(void)
994994

995995
/*
996996
* If we didn't create XLOG entries, we're done here; otherwise we
997-
* should flush those entries the same as a commit record. (An
998-
* example of a possible record that wouldn't cause an XID to be
999-
* assigned is a sequence advance record due to nextval() --- we want
1000-
* to flush that to disk before reporting commit.)
997+
* should trigger flushing those entries the same as a commit record
998+
* would. This will primarily happen for HOT pruning and the like; we
999+
* want these to be flushed to disk in due time.
10011000
*/
10021001
if (!wrote_xlog)
10031002
gotocleanup;
@@ -1120,11 +1119,13 @@ RecordTransactionCommit(void)
11201119
/*
11211120
* Check if we want to commit asynchronously. We can allow the XLOG flush
11221121
* to happen asynchronously if synchronous_commit=off, or if the current
1123-
* transaction has not performed any WAL-logged operation. The latter
1124-
* case can arise if the current transaction wrote only to temporary
1125-
* and/or unlogged tables. In case of a crash, the loss of such a
1126-
* transaction will be irrelevant since temp tables will be lost anyway,
1127-
* and unlogged tables will be truncated. (Given the foregoing, you might
1122+
* transaction has not performed any WAL-logged operation or didn't assign
1123+
* a xid. The transaction can end up not writing any WAL, even if it has
1124+
* a xid, if it only wrote to temporary and/or unlogged tables. It can
1125+
* end up having written WAL without an xid if it did HOT pruning. In
1126+
* case of a crash, the loss of such a transaction will be irrelevant;
1127+
* temp tables will be lost anyway, unlogged tables will be truncated and
1128+
* HOT pruning will be done again later. (Given the foregoing, you might
11281129
* think that it would be unnecessary to emit the XLOG record at all in
11291130
* this case, but we don't currently try to do that. It would certainly
11301131
* cause problems at least in Hot Standby mode, where the
@@ -1140,7 +1141,8 @@ RecordTransactionCommit(void)
11401141
* if all to-be-deleted tables are temporary though, since they are lost
11411142
* anyway if we crash.)
11421143
*/
1143-
if ((wrote_xlog&&synchronous_commit>SYNCHRONOUS_COMMIT_OFF)||
1144+
if ((wrote_xlog&&markXidCommitted&&
1145+
synchronous_commit>SYNCHRONOUS_COMMIT_OFF)||
11441146
forceSyncCommit||nrels>0)
11451147
{
11461148
/*
@@ -1212,12 +1214,15 @@ RecordTransactionCommit(void)
12121214
latestXid=TransactionIdLatest(xid,nchildren,children);
12131215

12141216
/*
1215-
* Wait for synchronous replication, if required.
1217+
* Wait for synchronous replication, if required. Similar to the decision
1218+
* above about using committing asynchronously we only want to wait if
1219+
* this backend assigned a xid and wrote WAL. No need to wait if a xid
1220+
* was assigned due to temporary/unlogged tables or due to HOT pruning.
12161221
*
12171222
* Note that at this stage we have marked clog, but still show as running
12181223
* in the procarray and continue to hold locks.
12191224
*/
1220-
if (wrote_xlog)
1225+
if (wrote_xlog&&markXidCommitted)
12211226
SyncRepWaitForLSN(XactLastRecEnd);
12221227

12231228
/* Reset XactLastRecEnd until the next transaction writes something */

‎src/backend/commands/sequence.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include"postgres.h"
1616

1717
#include"access/transam.h"
18+
#include"access/xact.h"
1819
#include"access/xlogutils.h"
1920
#include"catalog/dependency.h"
2021
#include"catalog/namespace.h"
@@ -340,6 +341,10 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
340341
*/
341342
LockBuffer(buf,BUFFER_LOCK_EXCLUSIVE);
342343

344+
/* check the comment above nextval_internal()'s equivalent call. */
345+
if (RelationNeedsWAL(rel))
346+
GetTopTransactionId();
347+
343348
START_CRIT_SECTION();
344349

345350
{
@@ -441,6 +446,10 @@ AlterSequence(AlterSeqStmt *stmt)
441446
/* Note that we do not change the currval() state */
442447
elm->cached=elm->last;
443448

449+
/* check the comment above nextval_internal()'s equivalent call. */
450+
if (RelationNeedsWAL(seqrel))
451+
GetTopTransactionId();
452+
444453
/* Now okay to update the on-disk tuple */
445454
START_CRIT_SECTION();
446455

@@ -683,6 +692,16 @@ nextval_internal(Oid relid)
683692

684693
last_used_seq=elm;
685694

695+
/*
696+
* If something needs to be WAL logged, acquire an xid, so this
697+
* transaction's commit will trigger a WAL flush and wait for
698+
* syncrep. It's sufficient to ensure the toplevel transaction has a xid,
699+
* no need to assign xids subxacts, that'll already trigger a appropriate
700+
* wait. (Have to do that here, so we're outside the critical section)
701+
*/
702+
if (logit&&RelationNeedsWAL(seqrel))
703+
GetTopTransactionId();
704+
686705
/* ready to change the on-disk (or really, in-buffer) tuple */
687706
START_CRIT_SECTION();
688707

@@ -877,6 +896,10 @@ do_setval(Oid relid, int64 next, bool iscalled)
877896
/* In any case, forget any future cached numbers */
878897
elm->cached=elm->last;
879898

899+
/* check the comment above nextval_internal()'s equivalent call. */
900+
if (RelationNeedsWAL(seqrel))
901+
GetTopTransactionId();
902+
880903
/* ready to change the on-disk (or really, in-buffer) tuple */
881904
START_CRIT_SECTION();
882905

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp