Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/replication/syncrep.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * syncrep.c
4
 *
5
 * Synchronous replication is new as of PostgreSQL 9.1.
6
 *
7
 * If requested, transaction commits wait until their commit LSN are
8
 * acknowledged by the synchronous standbys.
9
 *
10
 * This module contains the code for waiting and release of backends.
11
 * All code in this module executes on the primary. The core streaming
12
 * replication transport remains within WALreceiver/WALsender modules.
13
 *
14
 * The essence of this design is that it isolates all logic about
15
 * waiting/releasing onto the primary. The primary defines which standbys
16
 * it wishes to wait for. The standbys are completely unaware of the
17
 * durability requirements of transactions on the primary, reducing the
18
 * complexity of the code and streamlining both standby operations and
19
 * network bandwidth because there is no requirement to ship
20
 * per-transaction state information.
21
 *
22
 * Replication is either synchronous or not synchronous (async). If it is
23
 * async, we just fastpath out of here. If it is sync, then we wait for
24
 * the write, flush or apply location on the standby before releasing
25
 * the waiting backend. Further complexity in that interaction is
26
 * expected in later releases.
27
 *
28
 * The best performing way to manage the waiting backends is to have a
29
 * single ordered queue of waiting backends, so that we can avoid
30
 * searching the through all waiters each time we receive a reply.
31
 *
32
 * In 9.5 or before only a single standby could be considered as
33
 * synchronous. In 9.6 we support a priority-based multiple synchronous
34
 * standbys. In 10.0 a quorum-based multiple synchronous standbys is also
35
 * supported. The number of synchronous standbys that transactions
36
 * must wait for replies from is specified in synchronous_standby_names.
37
 * This parameter also specifies a list of standby names and the method
38
 * (FIRST and ANY) to choose synchronous standbys from the listed ones.
39
 *
40
 * The method FIRST specifies a priority-based synchronous replication
41
 * and makes transaction commits wait until their WAL records are
42
 * replicated to the requested number of synchronous standbys chosen based
43
 * on their priorities. The standbys whose names appear earlier in the list
44
 * are given higher priority and will be considered as synchronous.
45
 * Other standby servers appearing later in this list represent potential
46
 * synchronous standbys. If any of the current synchronous standbys
47
 * disconnects for whatever reason, it will be replaced immediately with
48
 * the next-highest-priority standby.
49
 *
50
 * The method ANY specifies a quorum-based synchronous replication
51
 * and makes transaction commits wait until their WAL records are
52
 * replicated to at least the requested number of synchronous standbys
53
 * in the list. All the standbys appearing in the list are considered as
54
 * candidates for quorum synchronous standbys.
55
 *
56
 * If neither FIRST nor ANY is specified, FIRST is used as the method.
57
 * This is for backward compatibility with 9.6 or before where only a
58
 * priority-based sync replication was supported.
59
 *
60
 * Before the standbys chosen from synchronous_standby_names can
61
 * become the synchronous standbys they must have caught up with
62
 * the primary; that may take some time. Once caught up,
63
 * the standbys which are considered as synchronous at that moment
64
 * will release waiters from the queue.
65
 *
66
 * Portions Copyright (c) 2010-2026, PostgreSQL Global Development Group
67
 *
68
 * IDENTIFICATION
69
 *    src/backend/replication/syncrep.c
70
 *
71
 *-------------------------------------------------------------------------
72
 */
73
#include "postgres.h"
74
75
#include <unistd.h>
76
77
#include "access/xact.h"
78
#include "common/int.h"
79
#include "miscadmin.h"
80
#include "pgstat.h"
81
#include "replication/syncrep.h"
82
#include "replication/walsender.h"
83
#include "replication/walsender_private.h"
84
#include "storage/proc.h"
85
#include "tcop/tcopprot.h"
86
#include "utils/guc_hooks.h"
87
#include "utils/ps_status.h"
88
#include "utils/wait_event.h"
89
90
/* User-settable parameters for sync rep */
91
char     *SyncRepStandbyNames;
92
93
#define SyncStandbysDefined() \
94
0
  (SyncRepStandbyNames != NULL && SyncRepStandbyNames[0] != '\0')
95
96
static bool announce_next_takeover = true;
97
98
SyncRepConfigData *SyncRepConfig = NULL;
99
static int  SyncRepWaitMode = SYNC_REP_NO_WAIT;
100
101
static void SyncRepQueueInsert(int mode);
102
static void SyncRepCancelWait(void);
103
static int  SyncRepWakeQueue(bool all, int mode);
104
105
static bool SyncRepGetSyncRecPtr(XLogRecPtr *writePtr,
106
                 XLogRecPtr *flushPtr,
107
                 XLogRecPtr *applyPtr,
108
                 bool *am_sync);
109
static void SyncRepGetOldestSyncRecPtr(XLogRecPtr *writePtr,
110
                     XLogRecPtr *flushPtr,
111
                     XLogRecPtr *applyPtr,
112
                     SyncRepStandbyData *sync_standbys,
113
                     int num_standbys);
114
static void SyncRepGetNthLatestSyncRecPtr(XLogRecPtr *writePtr,
115
                      XLogRecPtr *flushPtr,
116
                      XLogRecPtr *applyPtr,
117
                      SyncRepStandbyData *sync_standbys,
118
                      int num_standbys,
119
                      uint8 nth);
120
static int  SyncRepGetStandbyPriority(void);
121
static int  standby_priority_comparator(const void *a, const void *b);
122
static int  cmp_lsn(const void *a, const void *b);
123
124
#ifdef USE_ASSERT_CHECKING
125
static bool SyncRepQueueIsOrderedByLSN(int mode);
126
#endif
127
128
/*
129
 * ===========================================================
130
 * Synchronous Replication functions for normal user backends
131
 * ===========================================================
132
 */
