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

Commit82e0d6e

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 parent40a9a16 commit82e0d6e

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

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

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,7 @@ RecordTransactionCommit(void)
918918
intnmsgs=0;
919919
SharedInvalidationMessage*invalMessages=NULL;
920920
boolRelcacheInitFileInval= false;
921+
boolwrote_xlog=XactLastRecEnd.xrecoff!=0;
921922

922923
/* Get data needed for commit record */
923924
nrels=smgrGetPendingDeletes(true,&rels,&haveNonTemp);
@@ -946,12 +947,11 @@ RecordTransactionCommit(void)
946947

947948
/*
948949
* If we didn't create XLOG entries, we're done here; otherwise we
949-
* should flush those entries the same as a commit record. (An
950-
* example of a possible record that wouldn't cause an XID to be
951-
* assigned is a sequence advance record due to nextval() --- we want
952-
* to flush that to disk before reporting commit.)
950+
* should trigger flushing those entries the same as a commit record
951+
* would. This will primarily happen for HOT pruning and the like; we
952+
* want these to be flushed to disk in due time.
953953
*/
954-
if (XactLastRecEnd.xrecoff==0)
954+
if (!wrote_xlog)
955955
gotocleanup;
956956
}
957957
else
@@ -1039,16 +1039,31 @@ RecordTransactionCommit(void)
10391039
}
10401040

10411041
/*
1042-
* Check if we want to commit asynchronously. If the user has set
1043-
* synchronous_commit = off, and we're not doing cleanup of any non-temp
1044-
* rels nor committing any command that wanted to force sync commit, then
1045-
* we can defer flushing XLOG. (We must not allow asynchronous commit if
1046-
* there are any non-temp tables to be deleted, because we might delete
1047-
* the files before the COMMIT record is flushed to disk. We do allow
1048-
* asynchronous commit if all to-be-deleted tables are temporary though,
1049-
* since they are lost anyway if we crash.)
1042+
* Check if we want to commit asynchronously. We can allow the XLOG flush
1043+
* to happen asynchronously if synchronous_commit=off, or if the current
1044+
* transaction has not performed any WAL-logged operation or didn't assign
1045+
* a xid. The transaction can end up not writing any WAL, even if it has
1046+
* a xid, if it only wrote to temporary tables. It can end up having
1047+
* written WAL without an xid if it did HOT pruning. In case of a crash,
1048+
* the loss of such a transaction will be irrelevant; temp tables will be
1049+
* lost anyway and HOT pruning will be done again later. (Given the
1050+
* foregoing, you might think that it would be unnecessary to emit the
1051+
* XLOG record at all in this case, but we don't currently try to do that.
1052+
* It would certainly cause problems at least in Hot Standby mode, where
1053+
* the KnownAssignedXids machinery requires tracking every XID assignment.
1054+
* It might be OK to skip it only when wal_level < hot_standby, but for
1055+
* now we don't.)
1056+
*
1057+
* However, if we're doing cleanup of any non-temp rels or committing any
1058+
* command that wanted to force sync commit, then we must flush XLOG
1059+
* immediately. (We must not allow asynchronous commit if there are any
1060+
* non-temp tables to be deleted, because we might delete the files before
1061+
* the COMMIT record is flushed to disk. We do allow asynchronous commit
1062+
* if all to-be-deleted tables are temporary though, since they are lost
1063+
* anyway if we crash.)
10501064
*/
1051-
if (XactSyncCommit||forceSyncCommit||haveNonTemp)
1065+
if ((wrote_xlog&&markXidCommitted&&XactSyncCommit)
1066+
||forceSyncCommit||haveNonTemp)
10521067
{
10531068
/*
10541069
* Synchronous commit case:

‎src/backend/commands/sequence.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ DefineSequence(CreateSeqStmt *seq)
247247
*/
248248
LockBuffer(buf,BUFFER_LOCK_EXCLUSIVE);
249249

250+
/* check the comment above nextval_internal()'s equivalent call. */
251+
if (!rel->rd_istemp)
252+
GetTopTransactionId();
253+
250254
START_CRIT_SECTION();
251255

252256
{
@@ -363,6 +367,10 @@ AlterSequenceInternal(Oid relid, List *options)
363367
/* Note that we do not change the currval() state */
364368
elm->cached=elm->last;
365369

370+
/* check the comment above nextval_internal()'s equivalent call. */
371+
if (!seqrel->rd_istemp)
372+
GetTopTransactionId();
373+
366374
/* Now okay to update the on-disk tuple */
367375
START_CRIT_SECTION();
368376

@@ -596,6 +604,16 @@ nextval_internal(Oid relid)
596604

597605
last_used_seq=elm;
598606

607+
/*
608+
* If something needs to be WAL logged, acquire an xid, so this
609+
* transaction's commit will trigger a WAL flush and wait for
610+
* syncrep. It's sufficient to ensure the toplevel transaction has a xid,
611+
* no need to assign xids subxacts, that'll already trigger a appropriate
612+
* wait. (Have to do that here, so we're outside the critical section)
613+
*/
614+
if (logit&& !seqrel->rd_istemp)
615+
GetTopTransactionId();
616+
599617
/* ready to change the on-disk (or really, in-buffer) tuple */
600618
START_CRIT_SECTION();
601619

@@ -790,6 +808,10 @@ do_setval(Oid relid, int64 next, bool iscalled)
790808
/* In any case, forget any future cached numbers */
791809
elm->cached=elm->last;
792810

811+
/* check the comment above nextval_internal()'s equivalent call. */
812+
if (!seqrel->rd_istemp)
813+
GetTopTransactionId();
814+
793815
/* ready to change the on-disk (or really, in-buffer) tuple */
794816
START_CRIT_SECTION();
795817

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp