说明:磐维有集中式 与分布式 两种相互独立的产品形态,二者的架构、组件、参数和运维命令均不可混用。以下按形态分别说明;共通的内核理论单独归入第一节。
一、共通的内核理论底座
1.1 进程与线程模型
- 服务端采用单进程多线程模型:一个数据库实例对应一个主进程,后台由多个线程承担 WAL 写入、检查点、日志回放、autovacuum、undo 回收等职责。
- 客户端与服务器为 C/S 分离架构,客户端通过 gsql、JDBC/ODBC 等连接实例。
- 开启线程池 (
enable_thread_pool)后,worker 数量固定,会话在内部就绪队列中排队。这是高并发下"连接建得上、SQL 不执行"的典型机制根源:当 worker 全部被长查询、锁等待或 I/O 阻塞占满时,新语句只能在队列中排队,表现为idle_worker=0、排队会话数持续增长。
高阶要点 :线程池把"连接数"和"并发执行数"解耦,运维上要把监控重心从连接数转到排队长度与 worker 利用率 ,而不是一味调大 max_connections。
1.2 存储引擎:Astore 与 Ustore 的治理分水岭
这是高阶运维最容易踩坑的地方,必须建立"按引擎选治理手段"的思维:
| 维度 | Astore(行存堆表) | Ustore(Inplace-Update 引擎) |
|---|---|---|
| 旧版本存放 | 表内页中的死元组 | undo 空间 |
| 空间回收手段 | VACUUM 回收页内死元组 |
undo 回收线程(undorecycler)回收 undo |
| 膨胀监控指标 | n_dead_tup、表物理大小 |
n_dead_tup 无效,应看 undo 空间用量与回收进度 |
| 典型误操作 | --- | 对 Ustore 表反复 VACUUM,完全无效 |
| 闪回支持 | 回收站(recyclebin)支持 | 新版闪回能力主要面向 Ustore;回收站对 Ustore 支持存在版本差异,须按实际版本核对 |
建表时通过 WITH (STORAGE_TYPE=USTORE) / WITH (STORAGE_TYPE=ASTORE) 指定,查询 pg_stat_user_tables 等视图的 Engine 列可确认实际引擎类型。
1.3 MVCC、快照与"为什么 VACUUM 推不动"
- 全局 xmin(最老活跃快照)决定旧版本能否回收。
- 长事务、未提交事务、复制槽滞留、备机反馈的 xmin 都会钉住全局 xmin,导致死元组无法回收、clog/csnlog 无法截断、undo 持续膨胀。
- 判断口径:
idle in transaction不等于一定阻塞回收,关键要看该会话是否持有旧快照(backend_xmin 年龄) ;backend_xid(写过数据的 XID)与backend_xmin(持有的最老快照)是两回事,后者才是回收边界。
1.4 WAL、检查点与复制
- WAL 段写满会触发
CHECKPOINT_CAUSE_XLOG检查点;检查点无法推进 → WAL 无法回收 →pg_xlog目录膨胀 → 磁盘打满,是一条经典传导链。 - 备机追不上的典型报错:
requested WAL segment %s has already been removed(错误码 58P01)。根因是主库按检查点/复制槽保留策略回收了备机尚未接收的段,落后超过 WAL 保留窗口就无法追平,只能重建备机。 - 保留窗口由
wal_keep_segments(pg_xlog 下保留的日志段最小数目)与复制槽共同决定;生产上应优先用复制槽 而非单纯调大wal_keep_segments,否则主库磁盘不可控。
1.5 内存体系
- 实例级 :
max_process_memory限制单节点可用最大物理内存;shared_buffers为共享内存大小(单位 8kB,需重启)。 - 逻辑内存管理 :开启
enable_memory_limit后启用逻辑内存管理模块。此时max_process_memory、shared_buffers、cstore_buffers、max_connections、max_pred_locks_per_transaction等参数必须满足内部约束,否则实例直接启动失败并报内存值超限------这是"改完参数起不来"的高频原因。 - 会话级 :
work_mem控制排序与哈希表落盘前的内存上限;高并发下work_mem × 并发数才是真实峰值,不能只看单会话。 - 内存四级防线 (高并发大查询混合负载防 OOM):
work_mem预算 → auto spread 自动摊薄 → 落盘溢写 → 系统级提前降级。
1.6 高可用组件全景
磐维的高可用由五类能力共同构成:
- 流复制扩展:同步复制、复制槽、逻辑复制;
- DCF:分布式一致性协议,替代传统流复制做日志复制与选主;
- 共享存储:DSS / 企业级共享存储方案;
- CM(Cluster Manager):集群管理,含 cm_server(实例管理与仲裁)、cm_agent(部署在各主机,启停与监控实例进程)、cm_ctl(命令行客户端)、cm_monitor(守护 cm_agent);
- Roach:备份恢复体系。
关键认知 :常规主备部署 ≠ 高可用。只有引入 CM 自动 Failover ,才具备故障自动切换能力。DCF 模式下不走流复制,pg_stat_replication 中查不到复制信息,不能按流复制的视图预期去判断 DCF 集群的复制状态。
二、磐维集中式高阶运维
2.1 架构与组件定位
- 典型拓扑:一主多备(如 1 主 2 从),支撑多点可读、数据不丢失、异地灾备。
- 集群由 CM 统一管理、维护和监控;
Datanode State段中P Primary Normal/S Standby Normal与 CMServer 的 Primary/Standby 状态,是判断主备健康的第一手依据。 - 安装包按 CPU 架构与型号 适配(x86 含海光 C86、鲲鹏 920、飞腾等),不区分操作系统;部署前应先用
lscpu与/etc/os-release确认架构与系统版本,再选择对应安装程序。
2.2 参数体系(按生效方式分类管理)
参数上下文决定变更方式,这是高阶运维的基本功:
| 参数 | 上下文 | 是否需重启 | 关键说明 |
|---|---|---|---|
max_process_memory |
POSTMASTER | 是 | 单节点最大物理内存,单位 kB |
shared_buffers |
POSTMASTER | 是 | 共享内存,单位 8kB,16 ~ 1073741823 |
max_connections |
POSTMASTER | 是 | 上限受 job_queue_processes、autovacuum_max_workers、max_inner_tool_connections 等动态扣减 |
enable_thread_pool |
POSTMASTER | 是 | 线程池开关 |
work_mem |
USERSET | 否 | 64 ~ 2147483647 kB,会话级可调 |
checkpoint_timeout |
SIGHUP | 否 | 30 ~ 3600 秒 |
wal_keep_segments |
SIGHUP | 否 | 2 ~ INT_MAX,保留日志段数 |
autovacuum |
SIGHUP | 否 | 依赖 track_counts=on |
enable_memory_limit |
--- | 视版本 | 逻辑内存管理总开关,开启后需整套参数自洽 |
调优实践 :先确认参数上下文再决定用 gs_guc reload(SIGHUP)还是 gs_guc set + 重启(POSTMASTER);POSTMASTER 类参数变更应纳入变更窗口,并提前用参数自洽校验避免实例起不来。
2.3 常用运维命令(参数以实际版本 help 为准)
bash
# 集群级:状态、启停、切换(OM 方式)
gs_om -t status --detail
gs_om -t start
gs_om -t stop
gs_om -t restart
gs_om -t switchover --time-out=300
# 单实例级:启停、状态、升主、重建
gs_ctl status -D $PGDATA
gs_ctl start -D $PGDATA
gs_ctl stop -D $PGDATA -m fast
gs_ctl restart -D $PGDATA
gs_ctl promote -D $PGDATA
gs_ctl build -D $PGDATA -b full
# CM 方式(集群管理)
cm_ctl query -Cv
cm_ctl switchover -n <NODEID> -D $PGDATA
cm_ctl setrunmode -n <NODEID> -D $PGDATA --xmode=minority --votenum=<NUM>
# 参数
gs_guc reload -N all -I all -c "checkpoint_timeout=900"
gs_guc set -N all -I all -c "max_connections=3000"
# 客户端
gsql -d postgres -p 15400 -r
切换铁律 :同一个数据库的切换操作不能重叠执行 ,上一次未完成时禁止再次发起,否则极易在切换窗口叠加故障。DCF 模式下降级/仲裁使用 cm_ctl setrunmode,minority 模式必须显式给出投票数。
2.4 备份恢复体系
三类能力:逻辑备份恢复、物理备份恢复、闪回恢复。
Roach(推荐用于集群级物理备份)
- 进程模型:master 进程只存在于备份主节点,agent 进程分布于其余参与节点;master 与 agent 建立长连接,驱动整个备份流程。master 采用 IP 白名单认证,只允许实例内 IP 连接。
- 全量命令模板:
bash
gs_roach backup -d /backup/roach/full_20260101 --cluster --backup-type full --compress --parallel 8
- 增量命令示例(必须挂在上一次备份链上,依赖基线 LSN 取变更块):
bash
gs_roach backup -d /backup/roach/incr_20260102 --cluster --backup-type incremental --base /backup/roach/full_20260101 --parallel 8
- 前置条件 :全量/增量备份必须开启
enable_cbm_tracking=on(变更块追踪),关闭则备份失败。增量依赖pg_cbm_get_changed_block获取上次 LSN 与当前 LSN 之间的变化块,只拷贝变更块;若启动时检测到 CBM 追踪未完成,会重建 CBM 起点。 - 注意 :
gs_roach命令名区分大小写,命令取值不区分大小写;不支持的参数会被静默忽略 (例如--agent-port会被忽略但命令仍成功),因此不能用"命令成功"推断参数全部生效。
逻辑备份 :gs_dump / gs_dumpall / gs_restore,适合跨版本、跨平台、单表/单 schema 迁移。
闪回
- 闪回 DROP / TRUNCATE 基于回收站 (
enable_recyclebin,默认 off,可在线开关),通过还原回收站中记录的物理文件实现。 - Oracle 兼容的闪回与闪回查询可找回 INSERT/UPDATE/DELETE 之前的数据,并支持按指定时间闪回。
- 基于
pg_flashback函数的闪回表不支持连续闪回 ;V$DATABASE的flashback_on可作可用性前置检查。 - 回收站对存储引擎的支持范围随版本变化,须按实际版本核对。
恢复铁律 :物理备份恢复必须同版本 。将低版本物理备份恢复到高版本环境,会出现系统函数缺失(如 pg_get_expr_nocoll_b)并导致 gs_dumpall 失败。
2.5 性能诊断体系
(1)WDR 报告 ------ 集中式的"AWR"
- 基于两个不同时间点的性能快照生成区间性能报表,用于内核级性能诊断。
- 生成入口为
generate_wdr_report(...)函数(指定两个快照 ID 与报告类型)。 - 报告核心内容:Top 10 等待事件(等待次数、总等待时间、平均等待时间、事件类型),等待事件可归为等待状态、轻量级锁等待、IO 等待、事务锁等待四类。
- 高阶用法:定时主动分析 run 日志与 WDR 报告,按 CPU 占用率、内存占用率、长 SQL 比例等阈值触发,自动产出 html/pdf。
- 常见坑:初始用户远程连接被安全策略拒绝(
FATAL: Forbid remote connection with initial user.)会导致 WDR 快照失败 ,需修正pg_hba.conf。
(2)实时观测 SQL
sql
-- 会话与等待事件
SELECT pid, datname, usename, state, wait_event_type, wait_event,
query_start, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY duration DESC;
-- 锁阻塞关系
SELECT a.pid AS blocked_pid, a.usename AS blocked_user, a.query AS blocked_query,
b.pid AS blocking_pid, b.usename AS blocking_user, b.query AS blocking_query
FROM pg_stat_activity a
JOIN pg_locks l1 ON l1.pid = a.pid AND NOT l1.granted
JOIN pg_locks l2 ON l2.locktype = l1.locktype
AND l2.database IS NOT DISTINCT FROM l1.database
AND l2.relation IS NOT DISTINCT FROM l1.relation
AND l2.granted
JOIN pg_stat_activity b ON b.pid = l2.pid
WHERE a.pid <> b.pid;
-- 复制状态
SELECT client_addr, state, sync_state, sent_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;
-- 复制槽滞后
SELECT slot_name, active, restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots;
-- 数据库级锁冲突与死锁
SELECT datname, confl_tablespace, confl_lock, confl_snapshot, confl_bufferpin, confl_deadlock
FROM pg_stat_database_conflicts;
-- 表级死元组(Astore 适用)
SELECT relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
(3)慢 SQL 与执行计划
STATEMENT_HISTORY记录执行语句信息,需 sysadmin 权限,且只能在系统库查询 ,用户库查不到结果。慢 SQL 的lock_wait_time、is_slow_sql是定位"锁等待型慢 SQL"的直接证据(典型如并发下TRUNCATE等待近千秒)。EXPLAIN输出执行计划节点树,顶层为总开销;CREATE OUTLINE可将 SQL 与执行计划绑定,固定计划、稳定性能。- 计划翻转监控:以 planid 变化判断计划是否翻转,及时发现性能退化。
2.6 空间与膨胀治理
Astore 表
- 死元组靠 VACUUM 回收。
autovacuum尝试 truncate 扫描时拿不到排他锁 会报could not (re)acquire exclusive lock for truncate scan,导致分区几十倍膨胀、n_dead_tup极高。此时常规 VACUUM 无效,高阶手段是交换分区收缩空间。 - VM 位若被错误标为 all-visible,VACUUM 跳页会漏扫含死元组的页,造成"死元组比例虚高 + 索引膨胀";保守少设只增加扫描页数,无正确性问题。
Ustore 表:只看 undo 空间用量与回收进度,VACUUM 无效。
长事务治理:定期清理长时间运行的会话(含 idle in transaction 且持有旧快照者),让 VACUUM 最老位置推进,是缓解 update/delete 频繁表膨胀的根本手段。快照泄漏会同时导致表膨胀与 undo 无法回收。
2.7 典型高阶故障模式
| 现象 | 机制根因 | 处置方向 |
|---|---|---|
| 主备切换出现双主 | 网络故障/磁盘满导致主备连接断开,两侧均为 Primary | 严格按"关闭备机 → 以 standby 启动 → refreshconf → 状态确认"步骤修复,否则丢数据 |
| 主动切换后主键冲突/数据不一致 | 切换流程未阻断写入、未保证 RPO=0;备机升主后从 need_repair 恢复 | 单中心一主一备场景优先手工切换规避;切换前确认复制追平 |
| 备机请求 WAL 段已被回收(58P01) | 主库回收了备机未接收的段,落后超保留窗口 | 用 gs_basebackup 或全量备份 + gs_ctl build 重建备机 |
| 提交慢/TPS 下降 | commit 等待 WAL writer 刷盘,信号量等待在 xlog 路径 | 检查 wal writer 状态、攒批参数 wal_flush_delay / wal_flush_timeout 与 flush 推进 |
| 连接可建、SQL 不执行 | 线程池 worker 饱和,语句在就绪队列排队 | 查排队长度与 idle_worker,治理长查询与锁等待,而非盲目加连接 |
| 实例启动失败并报内存超限 | enable_memory_limit=on 后内存类参数不自洽 |
按提示回调 max_process_memory/shared_buffers 等参数后重启 |
| WDR 快照失败 | 初始用户远程连接被拒 | 修正 pg_hba.conf |
2.8 进阶能力
- MOT 内存表 :使用与磁盘表相同的 SELECT/DML/DDL 语法,差异集中在建删表需
FOREIGN关键字(如drop FOREIGN table test;)。持久性由 WAL 重做日志 + 检查点共同保证;配置在mot.conf。限制:开启增量检查点时不允许创建 MOT;MOT 采用 NUMA-aware 内存管理,需关闭操作系统 NUMA 平衡以发挥优势;索引存在使用边界。 - AI 能力:智能参数调优(结合深度强化学习与全局搜索自动寻优)、索引推荐、慢 SQL 根因分析、SQL 改写建议,可作为人工调优的补充而非替代。
- 审计:备份恢复等操作具备可审计性,生产环境应开启并纳入合规检查。
三、磐维分布式高阶运维
3.1 架构角色
| 角色 | 职责 | 高阶关注点 |
|---|---|---|
| GTM | 全局事务管理器,负责全局事务协调与全局快照分配 | 主备高可用;快照过旧会直接导致集群不可用 |
| CN | 协调节点,接收 SQL、生成分布式计划、下发 DN、汇总结果 | 连接池容量、计划形态(Stream vs Remote Query) |
| DN | 数据节点,实际存储与执行 | 一主多备,主备状态与数据分布均衡 |
| HA Server / DCS | 高可用管理与分布式配置/选主 | monitor all 中 state/leader 状态 |
典型生产拓扑示例:1 GTM + 30 CN + 20 DN(DN 一主两备),共 33 个节点。部署描述文件(如 panwei.yml)中会显式定义 HA 服务节点、DCS 端口、GTM、CN 与 DN 分组。
3.2 GTM 运维要点
- GTM 故障的差异化影响 :GTM 连接中断时,DML(INSERT/UPDATE/DELETE/SELECT)可能仍可执行(本地事务不需要全局快照),但 DDL(CREATE/ALTER/DROP)需要向 GTM 获取全局快照,必然失败 ,典型报错
gtm connect failed、cannot get global snapshot。因此"业务能查能改但不能建表"是 GTM 异常的强信号,应优先查 GTM 进程与网络。 - 快照过旧导致集群不可用 :报
snapshot is invalid, snapshot too old,提示 global csn 当前值低于cutoff_csn_min。处置为切换 GTM 主备、手工提升 csn 号并重启 GTM 节点(量级约 10 分钟)。 gtm_thread_attr线程分组数限制 :第三个值为线程分组数,默认最大 64。当部署节点数超过该值(如 96 节点)时,安装最后一步 CN 初始化会失败,报Rpc channel create failed、thread pool Current group num 96 out of range [0,64],集群所有 CN 处于 unstable。处置为调大该值(如 128)后重新打包安装。- GTM 主备 :
ha_ctl monitor gtm输出的 role 列可监控主备角色(primary/standby);停止集群后 state 为 stopped 但角色字段仍保留,不能仅凭 role 判断存活。
3.3 集群管理命令
bash
# 集群整体状态
ha_ctl monitor all
# GTM 角色监控
ha_ctl monitor gtm
# 集群启停(按部署形态选用对应入口)
ha_ctl stop all
ha_ctl start all
# 单实例操作
gs_ctl status -D $PGDATA
gs_ctl build -D $PGDATA -b full
判断集群健康时,monitor all 应同时看:ha_server 的 state=running 与 leader=True、DCS 是否在线、GTM 主备角色、CN 是否 stable、DN 的 Primary/Standby 与 Normal 状态。
3.4 在线扩容与数据重平衡
- 支持在线扩容 :动态增加计算/存储节点,数据自动平衡,平衡过程对业务透明;支持启动、暂停、调整平衡粒度------这是分布式运维的关键控制手段,大表重分布期间可暂停以保护业务。
- 前置条件 :已有节点与新增节点之间必须建立 root 用户互信 与数据库管理用户互信,否则扩容命令无法执行。
- 扩容前应评估:新节点 CPU 架构/OS 与存量一致、网络带宽是否满足重分布流量、目标表是否有大字段导致重分布耗时过长。
3.5 分布式执行计划
- 计划是节点树,每个步骤为一个运算符,描述从扫描、连接、排序到输出的过程。
- Stream 执行计划 :分布式并行查询的数据流由 Stream 池管理,连接通过 StreamNodeGroup 管理。SQL 采用 Stream 计划时会注册到内部流信息表,退出时释放全局锁;若锁未释放,所有后续依赖 Stream 计划的 SQL 都会阻塞------这是分布式环境"越跑越慢直到全部卡住"的隐蔽根因。
- Remote Query 下推 :
query_dop=1时,SQL 被完整下推到 DN 执行,不走 Stream 计划。这既是性能手段(减少跨节点数据流动),也会改变语义行为(见下条)。 - 分布式事务中
sysdate不更新 :事务块内多条使用sysdate的 SQL,若计划为 Stream,CN 不会对同一 DN 重复发送时间戳消息,导致后续语句时间值不变、基于时间的条件失效。规避手段即query_dop=1走 Remote Query,使每次执行发送新时间戳。 - 计划绑定 :开启
enable_sqlbind后,执行计划与加no_expand的效果一致,可用于固定分布式计划形态。
3.6 备份恢复
- 支持逻辑备份恢复、物理备份恢复、闪回恢复三类,并提供备份/恢复过程的数据可靠性保障机制。
- 物理备份恢复必须同版本(跨版本恢复会导致系统函数缺失等连锁问题)。
- 分布式环境备份需覆盖 GTM、CN、DN 全部角色,且必须做定期恢复演练验证备份有效性------只备不验是分布式运维最大的隐性风险。
3.7 典型分布式故障
| 现象 | 根因 | 处置 |
|---|---|---|
业务报 no free slot, used/max: 1007/1000,DN 连接数飙升 8000+ |
CN 连接池 max_pool_size 占满;persistent_datanode_connections=on 使内部连接不释放;负载未均衡致单点压力 |
调整连接池与持久连接策略,治理负载倾斜 |
查询视图报 negative bitmapset member not allowed |
视图定义含 SELECT DISTINCT 聚合,declare cursor with hold 场景触发 |
在视图定义外层再嵌套一层子查询 |
| CPU 使用率飙升 | 高频全表扫描 SQL 与含 distinct/union 的 SQL 高并发执行(如 7 小时 488 万次) | SQL 调优 + 版本升级 + 限流 |
TRUNCATE 成为慢 SQL |
并发插入持有锁,lock_wait_time 达数百秒 |
查 STATEMENT_HISTORY 定位持锁会话,错峰执行 |
| 大表 DDL 耗时长、业务中断窗口大 | int 改 bigint 触发全表重写,与长持独占锁叠加 |
按表规模评估,改用影子表/在线变更方案 |
四、高阶运维方法论(观测---定位---处置闭环)
- 先定形态:集中式看 CM/主备/线程池;分布式看 GTM/CN/DN/DCS。两者的参数、命令、故障模型不可互套。
- 先看全局再下钻 :集群状态(
gs_om -t status --detail/ha_ctl monitor all)→ 实例状态 → 会话与等待 → 具体 SQL/锁。 - 以等待事件为主线 :WDR 报告给出区间画像,
pg_stat_activity给出实时落点;等待类型决定优化方向(锁等待→业务/事务设计;IO 等待→存储与预取;轻量级锁→并发热点页)。 - 按引擎选治理手段:Astore 走 VACUUM/分区交换;Ustore 走 undo 回收。选错方向等于白做。
- 变更前做参数自洽校验 :尤其是 POSTMASTER 类内存参数与
enable_memory_limit组合,避免"改完起不来"。 - 高可用必须演练 :切换、双主修复、备机重建(
gs_ctl build)、备份恢复四条链路都要有可执行的 SOP 和回退方案。 - 容量与保留窗口对齐 :
wal_keep_segments、复制槽、归档策略三者要和备机最大可容忍落后时长对齐,否则 58P01 类故障不可避免。
五、常见误区速查
- ❌ 把"常规主备"当"高可用"------没有 CM 自动 Failover 就不是高可用。
- ❌ 对 Ustore 表反复 VACUUM 治理膨胀------无效,应看 undo。
- ❌ 用
pg_stat_replication判断 DCF 集群复制状态------DCF 不走流复制,查不到。 - ❌ 看到
idle in transaction就断定阻塞 VACUUM------要看是否持有旧快照(backend_xmin)。 - ❌ 物理备份跨版本恢复------必须同版本。
- ❌ 以为
gs_roach命令成功就代表参数全部生效------不支持的参数会被静默忽略。 - ❌ 分布式扩容前不检查互信与网络------扩容命令直接失败或重分布极慢。
- ❌ 主备切换重叠执行------同一数据库切换未完成时禁止再次发起。
上述命令与参数取值请以实际部署版本的命令帮助和参数手册为准;不同版本在闪回、回收站、连接池、DCF 等特性上存在差异,变更前应先在测试环境验证。