133
134
/*
135
 * Wait for synchronous replication, if requested by user.
136
 *
137
 * Initially backends start in state SYNC_REP_NOT_WAITING and then
138
 * change that state to SYNC_REP_WAITING before adding ourselves
139
 * to the wait queue. During SyncRepWakeQueue() a WALSender changes
140
 * the state to SYNC_REP_WAIT_COMPLETE once replication is confirmed.
141
 * This backend then resets its state to SYNC_REP_NOT_WAITING.
142
 *
143
 * 'lsn' represents the LSN to wait for.  'commit' indicates whether this LSN
144
 * represents a commit record.  If it doesn't, then we wait only for the WAL
145
 * to be flushed if synchronous_commit is set to the higher level of
146
 * remote_apply, because only commit records provide apply feedback.
147
 */
148
void
149
SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
150
0
{
151
0
  int     mode;
152
153
  /*
154
   * This should be called while holding interrupts during a transaction
155
   * commit to prevent the follow-up shared memory queue cleanups to be
156
   * influenced by external interruptions.
157
   */
158
0
  Assert(InterruptHoldoffCount > 0);
159
160
  /*
161
   * Fast exit if user has not requested sync replication, or there are no
162
   * sync replication standby names defined.
163
   *
164
   * Since this routine gets called every commit time, it's important to
165
   * exit quickly if sync replication is not requested.
166
   *
167
   * We check WalSndCtl->sync_standbys_status flag without the lock and exit
168
   * immediately if SYNC_STANDBY_INIT is set (the checkpointer has
169
   * initialized this data) but SYNC_STANDBY_DEFINED is missing (no sync
170
   * replication requested).
171
   *
172
   * If SYNC_STANDBY_DEFINED is set, we need to check the status again later
173
   * while holding the lock, to check the flag and operate the sync rep
174
   * queue atomically.  This is necessary to avoid the race condition
175
   * described in SyncRepUpdateSyncStandbysDefined().  On the other hand, if
176
   * SYNC_STANDBY_DEFINED is not set, the lock is not necessary because we
177
   * don't touch the queue.
178
   */
179
0
  if (!SyncRepRequested() ||
180
0
    ((((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_status) &
181
0
     (SYNC_STANDBY_INIT | SYNC_STANDBY_DEFINED)) == SYNC_STANDBY_INIT)
182
0
    return;
183
184
  /* Cap the level for anything other than commit to remote flush only. */
185
0
  if (commit)
186
0
    mode = SyncRepWaitMode;
187
0
  else
188
0
    mode = Min(SyncRepWaitMode, SYNC_REP_WAIT_FLUSH);
189
190
0
  Assert(dlist_node_is_detached(&MyProc->syncRepLinks));
191
0
  Assert(WalSndCtl != NULL);
192
193
0
  LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
194
0
  Assert(MyProc->syncRepState == SYNC_REP_NOT_WAITING);
195
196
  /*
197
   * We don't wait for sync rep if SYNC_STANDBY_DEFINED is not set.  See
198
   * SyncRepUpdateSyncStandbysDefined().
199
   *
200
   * Also check that the standby hasn't already replied. Unlikely race
201
   * condition but we'll be fetching that cache line anyway so it's likely
202
   * to be a low cost check.
203
   *
204
   * If the sync standby data has not been initialized yet
205
   * (SYNC_STANDBY_INIT is not set), fall back to a check based on the LSN,
206
   * then do a direct GUC check.
207
   */
208
0
  if (WalSndCtl->sync_standbys_status & SYNC_STANDBY_INIT)
209
0
  {
210
0
    if ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_DEFINED) == 0 ||
211
0
      lsn <= WalSndCtl->lsn[mode])
212
0
    {
213
0
      LWLockRelease(SyncRepLock);
214
0
      return;
215
0
    }
216
0
  }
217
0
  else if (lsn <= WalSndCtl->lsn[mode])
218
0
  {
219
    /*
220
     * The LSN is older than what we need to wait for.  The sync standby
221
     * data has not been initialized yet, but we are OK to not wait
222
     * because we know that there is no point in doing so based on the
223
     * LSN.
224
     */
225
0
    LWLockRelease(SyncRepLock);
226
0
    return;
227
0
  }
228
0
  else if (!SyncStandbysDefined())
229
0
  {
230
    /*
231
     * If we are here, the sync standby data has not been initialized yet,
232
     * and the LSN is newer than what need to wait for, so we have fallen
233
     * back to the best thing we could do in this case: a check on
234
     * SyncStandbysDefined() to see if the GUC is set or not.
235
     *
236
     * When the GUC has a value, we wait until the checkpointer updates
237
     * the status data because we cannot be sure yet if we should wait or
238
     * not. Here, the GUC has *no* value, we are sure that there is no
239
     * point to wait; this matters for example when initializing a
240
     * cluster, where we should never wait, and no sync standbys is the
241
     * default behavior.
242
     */
243
0
    LWLockRelease(SyncRepLock);
244
0
    return;
245
0
  }
246
247
  /*
248
   * Set our waitLSN so WALSender will know when to wake us, and add
249
   * ourselves to the queue.
250
   */
251
0
  MyProc->waitLSN = lsn;
252
0
  MyProc->syncRepState = SYNC_REP_WAITING;
253
0
  SyncRepQueueInsert(mode);
254
0
  Assert(SyncRepQueueIsOrderedByLSN(mode));
255
0
  LWLockRelease(SyncRepLock);
256
257
  /* Alter ps display to show waiting for sync rep. */
258
0
  if (update_process_title)
259
0
  {
260
0
    char    buffer[32];
261
262
0
    sprintf(buffer, "waiting for %X/%08X", LSN_FORMAT_ARGS(lsn));
263
0
    set_ps_display_suffix(buffer);
264
0
  }
265
266
  /*
267
   * Wait for specified LSN to be confirmed.
268
   *
269
   * Each proc has its own wait latch, so we perform a normal latch
270
   * check/wait loop here.
271
   */
272
0
  for (;;)
273
0
  {
274
0
    int     rc;
275
276
    /* Must reset the latch before testing state. */
277
0
    ResetLatch(MyLatch);
278
279
    /*
280
     * Acquiring the lock is not needed, the latch ensures proper
281
     * barriers. If it looks like we're done, we must really be done,
282
     * because once walsender changes the state to SYNC_REP_WAIT_COMPLETE,
283
     * it will never update it again, so we can't be seeing a stale value
284
     * in that case.
285
     */
286
0
    if (MyProc->syncRepState == SYNC_REP_WAIT_COMPLETE)
287
0
      break;
288
289
    /*
290
     * If a wait for synchronous replication is pending, we can neither
291
     * acknowledge the commit nor raise ERROR or FATAL.  The latter would
292
     * lead the client to believe that the transaction aborted, which is
293
     * not true: it's already committed locally. The former is no good
294
     * either: the client has requested synchronous replication, and is
295
     * entitled to assume that an acknowledged commit is also replicated,
296
     * which might not be true. So in this case we issue a WARNING (which
297
     * some clients may be able to interpret) and shut off further output.
298
     * We do NOT reset ProcDiePending, so that the process will die after
299
     * the commit is cleaned up.
300
     */
301
0
    if (ProcDiePending)
302
0
    {
303
0
      if (ProcDieSenderPid != 0)
304
0
        ereport(WARNING,
305
0
            (errcode(ERRCODE_ADMIN_SHUTDOWN),
306
0
             errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
307
0
             errdetail("The transaction has already committed locally, but might not have been replicated to the standby."),
308
0
             errdetail_log("The transaction has already committed locally, but might not have been replicated to the standby.  Signal sent by PID %d, UID %d.",
309
0
                     (int) ProcDieSenderPid,
310
0
                     (int) ProcDieSenderUid)));
311
0
      else
312
0
        ereport(WARNING,
313
0
            (errcode(ERRCODE_ADMIN_SHUTDOWN),
314
0
             errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
315
0
             errdetail("The transaction has already committed locally, but might not have been replicated to the standby.")));
316
0
      whereToSendOutput = DestNone;
317
0
      SyncRepCancelWait();
318
0
      break;
319
0
    }
320
321
    /*
322
     * It's unclear what to do if a query cancel interrupt arrives.  We
323
     * can't actually abort at this point, but ignoring the interrupt
324
     * altogether is not helpful, so we just terminate the wait with a
325
     * suitable warning.
326
     */
327
0
    if (QueryCancelPending)
328
0
    {
329
0
      QueryCancelPending = false;
330
0
      ereport(WARNING,
331
0
          (errmsg("canceling wait for synchronous replication due to user request"),
332
0
           errdetail("The transaction has already committed locally, but might not have been replicated to the standby.")));
333
0
      SyncRepCancelWait();
334
0
      break;
335
0
    }
336
337
    /*
338
     * Wait on latch.  Any condition that should wake us up will set the
339
     * latch, so no need for timeout.
340
     */
341
0
    rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1,
342
0
             WAIT_EVENT_SYNC_REP);
343
344
    /*
345
     * If the postmaster dies, we'll probably never get an acknowledgment,
346
     * because all the wal sender processes will exit. So just bail out.
347
     */
348
0
    if (rc & WL_POSTMASTER_DEATH)
349
0
    {
350
0
      ProcDiePending = true;
351
0
      whereToSendOutput = DestNone;
352
0
      SyncRepCancelWait();
353
0
      break;
354
0
    }
355
0
  }
