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

Commit6f60fdd

Browse files
committed
Improve replication connection timeouts.
Rename replication_timeout to wal_sender_timeout, and add a new settingcalled wal_receiver_timeout that does the same at the walreceiver side.There was previously no timeout in walreceiver, so if the network went down,for example, the walreceiver could take a long time to notice that theconnection was lost. Now with the two settings, both sides of a replicationconnection will detect a broken connection similarly.It is no longer necessary to manually set wal_receiver_status_interval toa value smaller than the timeout. Both wal sender and receiver nowautomatically send a "ping" message if more than 1/2 of the configuredtimeout has elapsed, and it hasn't received any messages from the other end.Amit Kapila, heavily edited by me.
1 parent8521d13 commit6f60fdd

File tree

10 files changed

+190
-67
lines changed

10 files changed

+190
-67
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,10 +2236,10 @@ include 'filename'
22362236
</listitem>
22372237
</varlistentry>
22382238

2239-
<varlistentry id="guc-replication-timeout" xreflabel="replication_timeout">
2240-
<term><varname>replication_timeout</varname> (<type>integer</type>)</term>
2239+
<varlistentry id="guc-wal-sender-timeout" xreflabel="wal_sender_timeout">
2240+
<term><varname>wal_sender_timeout</varname> (<type>integer</type>)</term>
22412241
<indexterm>
2242-
<primary><varname>replication_timeout</> configuration parameter</primary>
2242+
<primary><varname>wal_sender_timeout</> configuration parameter</primary>
22432243
</indexterm>
22442244
<listitem>
22452245
<para>
@@ -2251,12 +2251,6 @@ include 'filename'
22512251
the <filename>postgresql.conf</> file or on the server command line.
22522252
The default value is 60 seconds.
22532253
</para>
2254-
<para>
2255-
To prevent connections from being terminated prematurely,
2256-
<xref linkend="guc-wal-receiver-status-interval">
2257-
must be enabled on the standby, and its value must be less than the
2258-
value of <varname>replication_timeout</>.
2259-
</para>
22602254
</listitem>
22612255
</varlistentry>
22622256

@@ -2474,11 +2468,6 @@ include 'filename'
24742468
the <filename>postgresql.conf</> file or on the server command line.
24752469
The default value is 10 seconds.
24762470
</para>
2477-
<para>
2478-
When <xref linkend="guc-replication-timeout"> is enabled on a sending server,
2479-
<varname>wal_receiver_status_interval</> must be enabled, and its value
2480-
must be less than the value of <varname>replication_timeout</>.
2481-
</para>
24822471
</listitem>
24832472
</varlistentry>
24842473

@@ -2507,6 +2496,25 @@ include 'filename'
25072496
</listitem>
25082497
</varlistentry>
25092498

2499+
<varlistentry id="guc-wal-receiver-timeout" xreflabel="wal_receiver_timeout">
2500+
<term><varname>wal_receiver_timeout</varname> (<type>integer</type>)</term>
2501+
<indexterm>
2502+
<primary><varname>wal_receiver_timeout</> configuration parameter</primary>
2503+
</indexterm>
2504+
<listitem>
2505+
<para>
2506+
Terminate replication connections that are inactive longer
2507+
than the specified number of milliseconds. This is useful for
2508+
the receiving standby server to detect a primary node crash or network
2509+
outage.
2510+
A value of zero disables the timeout mechanism. This parameter
2511+
can only be set in
2512+
the <filename>postgresql.conf</> file or on the server command line.
2513+
The default value is 60 seconds.
2514+
</para>
2515+
</listitem>
2516+
</varlistentry>
2517+
25102518
</variablelist>
25112519
</sect2>
25122520
</sect1>

‎doc/src/sgml/release-9.1.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3322,7 +3322,7 @@
33223322
<listitem>
33233323
<para>
33243324
Add
3325-
<link linkend="guc-replication-timeout"><varname>replication_timeout</></link>
3325+
<varname>replication_timeout</>
33263326
setting (Fujii Masao, Heikki Linnakangas)
33273327
</para>
33283328

