At Fri, 28 Apr 2023 11:15:51 +0900 (JST), Kyotaro Horiguchi
<[email protected]> wrote in
> At Thu, 27 Apr 2023 17:30:40 -0400, Melanie Plageman
> <[email protected]> wrote in
> > After a quick example implementation of this, I found that it seemed to
> > try and flush the stats less often on an idle standby (good) than using
> > enable_timeout_every().
>
> Just rearming with the full-interval will work that way. Our existing
> strategy for this is seen in PostgresMain().
>
> stats_timeout = pgstat_report_stat(false);
> if (stats_timeout > 0)
> {
> if (!get_timeout_active(BLAH_TIMEOUT))
> enable_timeout_after(BLAH_TIMEOUT, stats_timeout);
> }
> else
> {
> if (get_timeout_active(BLAH_TIMEOUT))
> disable_timeout(BLAH_TIMEOUT, false);
> }
> WaitLatch();
Im my example, I left out idle-time flushing, but I realized we don't
need the timeout mechanism here since we're already managing it. So
the following should work (assuming the timestamp updates with
GetCurrentTimestamp() in my last patch).
@@ -3889,13 +3900,23 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool
randAccess,
/* Update pg_stat_recovery_prefetch
before sleeping. */
XLogPrefetcherComputeStats(xlogprefetcher);
+ /*
+ * Report stats; if not time yet, set
next WaitLatch to
+ * wake up at the next reporing time.
+ */
+ wait_time = pgstat_report_stat(false);
+
+ /* if no pending stats, sleep forever */
+ if (wait_time == 0)
+ wait_time = -1L;
+
/*
* Wait for more WAL to arrive, when we
will be woken
* immediately by the WAL receiver.
*/
(void)
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_EXIT_ON_PM_DEATH,
- -1L,
+
wait_time,
WAIT_EVENT_RECOVERY_WAL_STREAM);
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/access/transam/xlogrecovery.c
b/src/backend/access/transam/xlogrecovery.c
index 188f6d6f85..0dd465c5e3 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -3248,6 +3248,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr
targetPagePtr, int reqLen,
close(readFile);
readFile = -1;
readSource = XLOG_FROM_ANY;
+ pgstat_report_stat(false);
}
XLByteToSeg(targetPagePtr, readSegNo, wal_segment_size);
@@ -3607,6 +3608,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool
randAccess,
wal_retrieve_retry_interval))
{
long wait_time;
+ long stats_timeout;
wait_time =
wal_retrieve_retry_interval -
TimestampDifferenceMilliseconds(last_fail_time, now);
@@ -3617,6 +3619,14 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool
randAccess,
/* Do background tasks that
might benefit us later. */
KnownAssignedTransactionIdsIdleMaintenance();
+ /*
+ * Report stats; if not time
yet, set next WaitLatch to
+ * wake up at the next reporing
time.
+ */
+ stats_timeout =
pgstat_report_stat(false);
+ if (stats_timeout > 0 &&
stats_timeout < wait_time)
+ wait_time =
stats_timeout;
+
(void)
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT |
WL_EXIT_ON_PM_DEATH,
@@ -3698,6 +3708,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool
randAccess,
case XLOG_FROM_STREAM:
{
bool havedata;
+ long wait_time;
/*
* We should be able to move to
XLOG_FROM_STREAM only in
@@ -3889,13 +3900,23 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool
randAccess,
/* Update pg_stat_recovery_prefetch
before sleeping. */
XLogPrefetcherComputeStats(xlogprefetcher);
+ /*
+ * Report stats; if not time yet, set
next WaitLatch to
+ * wake up at the next reporing time.
+ */
+ wait_time = pgstat_report_stat(false);
+
+ /* if no pending stats, sleep forever */
+ if (wait_time == 0)
+ wait_time = -1L;
+
/*
* Wait for more WAL to arrive, when we
will be woken
* immediately by the WAL receiver.
*/
(void)
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_EXIT_ON_PM_DEATH,
- -1L,
+
wait_time,
WAIT_EVENT_RECOVERY_WAL_STREAM);
ResetLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
break;
diff --git a/src/backend/storage/buffer/bufmgr.c
b/src/backend/storage/buffer/bufmgr.c
index 1fa689052e..520936d0dd 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1046,9 +1046,6 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence,
ForkNumber forkNum,
bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
if (found)
pgBufferUsage.local_blks_hit++;
- else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
- mode == RBM_ZERO_ON_ERROR)
- pgBufferUsage.local_blks_read++;
}
else
{
@@ -1062,9 +1059,6 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence,
ForkNumber forkNum,
strategy, &found,
io_context);
if (found)
pgBufferUsage.shared_blks_hit++;
- else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
- mode == RBM_ZERO_ON_ERROR)
- pgBufferUsage.shared_blks_read++;
}
/* At this point we do NOT hold any locks. */
@@ -1126,6 +1120,10 @@ ReadBuffer_common(SMgrRelation smgr, char
relpersistence, ForkNumber forkNum,
pgstat_count_io_op_time(io_object, io_context,
IOOP_READ,
io_start, 1);
+ if (isLocalBuf)
+ pgBufferUsage.local_blks_read++;
+ else
+ pgBufferUsage.shared_blks_read++;
/* check for garbage data */
if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
diff --git a/src/backend/utils/activity/pgstat.c
b/src/backend/utils/activity/pgstat.c
index b125802b21..0864b56689 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -608,7 +608,10 @@ pgstat_report_stat(bool force)
*/
Assert(!pgStatLocal.shmem->is_shutdown);
- now = GetCurrentTransactionStopTimestamp();
+ if (MyBackendType != B_STARTUP)
+ now = GetCurrentTransactionStopTimestamp();
+ else
+ now = GetCurrentTimestamp();
if (!force)
{
diff --git a/src/backend/utils/activity/pgstat_database.c
b/src/backend/utils/activity/pgstat_database.c
index 7149f22f72..c93b92771a 100644
--- a/src/backend/utils/activity/pgstat_database.c
+++ b/src/backend/utils/activity/pgstat_database.c
@@ -17,6 +17,7 @@
#include "postgres.h"
+#include "executor/instrument.h"
#include "utils/pgstat_internal.h"
#include "utils/timestamp.h"
#include "storage/procsignal.h"
@@ -269,7 +270,10 @@ AtEOXact_PgStat_Database(bool isCommit, bool parallel)
void
pgstat_update_dbstats(TimestampTz ts)
{
+ static BufferUsage lastBufferUsage = {0};
PgStat_StatDBEntry *dbentry;
+ PgStat_Counter hit_diff;
+ PgStat_Counter read_diff;
dbentry = pgstat_prep_database_pending(MyDatabaseId);
@@ -282,6 +286,16 @@ pgstat_update_dbstats(TimestampTz ts)
dbentry->blk_read_time += pgStatBlockReadTime;
dbentry->blk_write_time += pgStatBlockWriteTime;
+ /* we need to preserve pgBufferUsage */
+ read_diff =
+ pgBufferUsage.shared_blks_read -
lastBufferUsage.shared_blks_read +
+ pgBufferUsage.local_blks_read - lastBufferUsage.local_blks_read;
+ hit_diff =
+ pgBufferUsage.shared_blks_hit - lastBufferUsage.shared_blks_hit
+
+ pgBufferUsage.local_blks_hit - lastBufferUsage.local_blks_hit;
+ dbentry->blocks_fetched += read_diff + hit_diff;
+ dbentry->blocks_hit += hit_diff;
+
if (pgstat_should_report_connstat())
{
long secs;
@@ -304,6 +318,8 @@ pgstat_update_dbstats(TimestampTz ts)
pgStatBlockWriteTime = 0;
pgStatActiveTime = 0;
pgStatTransactionIdleTime = 0;
+
+ lastBufferUsage = pgBufferUsage;
}
/*
diff --git a/src/backend/utils/activity/pgstat_relation.c
b/src/backend/utils/activity/pgstat_relation.c
index 9876e0c1e8..8945b8141a 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -844,8 +844,6 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool
nowait)
dbentry->tuples_inserted += lstats->counts.tuples_inserted;
dbentry->tuples_updated += lstats->counts.tuples_updated;
dbentry->tuples_deleted += lstats->counts.tuples_deleted;
- dbentry->blocks_fetched += lstats->counts.blocks_fetched;
- dbentry->blocks_hit += lstats->counts.blocks_hit;
return true;
}