356
357
  /*
358
   * WalSender has checked our LSN and has removed us from queue. Clean up
359
   * state and leave.  It's OK to reset these shared memory fields without
360
   * holding SyncRepLock, because any walsenders will ignore us anyway when
361
   * we're not on the queue.  We need a read barrier to make sure we see the
362
   * changes to the queue link (this might be unnecessary without
363
   * assertions, but better safe than sorry).
364
   */
365
0
  pg_read_barrier();
366
0
  Assert(dlist_node_is_detached(&MyProc->syncRepLinks));
367
0
  MyProc->syncRepState = SYNC_REP_NOT_WAITING;
368
0
  MyProc->waitLSN = InvalidXLogRecPtr;
369
370
  /* reset ps display to remove the suffix */
371
0
  if (update_process_title)
372
0
    set_ps_display_remove_suffix();
373
0
}
374
375
/*
376
 * Insert MyProc into the specified SyncRepQueue, maintaining sorted invariant.
377
 *
378
 * Usually we will go at tail of queue, though it's possible that we arrive
379
 * here out of order, so start at tail and work back to insertion point.
380
 */
381
static void
382
SyncRepQueueInsert(int mode)
383
0
{
384
0
  dlist_head *queue;
385
0
  dlist_iter  iter;
386
387
0
  Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
388
0
  queue = &WalSndCtl->SyncRepQueue[mode];
389
390
0
  dlist_reverse_foreach(iter, queue)
391
0
  {
392
0
    PGPROC     *proc = dlist_container(PGPROC, syncRepLinks, iter.cur);
393
394
    /*
395
     * Stop at the queue element that we should insert after to ensure the
396
     * queue is ordered by LSN.
397
     */
398
0
    if (proc->waitLSN < MyProc->waitLSN)
399
0
    {
400
0
      dlist_insert_after(&proc->syncRepLinks, &MyProc->syncRepLinks);
401
0
      return;
402
0
    }
403
0
  }
404
405
  /*
406
   * If we get here, the list was either empty, or this process needs to be
407
   * at the head.
408
   */
409
0
  dlist_push_head(queue, &MyProc->syncRepLinks);
410
0
}
411
412
/*
413
 * Acquire SyncRepLock and cancel any wait currently in progress.
414
 */
