PostgreSQL wal receiver 统计信息 patch

之前写过一篇文档,关于如何编写一个C函数,在PostgreSQL hot standby中获取wal receiver的统计信息,以及上游节点的连接信息(conninfo)。
http://blog.163.com/digoal@126/blog/static/1638770402015744524871/

PostgreSQL 9.6 把这个功能合到内核了。

patch地址如下:

http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=b1a9bad9e744857291c7d5516080527da8219854

https://commitfest.postgresql.org/8/447/

主要新增代码:

为了保证取出状态的一致性,需要对&walrcv->mutex加锁。

+

+/*

+ * Return a string constant representing the state. This is used

+ * in system functions and views, and should *not* be translated.

+ */

+static const char *

+WalRcvGetStateString(WalRcvState state)

+{

+   switch (state)

+   {

+       case WALRCV_STOPPED:

+           return "stopped";

+       case WALRCV_STARTING:

+           return "starting";

+       case WALRCV_STREAMING:

+           return "streaming";

+       case WALRCV_WAITING:

+           return "waiting";

+       case WALRCV_RESTARTING:

+           return "restarting";

+       case WALRCV_STOPPING:

+           return "stopping";

+   }

+   return "UNKNOWN";

+}

+

+/*

+ * Returns activity of WAL receiver, including pid, state and xlog locations

+ * received from the WAL sender of another server.

+ */

+Datum

+pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)

+{

+#define PG_STAT_GET_WAL_RECEIVER_COLS  11

+   TupleDesc   tupdesc;

+   Datum       values[PG_STAT_GET_WAL_RECEIVER_COLS];

+   bool        nulls[PG_STAT_GET_WAL_RECEIVER_COLS];

+   WalRcvData *walrcv = WalRcv;

+   WalRcvState state;

+   XLogRecPtr  receive_start_lsn;

+   TimeLineID  receive_start_tli;

+   XLogRecPtr  received_lsn;

+   TimeLineID  received_tli;

+   TimestampTz last_send_time;

+   TimestampTz last_receipt_time;

+   XLogRecPtr  latest_end_lsn;

+   TimestampTz latest_end_time;

+   char       *slotname;

+

+   /* No WAL receiver, just return a tuple with NULL values */

+   if (walrcv->pid == 0)

+       PG_RETURN_NULL();

+

+   /* Initialise values and NULL flags arrays */

+   MemSet(values, 0, sizeof(values));

+   MemSet(nulls, 0, sizeof(nulls));

+

+   /* Initialise attributes information in the tuple descriptor */

+   tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_WAL_RECEIVER_COLS, false);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pid",

+                      INT4OID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 2, "status",

+                      TEXTOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 3, "receive_start_lsn",

+                      LSNOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 4, "receive_start_tli",

+                      INT4OID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 5, "received_lsn",

+                      LSNOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 6, "received_tli",

+                      INT4OID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 7, "last_msg_send_time",

+                      TIMESTAMPTZOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 8, "last_msg_receipt_time",

+                      TIMESTAMPTZOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 9, "latest_end_lsn",

+                      LSNOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 10, "latest_end_time",

+                      TIMESTAMPTZOID, -1, 0);

+   TupleDescInitEntry(tupdesc, (AttrNumber) 11, "slot_name",

+                      TEXTOID, -1, 0);

+

+   BlessTupleDesc(tupdesc);

+

+   /* Take a lock to ensure value consistency */

+   SpinLockAcquire(&walrcv->mutex);

+   state = walrcv->walRcvState;

+   receive_start_lsn = walrcv->receiveStart;

+   receive_start_tli = walrcv->receiveStartTLI;

+   received_lsn = walrcv->receivedUpto;

+   received_tli = walrcv->receivedTLI;

+   last_send_time = walrcv->lastMsgSendTime;

+   last_receipt_time = walrcv->lastMsgReceiptTime;

+   latest_end_lsn = walrcv->latestWalEnd;

+   latest_end_time = walrcv->latestWalEndTime;

+   slotname = pstrdup(walrcv->slotname);

+   SpinLockRelease(&walrcv->mutex);

+

+   /* Fetch values */

+   values[0] = Int32GetDatum(walrcv->pid);

+

+   if (!superuser())

+   {

+       /*

+        * Only superusers can see details. Other users only get the pid

+        * value to know whether it is a WAL receiver, but no details.

+        */

+       MemSet(&nulls[1], true, PG_STAT_GET_WAL_RECEIVER_COLS - 1);

+   }

