关于 YMatrix
部署数据库
使用数据库
管理集群
最佳实践
高级功能
高级查询
联邦查询
Grafana 监控
备份恢复
灾难恢复
图数据库
管理手册
性能调优
故障诊断
工具指南
系统配置参数
SQL 参考
本文档介绍如何用 hot standby 让备节点 standby 承接报表、BI 等只读查询,把连接、SQL 解析和查询调度的压力从主节点分流出去。适用于 YMatrix 6.8 及以上版本。
报表、BI、分析类业务通常是"连接多、单个查询不重",压力主要压在协调节点上:连接排队、SQL 解析和查询调度把主节点的 CPU 吃满,而数据节点还闲着。hot standby 就是把这个压力挪一部分到备节点上的开关。
适合开启的迹象:
remote_apply;不适合开启的情况:
YMatrix 集群里有两类节点,职责不同:
| 节点 | 角色 | 负责的事 |
|---|---|---|
| master | 主节点,主协调节点 | 接收连接、生成执行计划、调度查询 |
| standby | 备节点,备协调节点 | 与主节点保持同步;开启 hot standby 后也能接收只读连接 |
| primary segment | 主数据节点 | 存储数据、执行查询 |
| mirror | 备数据节点 | primary 的副本,primary 故障时接管 |
开启后,连接分布大致是这样:
只读应用 写入、维护
│ │
▼ ▼
standby 备节点 ←—— 复制 ——→ master 主节点
│ │
└─────────────┬───────────────┘
▼
primary segments 执行查询
│ │
mirror mirror
两条关键结论,决定了后面所有注意事项:
mx_hot_standby_use_primary_qe 决定。 该参数开启时,查询发往当前的 primary segments,因此某个 mirror 不可用也不会导致查询读不到数据,建议同时开启,见第 4 节。hot_standby 默认关闭,它只改变"恢复中的实例能否接受只读连接",不改变集群的主备切换机制。
按顺序确认四件事,可以避免重启后返工:
select content, role, hostname, port, status
from gp_segment_configuration
where content = -1;
输出两行:role = p 是主节点,role = m 是备节点。status = u 表示实例正常。记下备节点的 hostname 和 port,4.4 节要用。
此时直接连备节点会报 FATAL: the database system is in recovery mode——这是 hot standby 关闭时的正常响应,不代表实例有问题。
gpconfig -s hot_standby
gpconfig -s mx_hot_standby_use_primary_qe
如果已经是 on,说明之前开过,可以直接跳到 4.3 节确认。
安排维护窗口。 hot_standby 是 postmaster 级参数,设置分类为 restart,改完必须重启集群才能生效;重启会断开所有连接,并回滚未提交的事务。
准备应用侧。 只读应用要能改连接地址,并且在连接中断时能重试。这一步不做,重启完业务就连不上了。
在主节点上以安装用户执行,通常是 mxadmin:
gpconfig -c hot_standby -v on
gpconfig -c mx_hot_standby_use_primary_qe -v on
gpconfig 默认把参数写入所有实例的 postgresql.conf:主节点、备节点、数据节点和镜像,不需要逐个节点改。
两个参数的生效方式不同:
hot_standby 是 postmaster 参数,设置分类为 restart,必须重启;mx_hot_standby_use_primary_qe 是会话级参数,设置分类为 session,重启后新建的连接自动读到新值。注意!
设置完立刻执行gpconfig -s,两个参数仍会显示off:它读的是运行中的值,不是配置文件里的值。重启后才会变成on,不要误以为设置失败——配置文件里已经写入了hot_standby=on。
mxstop -a -r -M fast
各参数含义:-a 不提示确认,-r 停止后重新启动,-M fast 中断并回滚正在执行的事务。
注意!
不加-M fast时,mxstop默认是 smart 模式:只要还有活动连接就拒绝停止。这也是"重启卡住不动"最常见的原因。
旧文档里的mxstop -arf是 gpstop 时代沿用下来的写法,它在 6.8 的mxstop --help里查不到-f,建议按上面的显式写法执行。
重启期间集群不可用,建议在业务低峰操作。
集群起来后,先看参数:
gpconfig -s hot_standby
gpconfig -s mx_hot_standby_use_primary_qe
期望两边都是 on:
Values on all segments are consistent
GUC : hot_standby
Coordinator value: on
Segment value: on
再登录备节点确认状态:
psql -h <备节点主机名> -p <备节点端口> -d <数据库名>
-- 返回 t,说明备节点处于恢复状态,这是正常现象
select pg_is_in_recovery();
show hot_standby; -- 期望 on
show mx_hot_standby_use_primary_qe; -- 期望 on
最后在备节点上跑一条只读查询,例如 select count(*) from public.orders;,把表名换成你的业务表,确认能出结果;顺便试一条写入,应该失败并提示 cannot execute INSERT in a read-only transaction——报这个错是预期的,说明它确实只读。
hostname 和 port,值见第 3 节第 1 步。写入和维护应用保持连主节点不变。pg_hba.conf,按来源网段添加规则,然后执行:mxstop -u
-u 会重载主节点、备节点和所有数据节点的 pg_hba.conf,以及 postgresql.conf 中的运行时参数,不停止数据库。
SELECT 权限。这三条不是故障,是 hot standby 的固有行为,提前知道就不会误判:
一、读查询会和维护操作抢锁。 备节点上的查询走 primary 执行时,遵守常规的锁冲突规则。例如查询正在读某个分区,持有 AccessShareLock,此时主节点对该分区执行 TRUNCATE,需要 AccessExclusiveLock,就必须等查询结束。反过来说,维护操作也可能被只读查询拖住。所以 TRUNCATE、VACUUM FULL 这类需要排他锁的操作,尽量和报表高峰错开。
二、故障切换会中断查询。 hot_standby 不改变集群的主备切换机制。切换发生时,备节点上正在执行的查询会中断;备节点提升为主节点之后,原来指向它的只读连接也需要重新建立。这也是第 3 节要求应用具备重试能力的原因。
三、元数据的可见性受回放进度影响。 写 synchronous_commit = on 时,如果 synchronous_standby_names 里配了同步备库,提交要等 WAL 落到这些备库的持久存储,但不等待回放;该参数为空时(YMatrix 的默认配置),on 与 local 等价,提交只等本地刷盘,与备节点无关。不过在 mx_hot_standby_use_primary_qe = on 的推荐配置下,行数据直接从 primary segments 读取,所以新插入的行不受备节点回放进度影响。
受影响的是元数据:回放没跟上时,备节点的系统目录还是旧的,新建的表、新加的列在备节点上看不到——查询会报 relation "..." does not exist,等回放追上来后恢复可见。所以做完 DDL 想在备节点上马上使用,要等回放跟上。
| 参数 | 默认值 | 生效方式 | 作用与取舍 |
|---|---|---|---|
hot_standby |
off | 重启 | 是否允许恢复中的实例接受只读连接 |
mx_hot_standby_use_primary_qe |
off | 会话 | 备节点收到的分布式查询是否发往当前 primary segments。boolean 类型,可用 gpconfig -l 查 |
synchronous_commit |
on | 会话 | 配了同步备库时:on 等提交 WAL 落到备库持久存储,不等回放;remote_apply 等到回放完成。synchronous_standby_names 为空时,on、remote_write、remote_apply、local 都只等本地刷盘 |
max_standby_streaming_delay |
30s | 重载 | 回放为避让查询冲突可以延迟的时间预算,用完即取消冲突查询;-1 表示无限等待 |
hot_standby_feedback |
off | 重载 | 备库反馈查询需要保留的旧版本,减少因主库清理导致的查询取消,代价是主库表膨胀 |
wal_receiver_status_interval |
10s | 重载 | 反馈消息的发送周期上限,hot_standby_feedback 的反馈不会比这个更频繁 |
生效方式对应参数页的「设置分类」:重启是 restart,重载是 reload,会话是 session。各参数的取值范围请以 gpconfig -l 的输出为准。
调参建议:先保留默认值跑一段时间,再按实际情况动:
synchronous_commit = remote_apply,提交会等回放完成;代价是备节点上的查询若阻碍回放,主库提交也会跟着等。前提是 synchronous_standby_names 里列出了这个备节点,否则 remote_apply 与 on 一样只等本地刷盘,不会改变提交行为。max_standby_streaming_delay,或者打开 hot_standby_feedback。前者增加回放延迟,后者增加主库膨胀,两者都会把代价转移到别处。max_standby_streaming_delay 不是单条查询的超时时间,也不控制主节点上的普通锁等待,不要拿它当查询超时用。参数改回默认并重启即可回到开启前的状态:
gpconfig -c hot_standby -v off
gpconfig -c mx_hot_standby_use_primary_qe -v off
mxstop -a -r -M fast
关闭后备节点恢复为纯备用节点,不再接受只读连接;记得把只读应用的连接地址改回主节点。
Q:开了 hot standby,但应用连备节点连不上?
按顺序查:备节点的 status 是否为 u,查 gp_segment_configuration;备节点主机上的 pg_hba.conf 是否放通了来源网段、改完是否 mxstop -u;端口是否用的是备节点自己的;数据库用户是否存在且有权限。
Q:备节点上的查询比主节点上还慢?
先确认 mx_hot_standby_use_primary_qe 是否为 on。走 mirror 读取时,链路上的开销和可用性都更差;走 primary segments 才是推荐配置。另外备节点只承担协调工作,单条大查询不会因为挪到备节点而变快。
Q:备节点上执行查询报 primary segments can only process MPP protocol messages from primary QD?
说明当前会话的 mx_hot_standby_use_primary_qe 是关的:备节点的查询试图走 mirror,在没有 mirror 的集群上必然撞上这个错误。确认参数为 on 后重新连接再试。
Q:重启时命令没反应、一直等着?
大概率是没带 -M fast,smart 模式下有活动连接就会拒绝停止。确认业务可以断开后重新执行 mxstop -a -r -M fast。
Q:维护窗口里 TRUNCATE、VACUUM FULL 被卡住?
备节点上的只读查询在主节点上持有了表的共享锁,排他操作必须等它结束。先用 pg_stat_activity 和 pg_locks 定位持有 AccessShareLock 的会话,必要时用 pg_cancel_backend 结束它;长期做法是把维护操作挪到报表低峰,并在维护侧设置 lock_timeout,让操作失败而不是无限等待。
Q:发生切换后应用报错?
预期行为。备节点提升为主节点后旧连接全部失效,应用需要重连;并将只读应用的地址改到新的主节点,或新的备节点。
hot_standby、hot_standby_feedback 等参数的完整说明synchronous_commit 的同步级别说明