415
static void
416
SyncRepCancelWait(void)
417
0
{
418
0
  LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
419
0
  if (!dlist_node_is_detached(&MyProc->syncRepLinks))
420
0
    dlist_delete_thoroughly(&MyProc->syncRepLinks);
421
0
  MyProc->syncRepState = SYNC_REP_NOT_WAITING;
422
0
  LWLockRelease(SyncRepLock);
423
0
}
424
425
void
426
SyncRepCleanupAtProcExit(void)
427
0
{
428
  /*
429
   * First check if we are removed from the queue without the lock to not
430
   * slow down backend exit.
431
   */
432
0
  if (!dlist_node_is_detached(&MyProc->syncRepLinks))
433
0
  {
434
0
    LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
435
436
    /* maybe we have just been removed, so recheck */
437
0
    if (!dlist_node_is_detached(&MyProc->syncRepLinks))
438
0
      dlist_delete_thoroughly(&MyProc->syncRepLinks);
439
440
0
    LWLockRelease(SyncRepLock);
441
0
  }
442
0
}
443
444
/*
445
 * ===========================================================
446
 * Synchronous Replication functions for wal sender processes
447
 * ===========================================================
448
 */
449
450
/*
451
 * Take any action required to initialise sync rep state from config
452
 * data. Called at WALSender startup and after each SIGHUP.
453
 */
454
void
455
SyncRepInitConfig(void)
456
{
457
  int     priority;
458
459
  /*
460
   * Determine if we are a potential sync standby and remember the result
461
   * for handling replies from standby.
462
   */
463
  priority = SyncRepGetStandbyPriority();
464
  if (MyWalSnd->sync_standby_priority != priority)
465
  {
466
    SpinLockAcquire(&MyWalSnd->mutex);
467
    MyWalSnd->sync_standby_priority = priority;
468
    SpinLockRelease(&MyWalSnd->mutex);
469
470
    ereport(DEBUG1,
471
        (errmsg_internal("standby \"%s\" now has synchronous standby priority %d",
472
                 application_name, priority)));
473
  }
474
}
475
476
/*
477
 * Update the LSNs on each queue based upon our latest state. This
478
 * implements a simple policy of first-valid-sync-standby-releases-waiter.
479
 *
480
 * Other policies are possible, which would change what we do here and
481
 * perhaps also which information we store as well.
482
 */
483
void
484
SyncRepReleaseWaiters(void)
485
{
486
  XLogRecPtr  writePtr;
487
  XLogRecPtr  flushPtr;
488
  XLogRecPtr  applyPtr;
489
  bool    got_recptr;
490
  bool    am_sync;
491
  int     numwrite = 0;
492
  int     numflush = 0;
493
  int     numapply = 0;
494
495
  /*
496
   * If this WALSender is serving a standby that is not on the list of
497
   * potential sync standbys then we have nothing to do. If we are still
498
   * starting up, still running base backup or the current flush position is
499
   * still invalid, then leave quickly also.  Streaming or stopping WAL
500
   * senders are allowed to release waiters.
501
   */
502
  if (MyWalSnd->sync_standby_priority == 0 ||
503
    (MyWalSnd->state != WALSNDSTATE_STREAMING &&
504
     MyWalSnd->state != WALSNDSTATE_STOPPING) ||
505
    !XLogRecPtrIsValid(MyWalSnd->flush))
506
  {
507
    announce_next_takeover = true;
508
    return;
509
  }
510
511
  /*
512
   * We're a potential sync standby. Release waiters if there are enough
513
   * sync standbys and we are considered as sync.
514
   */
515
  LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
516
517
  /*
518
   * Check whether we are a sync standby or not, and calculate the synced
519
   * positions among all sync standbys.  (Note: although this step does not
520
   * of itself require holding SyncRepLock, it seems like a good idea to do
521
   * it after acquiring the lock.  This ensures that the WAL pointers we use
522
   * to release waiters are newer than any previous execution of this
523
   * routine used.)
524
   */
525
  got_recptr = SyncRepGetSyncRecPtr(&writePtr, &flushPtr, &applyPtr, &am_sync);
526
527
  /*
528
   * If we are managing a sync standby, though we weren't prior to this,
529
   * then announce we are now a sync standby.
530
   */
531
  if (announce_next_takeover && am_sync)
532
  {
533
    announce_next_takeover = false;
534
535
    if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY)
536
      ereport(LOG,
537
          (errmsg("standby \"%s\" is now a synchronous standby with priority %d",
538
              application_name, MyWalSnd->sync_standby_priority)));
539
    else
540
      ereport(LOG,
541
          (errmsg("standby \"%s\" is now a candidate for quorum synchronous standby",
542
              application_name)));
543
  }
544
545
  /*
546
   * If the number of sync standbys is less than requested or we aren't
547
   * managing a sync standby then just leave.
548
   */
549
  if (!got_recptr || !am_sync)
550
  {
551
    LWLockRelease(SyncRepLock);
552
    announce_next_takeover = !am_sync;
553
    return;
554
  }
555
556
  /*
557
   * Set the lsn first so that when we wake backends they will release up to
558
   * this location.
559
   */