‎src/backend/replication/walreceiver.c

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
/* GUC variables */
5757
intwal_receiver_status_interval;
58+
intwal_receiver_timeout;
5859
boolhot_standby_feedback;
5960

6061
/* libpqreceiver hooks to these when loaded */
@@ -121,7 +122,7 @@ static void WalRcvDie(int code, Datum arg);
121122
staticvoidXLogWalRcvProcessMsg(unsignedchartype,char*buf,Sizelen);
122123
staticvoidXLogWalRcvWrite(char*buf,Sizenbytes,XLogRecPtrrecptr);
123124
staticvoidXLogWalRcvFlush(booldying);
124-
staticvoidXLogWalRcvSendReply(void);
125+
staticvoidXLogWalRcvSendReply(boolforce,boolrequestReply);
125126
staticvoidXLogWalRcvSendHSFeedback(void);
126127
staticvoidProcessWalSndrMessage(XLogRecPtrwalEnd,TimestampTzsendTime);
127128

@@ -170,9 +171,10 @@ WalReceiverMain(void)
170171
{
171172
charconninfo[MAXCONNINFO];
172173
XLogRecPtrstartpoint;
173-
174174
/* use volatile pointer to prevent code rearrangement */
175175
volatileWalRcvData*walrcv=WalRcv;
176+
TimestampTzlast_recv_timestamp;
177+
boolping_sent;
176178

177179
/*
178180
* WalRcv should be set up already (if we are a backend, we inherit this
@@ -282,6 +284,10 @@ WalReceiverMain(void)
282284
MemSet(&reply_message,0,sizeof(reply_message));
283285
MemSet(&feedback_message,0,sizeof(feedback_message));
284286

287+
/* Initialize the last recv timestamp */
288+
last_recv_timestamp=GetCurrentTimestamp();
289+
ping_sent= false;
290+
285291
/* Loop until end-of-streaming or error */
286292
for (;;)
287293
{
@@ -316,15 +322,23 @@ WalReceiverMain(void)
316322
/* Wait a while for data to arrive */
317323
if (walrcv_receive(NAPTIME_PER_CYCLE,&type,&buf,&len))
318324
{
325+
/* Something was received from master, so reset timeout */
326+
last_recv_timestamp=GetCurrentTimestamp();
327+
ping_sent= false;
328+
319329
/* Accept the received data, and process it */
320330
XLogWalRcvProcessMsg(type,buf,len);
321331

322332
/* Receive any more data we can without sleeping */
323333
while (walrcv_receive(0,&type,&buf,&len))
334+
{
335+
last_recv_timestamp=GetCurrentTimestamp();
336+
ping_sent= false;
324337
XLogWalRcvProcessMsg(type,buf,len);
338+
}
325339

326340
/* Let the master know that we received some data. */
327-
XLogWalRcvSendReply();
341+
XLogWalRcvSendReply(false, false);
328342

329343
/*
330344
* If we've written some records, flush them to disk and let the
@@ -335,10 +349,48 @@ WalReceiverMain(void)
335349
else
336350
{
337351
/*
338-
* We didn't receive anything new, but send a status update to the
339-
* master anyway, to report any progress in applying WAL.
352+
* We didn't receive anything new. If we haven't heard anything
353+
* from the server for more than wal_receiver_timeout / 2,
354+
* ping the server. Also, if it's been longer than
355+
* wal_receiver_status_interval since the last update we sent,
356+
* send a status update to the master anyway, to report any
357+
* progress in applying WAL.
358+
*/
359+
boolrequestReply= false;
360+
361+
/*
362+
* Check if time since last receive from standby has reached the
363+
* configured limit.
340364
*/
341-
XLogWalRcvSendReply();
365+
if (wal_receiver_timeout>0)
366+
{
367+
TimestampTznow=GetCurrentTimestamp();
368+
TimestampTztimeout;
369+
370+
timeout=TimestampTzPlusMilliseconds(last_recv_timestamp,
371+
wal_receiver_timeout);
372+
373+
if (now >=timeout)
374+
ereport(ERROR,
375+
(errmsg("terminating walreceiver due to timeout")));
376+
377+
/*
378+
* We didn't receive anything new, for half of receiver
379+
* replication timeout. Ping the server.
380+
*/
381+
if (!ping_sent)
382+
{
383+
timeout=TimestampTzPlusMilliseconds(last_recv_timestamp,
384+
(wal_receiver_timeout/2));
385+
if (now >=timeout)
386+
{
387+
requestReply= true;
388+
ping_sent= true;
389+
}
390+
}
391+
}
392+
393+
XLogWalRcvSendReply(requestReply,requestReply);
342394
XLogWalRcvSendHSFeedback();
343395
}
344396
}
@@ -460,6 +512,10 @@ XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len)
460512
memcpy(&keepalive,buf,sizeof(PrimaryKeepaliveMessage));
461513