+   else

+   {

+       values[1] = CStringGetTextDatum(WalRcvGetStateString(state));

+

+       if (XLogRecPtrIsInvalid(receive_start_lsn))

+           nulls[2] = true;

+       else

+           values[2] = LSNGetDatum(receive_start_lsn);

+       values[3] = Int32GetDatum(receive_start_tli);

+       if (XLogRecPtrIsInvalid(received_lsn))

+           nulls[4] = true;

+       else

+           values[4] = LSNGetDatum(received_lsn);

+       values[5] = Int32GetDatum(received_tli);

+       if (last_send_time == 0)

+           nulls[6] = true;

+       else

+           values[6] = TimestampTzGetDatum(last_send_time);

+       if (last_receipt_time == 0)

+           nulls[7] = true;

+       else

+           values[7] = TimestampTzGetDatum(last_receipt_time);

+       if (XLogRecPtrIsInvalid(latest_end_lsn))

+           nulls[8] = true;

+       else

+           values[8] = LSNGetDatum(latest_end_lsn);

+       if (latest_end_time == 0)

+           nulls[9] = true;

+       else

+           values[9] = TimestampTzGetDatum(latest_end_time);

+       if (*slotname == '\0')

+           nulls[10] = true;

+       else

+           values[10] = CStringGetTextDatum(slotname);

+   }

+

+   /* Returns the record as Datum */

+   PG_RETURN_DATUM(HeapTupleGetDatum(

+                         heap_form_tuple(tupdesc, values, nulls)));

+}

用法参考:

http://www.postgresql.org/docs/devel/static/monitoring-stats.html#PG-STAT-WAL-RECEIVER-VIEW

可以获取到的信息,

wal receiver的PID。

当前的状态(停止,正在启动,正在接收,正在等待,重启中,停止中,未知)。

WAL RECEIVER进程启动时的WAL需接收位置receive_start_lsn,时间线receive_start_tli。

当前wal receiver已接收并flush到磁盘的WAL 位置received_lsn,时间线received_tli。

最后一次接收到 wal sender 发送过来的消息的 wal sender  端携带的发消息时的时间。last_msg_send_time

最后一次接收到 wal sender 发送过来的消息的 wal receiver 端的当前时间。last_msg_receipt_time

(last_msg_receipt_time - last_msg_send_time)就是网络延迟。(当然前提是两个服务器的时钟一致。)

最后一次feed back给wal sender的 wal 已接收位置 latest_end_lsn

最后一次feed back给wal sender的 wal 已接收时间戳 latest_end_time

上游节点的slot name。

Table 27-5. pg_stat_wal_receiver View

Column Type Description
pid integer Process ID of the WAL receiver process
status text Activity status of the WAL receiver process
receive_start_lsn pg_lsn First transaction log position used when WAL receiver is started
receive_start_tli integer First timeline number used when WAL receiver is started
received_lsn pg_lsn Last transaction log position already received and flushed to disk, the initial value of this field being the first log position used when WAL receiver is started
received_tli integer Timeline number of last transaction log position received and flushed to disk, the initial value of this field being the timeline number of the first log position used when WAL receiver is started
last_msg_send_time timestamp with time zone Send time of last message received from origin WAL sender
last_msg_receipt_time timestamp with time zone Receipt time of last message received from origin WAL sender
latest_end_lsn pg_lsn Last transaction log position reported to origin WAL sender
latest_end_time timestamp with time zone Time of last transaction log position reported to origin WAL sender
slot_name text Replication slot name used by this WAL receiver

The pg_stat_wal_receiver view will contain only one row, showing statistics about the WAL receiver from that receiver's connected server.

时间: 2024-10-24 14:40:29

PostgreSQL wal receiver 统计信息 patch的相关文章

PostgreSQL · 特性分析 · 统计信息计算方法

一条SQL在PG中的执行过程是: ----> SQL输入 ----> 解析SQL,获取解析后的语法树 ----> 分析.重写语法树,获取查询树 ----> 根据重写.分析后的查询树计算各路径代价,从而选择一条成本最优的执行树 ----> 根据执行树进行执行 ----> 获取结果并返回 PostgreSQL的SQL优化.执行方式为代价模型.而这里的各路径的代价计算,则是依赖于系统表中的统计信息.那么这些统计信息如何得来的?就是这里要讨论的问题. PostgreSQL是ca