560
  if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr)
561
  {
562
    WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr;
563
    numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE);
564
  }
565
  if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr)
566
  {
567
    WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr;
568
    numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH);
569
  }
570
  if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr)
571
  {
572
    WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr;
573
    numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY);
574
  }
575
576
  LWLockRelease(SyncRepLock);
577
578
  elog(DEBUG3, "released %d procs up to write %X/%08X, %d procs up to flush %X/%08X, %d procs up to apply %X/%08X",
579
     numwrite, LSN_FORMAT_ARGS(writePtr),
580
     numflush, LSN_FORMAT_ARGS(flushPtr),
581
     numapply, LSN_FORMAT_ARGS(applyPtr));
582
}
583
584
/*
585
 * Calculate the synced Write, Flush and Apply positions among sync standbys.
586
 *
587
 * Return false if the number of sync standbys is less than
588
 * synchronous_standby_names specifies. Otherwise return true and
589
 * store the positions into *writePtr, *flushPtr and *applyPtr.
590
 *
591
 * On return, *am_sync is set to true if this walsender is connecting to
592
 * sync standby. Otherwise it's set to false.
593
 */
594
static bool
595
SyncRepGetSyncRecPtr(XLogRecPtr *writePtr, XLogRecPtr *flushPtr,
596
           XLogRecPtr *applyPtr, bool *am_sync)
597
0
{
598
0
  SyncRepStandbyData *sync_standbys;
599
0
  int     num_standbys;
600
0
  int     i;
601
602
  /* Initialize default results */
603
0
  *writePtr = InvalidXLogRecPtr;
604
0
  *flushPtr = InvalidXLogRecPtr;
605
0
  *applyPtr = InvalidXLogRecPtr;
606
0
  *am_sync = false;
607
608
  /* Quick out if not even configured to be synchronous */
609
0
  if (SyncRepConfig == NULL)
610
0
    return false;
611
612
  /* Get standbys that are considered as synchronous at this moment */
613
0
  num_standbys = SyncRepGetCandidateStandbys(&sync_standbys);
614
615
  /* Am I among the candidate sync standbys? */
616
0
  for (i = 0; i < num_standbys; i++)
617
0
  {
618
0
    if (sync_standbys[i].is_me)
619
0
    {
620
0
      *am_sync = true;
621
0
      break;
622
0
    }
623
0
  }
624
625
  /*
626
   * Nothing more to do if we are not managing a sync standby or there are
627
   * not enough synchronous standbys.
628
   */
629
0
  if (!(*am_sync) ||
630
0
    num_standbys < SyncRepConfig->num_sync)
631
0
  {
632
0
    pfree(sync_standbys);
633
0
    return false;
634
0
  }
635
636
  /*
637
   * In a priority-based sync replication, the synced positions are the
638
   * oldest ones among sync standbys. In a quorum-based, they are the Nth
639
   * latest ones.
640
   *
641
   * SyncRepGetNthLatestSyncRecPtr() also can calculate the oldest
642
   * positions. But we use SyncRepGetOldestSyncRecPtr() for that calculation
643
   * because it's a bit more efficient.
644
   *
645
   * XXX If the numbers of current and requested sync standbys are the same,
646
   * we can use SyncRepGetOldestSyncRecPtr() to calculate the synced
647
   * positions even in a quorum-based sync replication.
648
   */
649
0
  if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY)
650
0
  {
651
0
    SyncRepGetOldestSyncRecPtr(writePtr, flushPtr, applyPtr,
652
0
                   sync_standbys, num_standbys);
653
0
  }
654
0
  else
655
0
  {
656
0
    SyncRepGetNthLatestSyncRecPtr(writePtr, flushPtr, applyPtr,
657
0
                    sync_standbys, num_standbys,
658
0
                    SyncRepConfig->num_sync);
659
0
  }
660
661
0
  pfree(sync_standbys);
662
0
  return true;
663
0
}
664
665
/*
666
 * Calculate the oldest Write, Flush and Apply positions among sync standbys.
667
 */
668
static void
669
SyncRepGetOldestSyncRecPtr(XLogRecPtr *writePtr,
670
               XLogRecPtr *flushPtr,
671
               XLogRecPtr *applyPtr,
672
               SyncRepStandbyData *sync_standbys,
673
               int num_standbys)
674
0
{
675
0
  int     i;
676
677
  /*
678
   * Scan through all sync standbys and calculate the oldest Write, Flush
679
   * and Apply positions.  We assume *writePtr et al were initialized to
680
   * InvalidXLogRecPtr.
681
   */
682
0
  for (i = 0; i < num_standbys; i++)
683
0
  {
684
0
    XLogRecPtr  write = sync_standbys[i].write;
685
0
    XLogRecPtr  flush = sync_standbys[i].flush;
686
0
    XLogRecPtr  apply = sync_standbys[i].apply;
687
688
0
    if (!XLogRecPtrIsValid(*writePtr) || *writePtr > write)
689
0
      *writePtr = write;
690
0
    if (!XLogRecPtrIsValid(*flushPtr) || *flushPtr > flush)
691
0
      *flushPtr = flush;
692
0
    if (!XLogRecPtrIsValid(*applyPtr) || *applyPtr > apply)
693
0
      *applyPtr = apply;
694
0
  }
695
0
}
696
697
/*
698
 * Calculate the Nth latest Write, Flush and Apply positions among sync
699
 * standbys.
700
 */
701
static void
702
SyncRepGetNthLatestSyncRecPtr(XLogRecPtr *writePtr,
703
                XLogRecPtr *flushPtr,
704
                XLogRecPtr *applyPtr,
705
                SyncRepStandbyData *sync_standbys,
706
                int num_standbys,
707
                uint8 nth)