462514
ProcessWalSndrMessage(keepalive.walEnd,keepalive.sendTime);
515+
516+
/* If the primary requested a reply, send one immediately */
517+
if (keepalive.replyRequested)
518+
XLogWalRcvSendReply(true, false);
463519
break;
464520
}
465521
default:
@@ -609,19 +665,25 @@ XLogWalRcvFlush(bool dying)
609665

610666
/* Also let the master know that we made some progress */
611667
if (!dying)
612-
{
613-
XLogWalRcvSendReply();
614-
XLogWalRcvSendHSFeedback();
615-
}
668+
XLogWalRcvSendReply(false, false);
616669
}
617670
}
618671

619672
/*
620-
* Send reply message to primary, indicating our current XLOG positions and
621-
* the current time.
673+
* Send reply message to primary, indicating our current XLOG positions, oldest
674+
* xmin and the current time.
675+
*
676+
* If 'force' is not set, the message is only sent if enough time has
677+
* passed since last status update to reach wal_receiver_status_internal.
678+
* If wal_receiver_status_interval is disabled altogether and 'force' is
679+
* false, this is a no-op.
680+
*
681+
* If 'requestReply' is true, requests the server to reply immediately upon
682+
* receiving this message. This is used for heartbearts, when approaching
683+
* wal_receiver_timeout.
622684
*/
623685
staticvoid
624-
XLogWalRcvSendReply(void)
686+
XLogWalRcvSendReply(boolforce,boolrequestReply)
625687
{
626688
charbuf[sizeof(StandbyReplyMessage)+1];
627689
TimestampTznow;
@@ -630,7 +692,7 @@ XLogWalRcvSendReply(void)
630692
* If the user doesn't want status to be reported to the master, be sure
631693
* to exit before doing anything at all.
632694
*/
633-
if (wal_receiver_status_interval <=0)
695+
if (!force&&wal_receiver_status_interval <=0)
634696
return;
635697

636698
/* Get current timestamp. */
@@ -645,7 +707,8 @@ XLogWalRcvSendReply(void)
645707
* this is only for reporting purposes and only on idle systems, that's
646708
* probably OK.
647709
*/
648-
if (XLByteEQ(reply_message.write,LogstreamResult.Write)
710+
if (!force
711+
&&XLByteEQ(reply_message.write,LogstreamResult.Write)
649712
&&XLByteEQ(reply_message.flush,LogstreamResult.Flush)
650713
&& !TimestampDifferenceExceeds(reply_message.sendTime,now,
651714
wal_receiver_status_interval*1000))
@@ -656,6 +719,7 @@ XLogWalRcvSendReply(void)
656719
reply_message.flush=LogstreamResult.Flush;
657720
reply_message.apply=GetXLogReplayRecPtr(NULL);
658721
reply_message.sendTime=now;
722+
reply_message.replyRequested=requestReply;
659723

660724
elog(DEBUG2,"sending write %X/%X flush %X/%X apply %X/%X",
661725
(uint32) (reply_message.write >>32), (uint32)reply_message.write,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp