Jeff Janes wrote:

> I'm attaching a patch for each option.  Each one independently solves the
> problem.  But I think we should do both.  There is no point in issuing
> unnecessary kill system calls, and there may also be more spurious wake-ups
> than just these ones.

I modified patch 1 a bit -- result attached.  I would like to back-patch
this all the way back to 9.4, but there are a few conflicts due to
c29aff959dc so I think I'm going to do pg10 only unless I get some votes
that it should go further back.  I think it should be fairly trivial to
resolve.

The other patch should be applied to master only IMO.

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
>From e482f52f792df3685f4f9d955d54e04570db5cc5 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvhe...@alvh.no-ip.org>
Date: Mon, 4 Sep 2017 13:18:44 +0200
Subject: [PATCH] fix basebackup throttle

---
 src/backend/replication/basebackup.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/backend/replication/basebackup.c 
b/src/backend/replication/basebackup.c
index 9776858f03..4db79d733c 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1336,10 +1336,7 @@ _tarWriteDir(const char *pathbuf, int basepathlen, 
struct stat *statbuf,
 static void
 throttle(size_t increment)
 {
-       TimeOffset      elapsed,
-                               elapsed_min,
-                               sleep;
-       int                     wait_result;
+       TimeOffset      elapsed_min;
 
        if (throttling_counter < 0)
                return;
@@ -1348,14 +1345,29 @@ throttle(size_t increment)
        if (throttling_counter < throttling_sample)
                return;
 
-       /* Time elapsed since the last measurement (and possible wake up). */
-       elapsed = GetCurrentTimestamp() - throttled_last;
-       /* How much should have elapsed at minimum? */
-       elapsed_min = elapsed_min_unit * (throttling_counter / 
throttling_sample);
-       sleep = elapsed_min - elapsed;
-       /* Only sleep if the transfer is faster than it should be. */
-       if (sleep > 0)
+       /* How much time should have elapsed at minimum? */
+       elapsed_min = elapsed_min_unit *
+               (throttling_counter / throttling_sample);
+
+       /*
+        * Since the latch could be set repeatedly because of concurrently WAL
+        * activity, sleep enough times in a loop to ensure enough time has
+        * passed.
+        */
+       for (;;)
        {
+               TimeOffset      elapsed,
+                                       sleep;
+               int                     wait_result;
+
+               /* Time elapsed since the last measurement (and possible wake 
up). */
+               elapsed = GetCurrentTimestamp() - throttled_last;
+
+               /* sleep if the transfer is faster than it should be */
+               sleep = elapsed_min - elapsed;
+               if (sleep <= 0)
+                       break;
+
                ResetLatch(MyLatch);
 
                /* We're eating a potentially set latch, so check for 
interrupts */
-- 
2.11.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to