708
0
{
709
0
  XLogRecPtr *write_array;
710
0
  XLogRecPtr *flush_array;
711
0
  XLogRecPtr *apply_array;
712
0
  int     i;
713
714
  /* Should have enough candidates, or somebody messed up */
715
0
  Assert(nth > 0 && nth <= num_standbys);
716
717
0
  write_array = palloc_array(XLogRecPtr, num_standbys);
718
0
  flush_array = palloc_array(XLogRecPtr, num_standbys);
719
0
  apply_array = palloc_array(XLogRecPtr, num_standbys);
720
721
0
  for (i = 0; i < num_standbys; i++)
722
0
  {
723
0
    write_array[i] = sync_standbys[i].write;
724
0
    flush_array[i] = sync_standbys[i].flush;
725
0
    apply_array[i] = sync_standbys[i].apply;
726
0
  }
727
728
  /* Sort each array in descending order */
729
0
  qsort(write_array, num_standbys, sizeof(XLogRecPtr), cmp_lsn);
730
0
  qsort(flush_array, num_standbys, sizeof(XLogRecPtr), cmp_lsn);
731
0
  qsort(apply_array, num_standbys, sizeof(XLogRecPtr), cmp_lsn);
732
733
  /* Get Nth latest Write, Flush, Apply positions */
734
0
  *writePtr = write_array[nth - 1];
735
0
  *flushPtr = flush_array[nth - 1];
736
0
  *applyPtr = apply_array[nth - 1];
737
738
0
  pfree(write_array);
739
0
  pfree(flush_array);
740
0
  pfree(apply_array);
741
0
}
742
743
/*
744
 * Compare lsn in order to sort array in descending order.
745
 */
746
static int
747
cmp_lsn(const void *a, const void *b)
748
0
{
749
0
  XLogRecPtr  lsn1 = *((const XLogRecPtr *) a);
750
0
  XLogRecPtr  lsn2 = *((const XLogRecPtr *) b);
751
752
0
  return pg_cmp_u64(lsn2, lsn1);
753
0
}
754
755
/*
756
 * Return data about walsenders that are candidates to be sync standbys.
757
 *
758
 * *standbys is set to a palloc'd array of structs of per-walsender data,
759
 * and the number of valid entries (candidate sync senders) is returned.
760
 * (This might be more or fewer than num_sync; caller must check.)
761
 */
762
int
763
SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys)
764
0
{
765
0
  int     i;
766
0
  int     n;
767
768
  /* Create result array */
769
0
  *standbys = palloc_array(SyncRepStandbyData, max_wal_senders);
770
771
  /* Quick exit if sync replication is not requested */
772
0
  if (SyncRepConfig == NULL)
773
0
    return 0;
774
775
  /* Collect raw data from shared memory */
776
0
  n = 0;
777
0
  for (i = 0; i < max_wal_senders; i++)
778
0
  {
779
0
    WalSnd     *walsnd;
780
0
    SyncRepStandbyData *stby;
781
0
    WalSndState state;    /* not included in SyncRepStandbyData */
782
783
0
    walsnd = &WalSndCtl->walsnds[i];
784
0
    stby = *standbys + n;
785
786
0
    SpinLockAcquire(&walsnd->mutex);
787
0
    stby->pid = walsnd->pid;
788
0
    state = walsnd->state;
789
0
    stby->write = walsnd->write;
790
0
    stby->flush = walsnd->flush;
791
0
    stby->apply = walsnd->apply;
792
0
    stby->sync_standby_priority = walsnd->sync_standby_priority;
793
0
    SpinLockRelease(&walsnd->mutex);
794
795
    /* Must be active */
796
0
    if (stby->pid == 0)
797
0
      continue;
798
799
    /* Must be streaming or stopping */
800
0
    if (state != WALSNDSTATE_STREAMING &&
801
0
      state != WALSNDSTATE_STOPPING)
802
0
      continue;
803
804
    /* Must be synchronous */
805
0
    if (stby->sync_standby_priority == 0)
806
0
      continue;
807
808
    /* Must have a valid flush position */
809
0
    if (!XLogRecPtrIsValid(stby->flush))
810
0
      continue;
811
812
    /* OK, it's a candidate */
813
0
    stby->walsnd_index = i;
814
0
    stby->is_me = (walsnd == MyWalSnd);
815
0
    n++;
816
0
  }
817
818
  /*
819
   * In quorum mode, we return all the candidates.  In priority mode, if we
820
   * have too many candidates then return only the num_sync ones of highest
821
   * priority.
822
   */
823
0
  if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY &&
824
0
    n > SyncRepConfig->num_sync)
825
0
  {
826
    /* Sort by priority ... */
827
0
    qsort(*standbys, n, sizeof(SyncRepStandbyData),
828
0
        standby_priority_comparator);
829
    /* ... then report just the first num_sync ones */
830
0
    n = SyncRepConfig->num_sync;
831
0
  }
832
833
0
  return n;
834
0
}
835
836
/*
837
 * qsort comparator to sort SyncRepStandbyData entries by priority
838
 */