PostgreSQL 统计信息混淆之处(scan,read,fetch,hit)源码解读

PostgreSQL 几个统计信息的解释难以理解,所以本文花一些时间从源码的角度来解释一下.让大家对这几个容易误解的统计值有更好的理解. 比较难理解的几个统计值为:pg_stat_all_indexes 的 idx_scan idx_tup_read idx_tup_fetch pg_statio_all_indexes 的 idx_blks_read idx_blks_hit pg_stat_all_tables 的 seq_scan seq_tup_read idx_scan idx_tup

PostgreSQL 统计信息pg_statistic格式及导入导出dump_stat - 兼容Oracle

标签 PostgreSQL , dump_stat , 统计信息 , 导出导入 背景 <PostgreSQL 规格评估 - 微观.宏观.精准 多视角估算数据库性能(选型.做预算不求人)> EXPLAIN是PG数据库用于输出SQL执行计划的语法, 1.生成的执行计划中包含COST一项. 如果校准了成本因子,COST可以和SQL实际执行时间对其.因子校对的方法如下,实际上每一种硬件,我们只需要校对一遍即可. <优化器成本因子校对(disk,ssd,memory IO开销精算) - Postg

PostgreSQL Analyze分区表:主表与子表的统计信息问题

  最近在PostgreSQL的Mail List中参与讨论了一个问题: ANALYZE'ing table hierarchies.   网友认为在Analyze分区表的时候,只能看到主表的analyze日期更新到最新,但是子表的日期没有变化,他认为analyze应该是在分析主表的时候会将与之相关的子表一起更新.     为此测试了一下,发现无论主表还是子表,需要单独的对其进行analyze才可以更新其最新的统计信息.   以下是实验部分:    music=> create table mu

postgresql 定时收集表和索引统计信息

--由于pg中表和索引的信息收集都是基于时间点的,对于以往的信息无法与现在的信息进行对比,故写下此工具进行统计信息收集 --创建数据信息的schema create schema db_stat; --创建收集信息的基础表 create table db_stat.snapshot_pg_stat_all_indexes (relid int,indexrelid int,schemaname varchar(200),relname varchar(550),indexrelname varc

PostgreSQL 长事务中DML产生的数据无法被及时纳入统计信息导致的问题

PostgreSQL最低的事务隔离级别是read committed,因此在事务中产生的数据变化,在外部是不可见的,包括auto analyze也是不可见的.例子: postgres=# show autovacuum; autovacuum ------------ on (1 row) postgres=# show autovacuum_naptime ; autovacuum_naptime -------------------- 1s (1 row) 会话A: postgres=#

Greenplum 自动统计信息收集 - 暨统计信息不准引入的broadcast motion一例

标签 PostgreSQL , Greenplum , 统计信息 , 自动统计信息 , broadcast motion , 执行计划 背景 数据库执行计划的好坏,与数据库的SQL优化器息息相关.Greenplum有两套优化器,legacy query optimizer 与 ORCA. 这两个优化器都是CBO优化器,都需要依赖统计信息,如果统计信息不准确,可能生成的执行计划就不准确. 例如我们有一个这样的QUERY,发现怎么跑都跑不出来. 观察执行计划,发现有一个节点用到了broadcast

PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum, count ...

标签 PostgreSQL , 流式统计 , insert on conflict , count , avg , min , max , sum 背景 流式统计count, avg, min, max, sum等是一个比较有意思的场景,可用于实时大屏,实时绘制统计图表. 比如菜鸟.淘宝.阿里游戏.以及其他业务系统的FEED日志,按各个维度实时统计输出结果.(实时FEED统计,实时各维度在线人数等) PostgreSQL insert on conflict语法以及rule, trigger的功

DDD实践问题之 - 关于论坛的帖子回复统计信息的更新的思考

之前,在用ENode开发forum案例时,遇到了关于如何实现论坛帖子的回复的统计信息如何更新的问题.后来找到了自己认为比较合理的解决方案,分享给大家.也希望能和大家交流,擦出更多的火花. 论坛核心领域问题分析 论坛领域的核心概念是:帖子.回复.大家都知道,一个帖子可以有零个或多个回复.对同一个帖子,不同的人可以并行发表回复.回复发表后,查看帖子详情时,可以根据回复的发表时间排序显示:此外,我们还关心某个帖子的最新发表的回复.最新回复的作者.最新回复时间,以及总回复数. 我们设计的系统,应该在实现