839
static int
840
standby_priority_comparator(const void *a, const void *b)
841
0
{
842
0
  const SyncRepStandbyData *sa = (const SyncRepStandbyData *) a;
843
0
  const SyncRepStandbyData *sb = (const SyncRepStandbyData *) b;
844
845
  /* First, sort by increasing priority value */
846
0
  if (sa->sync_standby_priority != sb->sync_standby_priority)
847
0
    return sa->sync_standby_priority - sb->sync_standby_priority;
848
849
  /*
850
   * We might have equal priority values; arbitrarily break ties by position
851
   * in the WalSnd array.  (This is utterly bogus, since that is arrival
852
   * order dependent, but there are regression tests that rely on it.)
853
   */
854
0
  return sa->walsnd_index - sb->walsnd_index;
855
0
}
856
857
858
/*
859
 * Check if we are in the list of sync standbys, and if so, determine
860
 * priority sequence. Return priority if set, or zero to indicate that
861
 * we are not a potential sync standby.
862
 *
863
 * Compare the parameter SyncRepStandbyNames against the application_name
864
 * for this WALSender, or allow any name if we find a wildcard "*".
865
 */
866
static int
867
SyncRepGetStandbyPriority(void)
868
0
{
869
0
  const char *standby_name;
870
0
  int     priority;
871
0
  bool    found = false;
872
873
  /*
874
   * Since synchronous cascade replication is not allowed, we always set the
875
   * priority of cascading walsender to zero.
876
   */
877
0
  if (am_cascading_walsender)
878
0
    return 0;
879
880
0
  if (!SyncStandbysDefined() || SyncRepConfig == NULL)
881
0
    return 0;
882
883
0
  standby_name = SyncRepConfig->member_names;
884
0
  for (priority = 1; priority <= SyncRepConfig->nmembers; priority++)
885
0
  {
886
0
    if (pg_strcasecmp(standby_name, application_name) == 0 ||
887
0
      strcmp(standby_name, "*") == 0)
888
0
    {
889
0
      found = true;
890
0
      break;
891
0
    }
892
0
    standby_name += strlen(standby_name) + 1;
893
0
  }
894
895
0
  if (!found)
896
0
    return 0;
897
898
  /*
899
   * In quorum-based sync replication, all the standbys in the list have the
900
   * same priority, one.
901
   */
902
0
  return (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY) ? priority : 1;
903
0
}
904
905
/*
906
 * Walk the specified queue from head.  Set the state of any backends that
907
 * need to be woken, remove them from the queue, and then wake them.
908
 * Pass all = true to wake whole queue; otherwise, just wake up to
909
 * the walsender's LSN.
910
 *
911
 * The caller must hold SyncRepLock in exclusive mode.
912
 */
913
static int
914
SyncRepWakeQueue(bool all, int mode)
915
0
{
916
0
  int     numprocs = 0;
917
0
  dlist_mutable_iter iter;
918
919
0
  Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
920
0
  Assert(LWLockHeldByMeInMode(SyncRepLock, LW_EXCLUSIVE));
921
0
  Assert(SyncRepQueueIsOrderedByLSN(mode));
922
923
0
  dlist_foreach_modify(iter, &WalSndCtl->SyncRepQueue[mode])
924
0
  {
925
0
    PGPROC     *proc = dlist_container(PGPROC, syncRepLinks, iter.cur);
926
927
    /*
928
     * Assume the queue is ordered by LSN
929
     */
930
0
    if (!all && WalSndCtl->lsn[mode] < proc->waitLSN)
931
0
      return numprocs;
932
933
    /*
934
     * Remove from queue.
935
     */
936
0
    dlist_delete_thoroughly(&proc->syncRepLinks);
937
938
    /*
939
     * SyncRepWaitForLSN() reads syncRepState without holding the lock, so
940
     * make sure that it sees the queue link being removed before the
941
     * syncRepState change.
942
     */
943
0
    pg_write_barrier();
944
945
    /*
946
     * Set state to complete; see SyncRepWaitForLSN() for discussion of
947
     * the various states.
948
     */
949
0
    proc->syncRepState = SYNC_REP_WAIT_COMPLETE;
950
951
    /*
952
     * Wake only when we have set state and removed from queue.
953
     */
954
0
    SetLatch(&(proc->procLatch));
955
956
0
    numprocs++;
957
0
  }
958
959
0
  return numprocs;
960
0
}
961
962
/*
963
 * The checkpointer calls this as needed to update the shared
964
 * sync_standbys_status flag, so that backends don't remain permanently wedged
965
 * if synchronous_standby_names is unset.  It's safe to check the current value
966
 * without the lock, because it's only ever updated by one process.  But we
967
 * must take the lock to change it.
968
 */
969
void
970
SyncRepUpdateSyncStandbysDefined(void)
971
0
{
972
0
  bool    sync_standbys_defined = SyncStandbysDefined();
973
974
0
  if (sync_standbys_defined !=
975
0
    ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_DEFINED) != 0))
976
0
  {
977
0
    LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
978
979
    /*
980
     * If synchronous_standby_names has been reset to empty, it's futile
981
     * for backends to continue waiting.  Since the user no longer wants
982
     * synchronous replication, we'd better wake them up.
983
     */
984
0
    if (!sync_standbys_defined)
985
0
    {
986
0
      int     i;
987
988
0
      for (i = 0; i < NUM_SYNC_REP_WAIT_MODE; i++)
989
0
        SyncRepWakeQueue(true, i);
990
0
    }
991
992
    /*
993
     * Only allow people to join the queue when there are synchronous
994
     * standbys defined.  Without this interlock, there's a race
995
     * condition: we might wake up all the current waiters; then, some
996
     * backend that hasn't yet reloaded its config might go to sleep on
997
     * the queue (and never wake up).  This prevents that.
998
     */
999
0
    WalSndCtl->sync_standbys_status = SYNC_STANDBY_INIT |
1000
0
      (sync_standbys_defined ? SYNC_STANDBY_DEFINED : 0);
1001
1002
0
    LWLockRelease(SyncRepLock);
1003
0
  }
1004
0
  else if ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_INIT) == 0)
1005
0
  {
1006
0
    LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
1007
1008
    /*
1009
     * Note that there is no need to wake up the queues here.  We would
1010
     * reach this path only if SyncStandbysDefined() returns false, or it
1011
     * would mean that some backends are waiting with the GUC set.  See
1012
     * SyncRepWaitForLSN().
1013
     */
1014
0
    Assert(!SyncStandbysDefined());
1015
1016
    /*
1017
     * Even if there is no sync standby defined, let the readers of this
1018
     * information know that the sync standby data has been initialized.
1019
     * This can just be done once, hence the previous check on
1020
     * SYNC_STANDBY_INIT to avoid useless work.
1021
     */
1022
0
    WalSndCtl->sync_standbys_status |= SYNC_STANDBY_INIT;
1023
1024
0
    LWLockRelease(SyncRepLock);
1025
0
  }
1026
0
}
1027
1028
#ifdef USE_ASSERT_CHECKING
1029
static bool
1030
SyncRepQueueIsOrderedByLSN(int mode)
1031
{
1032
  XLogRecPtr  lastLSN;
1033
  dlist_iter  iter;
1034
1035
  Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
1036
1037
  lastLSN = InvalidXLogRecPtr;
1038
1039
  dlist_foreach(iter, &WalSndCtl->SyncRepQueue[mode])
1040
  {
1041
    PGPROC     *proc = dlist_container(PGPROC, syncRepLinks, iter.cur);
1042
1043
    /*
1044
     * Check the queue is ordered by LSN and that multiple procs don't
1045
     * have matching LSNs
1046
     */
1047
    if (proc->waitLSN <= lastLSN)
1048
      return false;
1049
1050
    lastLSN = proc->waitLSN;
1051
  }
1052
1053
  return true;
1054
}
1055
#endif
1056
1057
/*
1058
 * ===========================================================
1059
 * Synchronous Replication functions executed by any process
1060
 * ===========================================================
1061
 */
1062
1063
bool
1064
check_synchronous_standby_names(char **newval, void **extra, GucSource source)
1065
2
{
1066
2
  if (*newval != NULL && (*newval)[0] != '\0')
1067
0
  {
1068
0
    yyscan_t  scanner;
1069
0
    int     parse_rc;
1070
0
    SyncRepConfigData *pconf;
1071
1072
    /* Result of parsing is returned in one of these two variables */
1073
0
    SyncRepConfigData *syncrep_parse_result = NULL;
1074
0
    char     *syncrep_parse_error_msg = NULL;
1075
1076
    /* Parse the synchronous_standby_names string */
1077
0
    syncrep_scanner_init(*newval, &scanner);
1078
0
    parse_rc = syncrep_yyparse(&syncrep_parse_result, &syncrep_parse_error_msg, scanner);
1079
0
    syncrep_scanner_finish(scanner);
1080
1081
0
    if (parse_rc != 0 || syncrep_parse_result == NULL)
1082
0
    {
1083
0
      GUC_check_errcode(ERRCODE_SYNTAX_ERROR);
1084
0
      if (syncrep_parse_error_msg)
1085
0
        GUC_check_errdetail("%s", syncrep_parse_error_msg);
1086
0
      else
1087
        /* translator: %s is a GUC name */
1088
0
        GUC_check_errdetail("\"%s\" parser failed.",
1089
0
                  "synchronous_standby_names");
1090
0
      return false;
1091
0
    }
1092
1093
0
    if (syncrep_parse_result->num_sync <= 0)
1094
0
    {
1095
0
      GUC_check_errmsg("number of synchronous standbys (%d) must be greater than zero",
1096
0
               syncrep_parse_result->num_sync);
1097
0
      return false;
1098
0
    }
1099
1100
    /* GUC extra value must be guc_malloc'd, not palloc'd */
1101
0
    pconf = (SyncRepConfigData *)
1102
0
      guc_malloc(LOG, syncrep_parse_result->config_size);
1103
0
    if (pconf == NULL)
1104
0
      return false;
1105
0
    memcpy(pconf, syncrep_parse_result, syncrep_parse_result->config_size);
1106
1107
0
    *extra = pconf;
1108
1109
    /*
1110
     * We need not explicitly clean up syncrep_parse_result.  It, and any
1111
     * other cruft generated during parsing, will be freed when the
1112
     * current memory context is deleted.  (This code is generally run in
1113
     * a short-lived context used for config file processing, so that will
1114
     * not be very long.)
1115
     */
1116
0
  }
1117
2
  else
1118
2
    *extra = NULL;
1119
1120
2
  return true;
1121
2
}
1122
1123
void
1124
assign_synchronous_standby_names(const char *newval, void *extra)
1125
2
{
1126
2
  SyncRepConfig = (SyncRepConfigData *) extra;
1127
2
}
1128
1129
void
1130
assign_synchronous_commit(int newval, void *extra)
1131
2
{
1132
2
  switch (newval)
1133
2
  {
1134
0
    case SYNCHRONOUS_COMMIT_REMOTE_WRITE:
1135
0
      SyncRepWaitMode = SYNC_REP_WAIT_WRITE;
1136
0
      break;
1137
2
    case SYNCHRONOUS_COMMIT_REMOTE_FLUSH:
1138
2
      SyncRepWaitMode = SYNC_REP_WAIT_FLUSH;
1139
2
      break;
1140
0
    case SYNCHRONOUS_COMMIT_REMOTE_APPLY:
1141
0
      SyncRepWaitMode = SYNC_REP_WAIT_APPLY;
1142
0
      break;
1143
0
    default:
1144
0
      SyncRepWaitMode = SYNC_REP_NO_WAIT;
1145
0
      break;
1146
2
  }
1147
2
}