跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

使用手册

内容来自 kbdiag README,是生成时的快照。

命令页:status · sessions · session · locks · txn · waits · slots · space · freeze · vacuum · archive · params · repl · cluster · top-objects · table · top · progress · checkpoint · wal · seq

KingbaseES 命令行诊断工具。单个静态二进制,直连线协议:不调 ksql,不进交互界面。每条命令对运行中的实例做一次只读查询,输出结论、证据和下一步该跑的命令。支持单机和 repmgr 主备集群。

这是用 Go 重写的 kbdiag 2.0,首个发布版本是 v2.0.0-alpha.1。shell 版(v1.x)已冻结,需要时用 v1.0.0。

安装

编译 Linux 静态二进制(Go 版本见 go.mod),拷到数据库主机:

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$(git describe --tags --match 'v2*' --always)" -o kbdiag ./cmd/kbdiag
scp kbdiag kingbase@db-host:~/kbdiag

ARM 主机用 GOARCH=arm64。二进制没有运行时依赖。

快速开始

sudo -iu kingbase        # 以数据库 OS 用户运行
~/kbdiag status          # 这是个什么实例
~/kbdiag sessions        # 谁连着,谁 idle in transaction
~/kbdiag locks           # 谁在等锁,被谁挡住
echo $?                  # 0 OK,1 WARN,2 FAIL,3 UNKNOWN

命令

命令看什么参数
status版本、数据目录、端口、角色;主库列出每个备库,备库看上游在不在收 WAL;运行时长、连接数已用/可用、各库大小、数据目录所在磁盘(只在本机运行时有)。普通用户已经连不上报 FAIL,备库没在收 WAL 报 WARN
sessions连接是谁占的(按用户、库、应用、客户端计数),再列出不是 idle 的客户端会话,事务最长的在前;idle in transaction 过久报 WARN。JSON 总是全部会话--all、--limit N、--idle-in-txn-warn 秒
session <pid>一个会话:是谁、在干什么、完整 SQL,在等什么锁、被谁挡住,挡住了谁,持有哪些锁--lock-wait-warn 秒、--idle-in-txn-warn 秒
locks谁挡的人最多、它持有什么锁,再列出每个等锁的会话(等得最久的在前)和直接挡路者;等太久报 WARN--limit N、--lock-wait-warn 秒
txn最老的 xid 压着 vacuum、是谁压的,开着的事务,两阶段事务;过久报 WARN--limit N、--xact-warn 秒、--prepared-warn 秒
waits在干活的会话在等什么,按等待事件和状态汇总,人多的在前;idle 会话和后台进程只计数
slots复制槽,未激活的和保留 WAL 最多的排前面;未激活报 WARN
space空间账:数据目录、WAL、表空间所在的文件系统(只在本机运行时有),WAL 大小对照 max_wal_size 和 wal_keep_segments,各库和表空间大小。数据目录或 WAL 所在文件系统的可用空间不够一个 WAL 段时 FAIL,其余只展示
freeze各库离事务号回卷还有多远,当前库最老的表;超过 autovacuum_freeze_max_age 报 WARN,到了拒绝分配新事务号的停止线报 FAIL--limit N
vacuum死元组最多的表和各自的 autovacuum 触发线,正在跑的 vacuum;没人会清时报 WARN(autovacuum 或 track_counts 关了,或表级关了 autovacuum 又过了线)。只在主库上有表统计--limit N
archive归档是不是在正常工作:设置、最后一次成功和失败、等着归档的 WAL;最后一次尝试失败时报 WARN
params哪些参数不是默认值、在哪设的(文件和行号);改了但要重启才生效的每个报 WARN
repl从本节点看复制:主库看同步设置和每个备库落后多少;备库看上游、接收和回放。同步备库不够数、回放暂停、备库没在收 WAL 时报 WARN;延迟只展示,不判
clusterrepmgr 眼里的集群(节点、角色、上游、最近事件),和本节点对照;两个主库、inactive 节点、repmgr 记错的角色、没挂上来的备库报 WARN。没给 -d 时连 esrep 库
top-objects当前库最大的表(堆、索引、TOAST 分列)和最大的索引。只展示--limit N
table <name>一张表:大小、行数、vacuum 和 analyze、冻结年龄、访问、索引;用 freeze、vacuum 的规则判。名字按 SQL 规则(不带引号的折成小写);找不到是 UNKNOWN
topsys_stat_statements 的累计 Top SQL(自上次重置以来),带每条占全部执行时间的比例;没在收集时明说。只展示--limit N、--by time/mean/calls/io/temp
progress正在跑的 VACUUM、CREATE INDEX、CLUSTER / VACUUM FULL、CHECKPOINT 到哪了。只展示
checkpoint最近一次 checkpoint,定时和被请求的各多少,脏页是谁写的(checkpointer、bgwriter、后端),相关参数。只展示
walWAL 写到哪了、sys_wal 多大,以及是什么让它留着:max_wal_size、wal_keep_segments、每个槽、等着归档的文件。只展示
seq当前库的序列,按用掉的比例排;取不出下一个值时报 FAIL--limit N

默认阈值:idle in transaction 300 秒,等锁 10 秒,事务 300 秒,两阶段事务 900 秒,都报 WARN。--limit 只影响显示,判定始终覆盖全部行。

连接

参数默认值
--host/tmp(本地 socket /tmp/.s.KINGBASE.54321);写主机名或 IP 走 TCP
-p, --port54321
-d, --dbnametest
-U, --usersystem
--timeout每条查询 10s
--json输出 JSON

密码从 PGPASSWORD 或 ~/.pgpass 取。连接是只读事务并设了 lock_timeout,kbdiag 不改任何东西;建议的处理语句(如 ROLLBACK PREPARED)只打印,不执行。

输出

locks  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-26T19:41:41+08:00)

[WARN] lock.waiting  session 803890 has waited 14s for AccessShareLock on public.kbdiag_inj_lock, blocked by 803881
  verify: kbdiag session 803881  # what the blocking session is doing

blockers: 1
  pid     blocks  holds
  803881  1       public.kbdiag_inj_lock AccessExclusiveLock

waiting: 1
  pid     object                  wants            waited  blocked by
  803890  public.kbdiag_inj_lock  AccessShareLock  14s     803881
  • 第一行:命令、结论和上下文(版本、角色、用户@位置、采集时间)。
  • finding:编号、症状(英文,工具输出全部是英文)、下一步(verify 看什么或 fix 怎么处理)。
  • 数据:按阅读排版,大小和时长换成易读单位;- 表示空值,? 表示当前账号看不到。--json 给每个探针的原始表(字节、秒),字段名稳定。

退出码

退出码含义
0OK
1WARN
2FAIL
3UNKNOWN:有东西没采到或看不到,所以不说 OK
64参数错误
69连不上数据库

权限

以 system 走本地 socket 能看到全部信息。没有监控角色的账号看不到别人会话的状态、时间和 SQL;kbdiag 把这些字段列进 redacted,结论给 UNKNOWN 而不是 OK;看得到的部分已经是 WARN 或 FAIL 时照报 WARN 或 FAIL。授予 sys_monitor 后解除。备库上两阶段事务是 not_applicable(到主库跑 txn),不影响结论。

运行要求

  • KingbaseES V8R6(在 V008R006C009B0014 上测试)
  • Linux amd64 或 arm64
  • repmgr 可选

1 - sessions:列会话

连接是谁占的、哪些会话在干活;标出长时间 idle in transaction 的会话。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。名为 kbdiag_inj_* 的业务会话是故障注入脚本造出来的。PID、计数与时间只属于本次采样。

用法

kbdiag sessions [--all] [--limit N] [--idle-in-txn-warn 秒] [--json]
参数作用
--all列出全部会话,包括 idle 的会话和后台进程
--limit N最多显示 N 行,默认 50,0 表示全部
--idle-in-txn-warn 秒idle in transaction 超过多少秒报 WARN,默认 300
--json输出 JSON

连接参数 --host、-p、-d、-U、--timeout 是全局参数,默认 /tmp 本地 socket、端口 54321、库 test、用户 system;密码从 PGPASSWORD 或 ~/.pgpass 取。连接是只读事务,并设了 lock_timeout。

--all 和 --limit 只影响显示:汇总和判定始终覆盖全部会话,没显示出来的会话也会报 WARN。

默认输出

现场有几个注入的会话:一个 idle in transaction 的会话持有表锁、一个读这张表的会话在等它,另一个 idle in transaction 的会话,一个在等两阶段事务的会话,还有一个 pg_sleep(3600)。

~/kbdiag sessions
echo EXIT_CODE=$?
sessions  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:17+08:00)

connected: 8 client sessions (not counting kbdiag), 1 walsender, 7 background
  count  user    database  application                 client
  2      esrep   esrep     internal_rwcmgr             192.168.105.10
  1      esrep   esrep     internal_rwcmgr             192.168.105.11
  1      system  test      kbdiag_inj_idle_txn         local
  1      system  test      kbdiag_inj_lock_holder      local
  1      system  test      kbdiag_inj_lock_waiter      local
  1      system  test      kbdiag_inj_long_query       local
  1      system  test      kbdiag_inj_prepared_waiter  local

not idle: 5
  pid      user    database  application                 client  state                xact  query  wait             sql
  1045715  system  test      kbdiag_inj_lock_holder      local   idle in transaction  30s   30s    -                lock table kbdiag_inj_lock in access exclusive mode;
  1045724  system  test      kbdiag_inj_lock_waiter      local   active               30s   30s    Lock:relation    select count(*) from kbdiag_inj_lock;
  1045809  system  test      kbdiag_inj_idle_txn         local   idle in transaction  28s   27s    -                select txid_current() as kbdiag_last, pg_sleep(1);
  1046007  system  test      kbdiag_inj_prepared_waiter  local   active               25s   25s    Lock:relation    lock table kbdiag_inj_2pc in access exclusive mode;
  1046088  system  test      kbdiag_inj_long_query       local   active               24s   24s    Timeout:PgSleep  select pg_sleep(3600);
EXIT_CODE=0
  • connected: 回答"连接是谁占的":客户端会话按用户、库、应用、客户端分组计数,不算 kbdiag 自己的连接。walsender 和后台进程只在标题行里计数。local 是 Unix socket。
  • not idle: 列出在干活或开着事务的客户端会话:active、idle in transaction 等。idle 的会话和后台进程不列,要看用 --all。
  • 按事务时长从长到短排;没有事务的排后面,再按 PID 排。
  • xact 是事务时长,query 是当前(或上一条)语句的时长,wait 是等待事件,写成 类型:事件。sql 截到 60 个字符,完整 SQL 用 session <pid> 看。- 表示空值。
  • 两个 idle in transaction 的会话都在 30 秒左右,没到默认的 300 秒,所以结论是 OK。

报 WARN

只留下 idle in transaction 的会话,把阈值降到 5 秒,免得例子要等 300 秒:

~/kbdiag sessions --idle-in-txn-warn 5
echo EXIT_CODE=$?
sessions  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:37:04+08:00)

[WARN] session.idle_in_txn  session 1049818 has been idle in transaction for 9s
  verify: kbdiag session 1049818  # which locks it holds, whether it blocks anyone

connected: 4 client sessions (not counting kbdiag), 1 walsender, 7 background
  count  user    database  application          client
  2      esrep   esrep     internal_rwcmgr      192.168.105.10
  1      esrep   esrep     internal_rwcmgr      192.168.105.11
  1      system  test      kbdiag_inj_idle_txn  local

not idle: 2
  pid      user    database  application          client          state                xact  query  wait  sql
  1049818  system  test      kbdiag_inj_idle_txn  local           idle in transaction  11s   10s    -     select txid_current() as kbdiag_last, pg_sleep(1);
  179417   esrep   esrep     internal_rwcmgr      192.168.105.10  active               0s    0s     -     SELECT n.node_id, n.type, n.upstream_node_id, n.node_name...
EXIT_CODE=1
  • 每个超过阈值的会话一条 finding,verify 行给出下一步要跑的命令。
  • esrep 那一行是 repmgr 自己的查询,采样时正好在跑。
  • 退出码 1 表示至少有一条 WARN。

idle in transaction 放 5 分钟,不管应用怎么设计都是毛病:连接池泄漏,或者漏了 commit。300 秒是滤掉噪声的下限,不是容量线;如果 DBA 经常手工开着事务改数据,可以调高。默认阈值下 txn 也会把同一个会话报成长事务。两条回答的问题不同(“它闲着"和"事务太长”),所以都保留。

连接是谁占的

status 报普通用户已经连不上时,verify 行指向这里。故障注入脚本占满了普通用户可用的全部连接:

~/kbdiag sessions
echo EXIT_CODE=$?
sessions  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:38:17+08:00)

connected: 96 client sessions (not counting kbdiag), 1 walsender, 7 background
  count  user       database  application      client
  93     kbdiag_ro  test      kbdiag_inj_conn  127.0.0.1
  2      esrep      esrep     internal_rwcmgr  192.168.105.10
  1      esrep      esrep     internal_rwcmgr  192.168.105.11

not idle: 0
EXIT_CODE=0

汇总一眼就能看出扎堆:kbdiag_ro 从 127.0.0.1 连进来 93 个 idle 会话,应用是 kbdiag_inj_conn。它们都是 idle,所以 not idle 是空的。

少显示几行

~/kbdiag sessions --limit 2
echo EXIT_CODE=$?
sessions  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:20+08:00)

connected: 8 client sessions (not counting kbdiag), 1 walsender, 7 background
  count  user    database  application                 client
  2      esrep   esrep     internal_rwcmgr             192.168.105.10
  1      esrep   esrep     internal_rwcmgr             192.168.105.11
  1      system  test      kbdiag_inj_idle_txn         local
  1      system  test      kbdiag_inj_lock_holder      local
  1      system  test      kbdiag_inj_lock_waiter      local
  1      system  test      kbdiag_inj_long_query       local
  1      system  test      kbdiag_inj_prepared_waiter  local

not idle: 5
  pid      user    database  application             client  state                xact  query  wait           sql
  1045715  system  test      kbdiag_inj_lock_holder  local   idle in transaction  33s   33s    -              lock table kbdiag_inj_lock in access exclusive mode;
  1045724  system  test      kbdiag_inj_lock_waiter  local   active               33s   33s    Lock:relation  select count(*) from kbdiag_inj_lock;
... 3 more rows not shown (use --limit 0 to show all)
EXIT_CODE=0

--limit 裁的是 not idle 列表(和 --json 里的行),最后一行说明还有多少行没显示。汇总和判定仍然覆盖全部会话。

全部会话

~/kbdiag sessions --all
echo EXIT_CODE=$?
sessions  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:46+08:00)

connected: 3 client sessions (not counting kbdiag), 1 walsender, 7 background
  count  user   database  application      client
  2      esrep  esrep     internal_rwcmgr  192.168.105.10
  1      esrep  esrep     internal_rwcmgr  192.168.105.11

all: 11
  pid     user    database  application          client          type                          state   xact  query  wait                    sql
  3271    -       -         check pointer        -               checkpointer                  -       -     -      -                       -
  3272    -       -         background flush     -               background writer             -       -     -      -                       -
  3273    -       -         wal flush            -               walwriter                     -       -     -      -                       -
  3274    -       -         auto vacuum          -               autovacuum launcher           -       -     -      -                       -
  3279    system  kingbase  ksh writer           -               ksh writer                    idle    -     2s     -                       select pg_catalog.metric_update_timer();
  3280    system  -         sys_ksh collector    -               ksh collector                 idle    -     -      -                       -
  3281    system  -         logical replication  -               logical replication launcher  -       -     -      -                       -
  3294    esrep   esrep     internal_rwcmgr      192.168.105.10  client backend                idle    -     2s     -                       SELECT n.node_id as nodeId, n.type as nodeType, n.upstrea...
  179417  esrep   esrep     internal_rwcmgr      192.168.105.10  client backend                idle    -     2s     -                       SELECT pg_catalog.pg_is_in_recovery()
  759699  esrep   esrep     internal_rwcmgr      192.168.105.11  client backend                idle    -     2s     -                       SELECT state,sync_state FROM pg_stat_replication where ap...
  903372  esrep   -         node2                192.168.105.11  walsender                     active  -     -      Activity:WalSenderMain  -
EXIT_CODE=0

--all 把 idle 的会话和后台进程也列出来,并多一列 type(backend_type)。walsender 是到备库的复制连接。

权限不足

用没有监控角色的 kbdiag_ro 连接,注入的会话还在:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro sessions
echo EXIT_CODE=$?
sessions  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:35:25+08:00)

connected: 1 walsender, 15 hidden
  count  user    database  application                 client
  3      esrep   esrep     internal_rwcmgr             ?
  1      -       -         auto vacuum                 ?
  1      -       -         background flush            ?
  1      -       -         check pointer               ?
  1      -       -         wal flush                   ?
  1      system  -         logical replication         ?
  1      system  -         sys_ksh collector           ?
  1      system  kingbase  -                           ?
  1      system  test      kbdiag_inj_idle_txn         ?
  1      system  test      kbdiag_inj_lock_holder      ?
  1      system  test      kbdiag_inj_lock_waiter      ?
  1      system  test      kbdiag_inj_long_query       ?
  1      system  test      kbdiag_inj_prepared_waiter  ?

not idle: 0 visible, 15 hidden
redacted: 15 rows of session.activity hide state, backend_type, client_addr, ages, wait, query (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • 这个账号看不到别人会话的状态、类型、客户端地址、各项时长、等待事件和 SQL,分不出会话是在干活、idle 还是后台进程,所以不说它们是 idle:15 个全算 hidden,照样按用户、库、应用计进汇总。
  • ? 是这个账号看不到的值,- 是空值。
  • 这些会话判不了,所以结论是 UNKNOWN、退出码 3,而不是 OK。redacted 行写明了被遮蔽的列和解决办法:授予 sys_monitor。
  • 会话自己关掉 track_activities(SET 或 ALTER ROLE ... SET)时,状态显示 disabled。它照样列出,但时长显示 ?:服务器里留的是旧值。它同样让结论变成 UNKNOWN,原因是 track_activities_off。

JSON

--json 总是包含全部会话(包括 idle 的会话和后台进程),值是原始值:时长以秒计,SQL 是完整的。格式见读懂一次真实结果。

退出码

退出码含义
0OK
1WARN:有会话 idle in transaction 太久
3UNKNOWN:有会话没采到或看不到
64用法错误
69连不上数据库

返回使用手册

2 - session:单个会话

一个会话的完整 SQL、在等什么、挡住了谁、持有哪些锁。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。示例里的会话是故障注入脚本造出来的:1045715 在 idle in transaction 状态下持有表 kbdiag_inj_lock 的排他锁,1045724 在等它,1045809 是另一个 idle in transaction 的会话。PID、计数与时间只属于本次采样。

用法

kbdiag session <pid> [--lock-wait-warn 秒] [--idle-in-txn-warn 秒] [--json]
参数作用
<pid>要看的会话 PID,必填
--lock-wait-warn 秒等锁超过多少秒报 WARN,默认 10
--idle-in-txn-warn 秒idle in transaction 超过多少秒报 WARN,默认 300
--json输出 JSON

连接参数和 sessions 相同。阈值和 finding 与 sessions、locks 相同。

在等锁的会话

~/kbdiag session 1045724
echo EXIT_CODE=$?
session  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:22+08:00)

[WARN] lock.waiting  session 1045724 has waited 35s for AccessShareLock on public.kbdiag_inj_lock, blocked by 1045715
  verify: kbdiag session 1045715  # what the blocking session is doing

session 1045724
  user         system
  database     test
  application  kbdiag_inj_lock_waiter
  client       local
  type         client backend
  state        active  (for 35s)
  xact         35s
  query        35s
  wait         Lock:relation
  xid / xmin   - / 6343

sql
  select count(*) from kbdiag_inj_lock;

waiting for: 1
  object                  wants            waited  blocked by
  public.kbdiag_inj_lock  AccessShareLock  35s     1045715

blocking: 0

holds: 0
EXIT_CODE=1
  • 最上面的键值块说明这个会话是谁(用户、库、应用、客户端、类型)、在干什么:状态和处于这个状态多久、事务和语句时长、等待事件、事务号和快照 xmin。
  • sql 是完整的语句,保留原来的换行。这是唯一能看到完整 SQL 的命令。idle 的会话标题写 last sql,因为那条语句已经结束了。
  • waiting for 是它想要的锁、等了多久、被谁直接挡住。
  • 它等了 35 秒,超过默认的 10 秒,所以有一条 lock.waiting WARN,退出码 1。verify 行指向挡路的会话。
  • waited 从会话上一次状态变化算起,只会多报一点,不会少报。

挡路的会话

~/kbdiag session 1045715
echo EXIT_CODE=$?
session  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:21+08:00)

[WARN] lock.waiting  session 1045724 has waited 34s for AccessShareLock on public.kbdiag_inj_lock, blocked by 1045715

session 1045715
  user         system
  database     test
  application  kbdiag_inj_lock_holder
  client       local
  type         client backend
  state        idle in transaction  (for 34s)
  xact         34s
  query        34s
  wait         -
  xid / xmin   6343 / -

last sql
  lock table kbdiag_inj_lock in access exclusive mode;

waiting for: 0

blocking: 1
  pid      object                  wants            waited
  1045724  public.kbdiag_inj_lock  AccessShareLock  34s

holds: 1
  object                  mode
  public.kbdiag_inj_lock  AccessExclusiveLock
EXIT_CODE=1
  • blocking 列出在等这个会话所持有的锁的会话,holds 列出它持有的锁。
  • 每个事务都持有自己的 virtualxid 和 transactionid 锁,除非有人在等这类锁,否则 holds 里不列;事务号在上面的键值块里。
  • 行锁会写明类型,例如 public.t (tuple),免得被读成表锁。
  • 这条 WARN 是等待者的 lock.waiting:它说的是这个会话已经挡住别人 34 秒,这是这个会话自己的问题。它没有 verify 行,因为会指回这里。
  • 这个会话 idle in transaction 已 34 秒:拿了锁一直没提交。它自己的 session.idle_in_txn 要到 300 秒才报。

idle in transaction

把阈值降到 10 秒:

~/kbdiag session 1045809 --idle-in-txn-warn 10
echo EXIT_CODE=$?
session  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:23+08:00)

[WARN] session.idle_in_txn  session 1045809 has been idle in transaction for 32s

session 1045809
  user         system
  database     test
  application  kbdiag_inj_idle_txn
  client       local
  type         client backend
  state        idle in transaction  (for 33s)
  xact         35s
  query        34s
  wait         -
  xid / xmin   6344 / -

last sql
  select txid_current() as kbdiag_last, pg_sleep(1);

waiting for: 0

blocking: 0

holds: 0
EXIT_CODE=1

这个会话有事务号,但没持有别人想要的锁,所以 holds 是空的。它压着的是 vacuum 视界,见 txn。

权限不足

用没有监控角色的 kbdiag_ro 连接,看挡路的会话:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro session 1045715
echo EXIT_CODE=$?
session  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:35:28+08:00)

session 1045715
  user         system
  database     test
  application  kbdiag_inj_lock_holder
  client       ?
  type         ?
  state        ?
  xact         ?
  query        ?
  wait         ?
  xid / xmin   6343 / -

sql
  ?

waiting for: 0

blocking: 1
  pid      object                  wants            waited
  1045724  public.kbdiag_inj_lock  AccessShareLock  ?

holds: 1
  object                  mode
  public.kbdiag_inj_lock  AccessExclusiveLock
redacted: 1 row of session.activity hides state, backend_type, client_addr, ages, wait, query (insufficient_privilege; grant sys_monitor)
redacted: 1 row of lock.list hides wait (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • 用户、库、应用看得到,事务号和 xmin 也看得到;状态、时长、客户端、类型、等待事件和 SQL 显示 ?。
  • 锁和谁挡谁看得到,别的会话等了多久看不到。
  • 这个会话判不了,所以结论是 UNKNOWN、退出码 3。授予 sys_monitor 后可以看全。

会话不存在

~/kbdiag session 999999
echo EXIT_CODE=$?
kbdiag: no session with pid 999999 (it may have ended)
session  UNKNOWN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:46+08:00)

session 999999: not found (it may have ended)
EXIT_CODE=3

找不到这个 PID 时(可能已经结束),标准错误输出一行说明,结论是 UNKNOWN,退出码 3。不给 PID 是用法错误,退出码 64。

JSON

--json 带文本所依据的活动行和锁行,值是原始值:时长以秒计,锁行一行不省,包括 virtualxid。下面是上面那个等待者的 lock.waiting finding,字段可供脚本使用:

{
  "id": "lock.waiting",
  "level": "WARN",
  "symptom": "session 1045724 has waited 37s for AccessShareLock on public.kbdiag_inj_lock, blocked by 1045715",
  "evidence": [
    {
      "probe_id": "lock.list",
      "fields": {
        "blocker_pids": [
          1045715
        ],
        "lock_mode": "AccessShareLock",
        "relation": "public.kbdiag_inj_lock",
        "wait_s": 37.3,
        "waiter_pid": 1045724
      }
    }
  ],
  "cause": null,
  "next": [
    {
      "kind": "verify",
      "command": "kbdiag session 1045715",
      "note": "what the blocking session is doing"
    }
  ]
}

退出码

退出码含义
0OK
1WARN:等锁或 idle in transaction 超过阈值
3UNKNOWN:会话不存在,或数据没采到、看不到
64用法错误
69连不上数据库

返回使用手册

3 - locks:锁等待

谁挡住了谁:先列挡路者,再列每个在等锁的会话、等了多久、被谁挡住。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。锁等待是故障注入脚本造出来的。主库上,1045715 在 idle in transaction 状态下持有表 kbdiag_inj_lock 的排他锁,1045724 在等它;一个两阶段(prepared)事务持有 kbdiag_inj_2pc 上的锁,1046007 在等它。PID、计数与时间只属于本次采样。

用法

kbdiag locks [--limit N] [--lock-wait-warn 秒] [--json]
参数作用
--limit N最多显示 N 个等锁的会话,默认 50,0 表示全部
--lock-wait-warn 秒等锁超过多少秒报 WARN,默认 10
--json输出 JSON

连接参数和 sessions 相同。--limit 只裁 waiting 列表,判定始终覆盖所有等待。

有会话在等锁

~/kbdiag locks
echo EXIT_CODE=$?
locks  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:17+08:00)

[WARN] lock.waiting  session 1045724 has waited 30s for AccessShareLock on public.kbdiag_inj_lock, blocked by 1045715
  verify: kbdiag session 1045715  # what the blocking session is doing

[WARN] lock.waiting  session 1046007 has waited 25s for AccessExclusiveLock on public.kbdiag_inj_2pc, blocked by an uncommitted two-phase transaction
  verify: kbdiag txn  # the blocker is an uncommitted two-phase transaction: its gid and how long it has been pending

blockers: 2
  pid      blocks  holds
  2PC      1       public.kbdiag_inj_2pc RowExclusiveLock
  1045715  1       public.kbdiag_inj_lock AccessExclusiveLock

waiting: 2
  pid      object                  wants                waited  blocked by
  1045724  public.kbdiag_inj_lock  AccessShareLock      30s     1045715
  1046007  public.kbdiag_inj_2pc   AccessExclusiveLock  25s     2PC
EXIT_CODE=1
  • 先列 blockers,因为出事时第一问是"谁挡的"。一个挡路者常常挡住几十个会话,所以按挡住的会话数排。holds 是挡路者在等待者想要的对象上持有的锁。
  • 两阶段事务不属于任何会话,所以写成 2PC。它的 finding 会说明这一点,并指向 kbdiag txn,在那里能看到 gid 和挂了多久。
  • 挡路者自己也在排队时会标出 (queued ahead for ...):服务器会把排在前面、锁模式冲突的等待者也算作挡路者。
  • waiting 列出每个在等锁的会话,等得最久的在前。blocked by 只写直接挡路的会话;链条更长时,对挡路者依次跑 session。
  • 每个等锁超过 --lock-wait-warn 的会话一条 lock.waiting;等得更短的照样列出,但不报。
  • waited 从等待者上一次状态变化算起:V8R6 没有记录开始等锁的时间。只会多报一点,不会少报。

等锁 10 秒对 OLTP 来说已经是事故,对批处理可能是正常的,所以报 WARN 而不是 FAIL。10 秒是滤掉行锁瞬时争用的下限;批处理库可以调高。

没有等待时:

~/kbdiag locks
echo EXIT_CODE=$?
locks  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:43+08:00)

waiting: 0
EXIT_CODE=0

在备库上

在备库上拿一个会话级的 advisory 锁:

~/kbdiag locks
echo EXIT_CODE=$?
locks  WARN  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:19+08:00)

[WARN] lock.waiting  session 599825 has waited 14s for advisory lock, blocked by 599816
  verify: kbdiag session 599816  # what the blocking session is doing

blockers: 1
  pid     blocks  holds
  599816  1       advisory ExclusiveLock

waiting: 1
  pid     object    wants          waited  blocked by
  599825  advisory  ExclusiveLock  14s     599816
EXIT_CODE=1

没有表的锁(比如 advisory 锁)用锁类型当对象名。

权限不足

用没有监控角色的 kbdiag_ro 连接,主库上的等待还在:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro locks
echo EXIT_CODE=$?
locks  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:35:26+08:00)

blockers: 2
  pid      blocks  holds
  2PC      1       public.kbdiag_inj_2pc RowExclusiveLock
  1045715  1       public.kbdiag_inj_lock AccessExclusiveLock

waiting: 2
  pid      object                  wants                waited  blocked by
  1045724  public.kbdiag_inj_lock  AccessShareLock      ?       1045715
  1046007  public.kbdiag_inj_2pc   AccessExclusiveLock  ?       2PC
redacted: 2 rows of lock.list hide wait (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • 锁和谁挡谁看得到。这个账号看不到别的会话的时间戳,所以等待时长显示 ?,阈值没法判。结论是 UNKNOWN,退出码 3。
  • 授予 sys_monitor 后可以看全。

JSON

--json 列出等锁会话的锁行,加上挡路者在同一对象上的锁:pid、locktype、relation、mode、granted、wait_s、blocked_by。blocked_by 保留服务器给的原样列表,两阶段事务写成 0。

已知限制

  • 并行查询的 worker 有自己的 PID 和锁行,所以一条等锁的并行查询可能被算成几个被挡住的会话。
  • 同一个挡路者的几个 advisory 锁会一起列在它的 holds 里,因为只按锁类型比对。

退出码

退出码含义
0OK
1WARN:有会话等锁太久
3UNKNOWN:数据没采到或看不到
64用法错误
69连不上数据库

返回使用手册

4 - txn:事务

谁压着 vacuum 视界:开着的事务、两阶段(prepared)事务,以及其中最老的那个。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。示例里的事务是故障注入脚本造出来的:两个 idle in transaction 的会话(其中一个持有表锁)、几个在等锁的会话、一个 pg_sleep(3600),还有 kbdiag_inj_2pc,一个既没提交也没回滚的两阶段事务。PID、计数与时间只属于本次采样。

用法

kbdiag txn [--limit N] [--xact-warn 秒] [--prepared-warn 秒] [--json]
参数作用
--limit N最多显示 N 个事务,默认 50,0 表示全部
--xact-warn 秒事务开了超过多少秒报 WARN,默认 300
--prepared-warn 秒两阶段事务挂了超过多少秒报 WARN,默认 900
--json输出 JSON

连接参数和 sessions 相同。--limit 只影响显示,判定始终覆盖全部事务。

默认输出

~/kbdiag txn
echo EXIT_CODE=$?
txn  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:18+08:00)

oldest xid: 6343  (1045715 xid, 1045724 xmin, 1046007 xmin, 1046088 xmin)

open transactions: 5
  pid      user    database  application                 state                xact  xid   xmin  sql
  1045715  system  test      kbdiag_inj_lock_holder      idle in transaction  31s   6343  -     lock table kbdiag_inj_lock in access exclusive mode;
  1045724  system  test      kbdiag_inj_lock_waiter      active               30s   -     6343  select count(*) from kbdiag_inj_lock;
  1045809  system  test      kbdiag_inj_idle_txn         idle in transaction  29s   6344  -     select txid_current() as kbdiag_last, pg_sleep(1);
  1046007  system  test      kbdiag_inj_prepared_waiter  active               25s   6347  6343  lock table kbdiag_inj_2pc in access exclusive mode;
  1046088  system  test      kbdiag_inj_long_query       active               25s   -     6343  select pg_sleep(3600);

prepared: 1
  gid             owner   database  age  xid
  kbdiag_inj_2pc  system  test      26s  6346
EXIT_CODE=0
  • oldest xid 是所有会话和两阶段事务里最老的事务号,以及谁持有它。这里 1045715 的事务号是 6343,另外三个会话的快照(xmin)是在 6343 还没结束时拿的。VACUUM 不能清理比它新的行版本,所以这一行回答"谁压着 vacuum 视界"。事务号按 2^32 取模比较,和服务器一样。
  • open transactions 列出在事务里的会话:有事务开始时间、事务号或快照 xmin 的。事务最老的在前。xid 在第一次写的时候才分配,只读事务只有 xmin。
  • prepared 列出所有两阶段事务:gid、属主、库、挂了多久、事务号。它们不属于任何会话,所以 sessions 看不到。
  • 都没到默认阈值,所以结论是 OK。

报 WARN

把两个阈值都降到 10 秒:

~/kbdiag txn --xact-warn 10 --prepared-warn 10
echo EXIT_CODE=$?
txn  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:21+08:00)

[WARN] txn.long  session 1045715 has had a transaction open for 34s, now idle in transaction
  verify: kbdiag session 1045715  # what it is running, which locks it holds, whether it blocks anyone

[WARN] txn.long  session 1045724 has had a transaction open for 34s, now active
  verify: kbdiag session 1045724  # what it is running, which locks it holds, whether it blocks anyone

[WARN] txn.long  session 1045809 has had a transaction open for 32s, now idle in transaction
  verify: kbdiag session 1045809  # what it is running, which locks it holds, whether it blocks anyone

[WARN] txn.long  session 1046007 has had a transaction open for 28s, now active
  verify: kbdiag session 1046007  # what it is running, which locks it holds, whether it blocks anyone

[WARN] txn.long  session 1046088 has had a transaction open for 28s, now active
  verify: kbdiag session 1046088  # what it is running, which locks it holds, whether it blocks anyone

[WARN] txn.prepared  two-phase transaction kbdiag_inj_2pc prepared 29s ago and not finished, holding back the vacuum horizon
  fix: ROLLBACK PREPARED 'kbdiag_inj_2pc'  # check with the application whether to commit (COMMIT PREPARED) or roll back; run it connected to database test, outside a transaction block

oldest xid: 6343  (1045715 xid, 1045724 xmin, 1046007 xmin, 1046088 xmin)

open transactions: 5
  pid      user    database  application                 state                xact  xid   xmin  sql
  1045715  system  test      kbdiag_inj_lock_holder      idle in transaction  34s   6343  -     lock table kbdiag_inj_lock in access exclusive mode;
  1045724  system  test      kbdiag_inj_lock_waiter      active               34s   -     6343  select count(*) from kbdiag_inj_lock;
  1045809  system  test      kbdiag_inj_idle_txn         idle in transaction  32s   6344  -     select txid_current() as kbdiag_last, pg_sleep(1);
  1046007  system  test      kbdiag_inj_prepared_waiter  active               28s   6347  6343  lock table kbdiag_inj_2pc in access exclusive mode;
  1046088  system  test      kbdiag_inj_long_query       active               28s   -     6343  select pg_sleep(3600);

prepared: 1
  gid             owner   database  age  xid
  kbdiag_inj_2pc  system  test      29s  6346
EXIT_CODE=1
  • txn.long:每个开了超过 --xact-warn 的事务一条,verify 行指向对应的会话。
  • txn.prepared:挂了超过 --prepared-warn 的两阶段事务。在有人提交或回滚之前,它一直持有锁、压着 vacuum 视界。fix 行给出语句,kbdiag 只打印,不执行。注释写明:先和应用确认是提交(COMMIT PREPARED)还是回滚,连到这个事务所在的库,在事务块外执行。
  • gid 含控制字符时,终端上显示的是转义后的文本,照抄执行匹配不到。这时不给 fix 行,verify 行提示从 --json 取原始 gid。
  • 两条都只报 WARN,不报 FAIL:它们的危害(表膨胀、锁长期不放)是以后的事;它们眼下挡住的会话由 locks 报。
  • 300 秒和 900 秒在服务器端没有对应的客观线。300 秒会碰上正常的批处理,批处理库可以调高。
  • 默认阈值下,idle in transaction 超过 300 秒的会话也会被 sessions 报成 session.idle_in_txn。两条回答的问题不同。

在备库上

~/kbdiag txn
echo EXIT_CODE=$?
txn  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:20+08:00)

oldest xid: 6354  (599825 xmin)

open transactions: 1
  pid     user    database  application             state   xact  xid  xmin  sql
  599825  system  test      kbdiag_inj_lock_waiter  active  14s   -    6354  select pg_advisory_lock(424242);

txn.prepared: not_applicable  (a standby cannot see the primary's two-phase transactions: run kbdiag txn on the primary)
EXIT_CODE=0

备库看不到主库的两阶段事务,所以 txn.prepared 是 not_applicable。它不表示"没有",也不影响结论。到主库上跑 txn。

权限不足

用没有监控角色的 kbdiag_ro 连接:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro txn
echo EXIT_CODE=$?
txn  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:35:27+08:00)

oldest xid: 6343  (1045715 xid, 1045724 xmin, 1046007 xmin, 1046088 xmin)

open transactions: 5, 10 sessions hidden
  pid      user    database  application                 state  xact  xid   xmin  sql
  1045715  system  test      kbdiag_inj_lock_holder      ?      ?     6343  -     ?
  1045724  system  test      kbdiag_inj_lock_waiter      ?      ?     -     6343  ?
  1045809  system  test      kbdiag_inj_idle_txn         ?      ?     6344  -     ?
  1046007  system  test      kbdiag_inj_prepared_waiter  ?      ?     6347  6343  ?
  1046088  system  test      kbdiag_inj_long_query       ?      ?     -     6343  ?

prepared: 1
  gid             owner   database  age  xid
  kbdiag_inj_2pc  system  test      35s  6346
redacted: 15 rows of session.activity hide state, backend_type, client_addr, ages, wait, query (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • KingbaseES 对任何账号都显示别人会话的事务号和 xmin,所以 oldest xid 和开着的事务照样找得出来,只是状态、时长和 SQL 显示 ?。
  • 既没有 xid 也没有 xmin 的遮蔽会话只计数(10 sessions hidden):它们多半是 idle,不能说成事务。
  • 结论是 UNKNOWN,退出码 3。授予 sys_monitor 后可以看全。
  • 会话活动或两阶段事务有一项没采到时,oldest xid 会注明可能有更老的;一个持有者都没找到时显示 unknown。

退出码

退出码含义
0OK
1WARN:有长事务,或两阶段事务挂得太久
3UNKNOWN:数据没采到或看不到
64用法错误
69连不上数据库

返回使用手册

5 - waits:等待事件

此刻在干活的会话在等什么,扎堆最多的在前。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。示例里的会话是故障注入脚本造出来的:两个 idle in transaction 的会话、两个在等表锁的会话、一个 pg_sleep(3600)。PID、计数与时间只属于本次采样。

用法

kbdiag waits [--json]

没有自己的参数。连接参数和 sessions 相同。

默认输出

~/kbdiag waits
echo EXIT_CODE=$?
waits  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:35:18+08:00)

not idle: 5
  wait               state                sessions  pids
  Lock:relation      active               2         1045724 1046007
  Client:ClientRead  idle in transaction  2         1045715 1045809
  Timeout:PgSleep    active               1         1046088

not shown: 3 idle, 8 background
EXIT_CODE=0
  • not idle 把在干活的会话按等待事件和状态分组,sessions 是个数,pids 列出是哪些。人数最多的组在前,因为要找的就是扎堆;人数相同时 active 在前。
  • Lock:relation:两个会话在等表锁;谁挡的、等了多久看 locks。
  • Client:ClientRead 加 idle in transaction:会话开着事务,在等客户端发下一条语句。
  • Timeout:PgSleep 是注入的 pg_sleep。active 却没有等待事件的会话写 (running):在 CPU 上,或者这段代码没有埋点。
  • pids 最多列 10 个,其余写 ... (+N),--json 里是全的。
  • not shown 给不列出来的计数:idle 的会话不回答"卡在哪";后台进程在主循环里空闲(任何 Activity 类等待,比如没东西可发的 walsender、两次 checkpoint 之间的 checkpointer)也不回答。后台进程卡在真正的等待上(比如 checkpointer 等 IO:DataFileSync)照样列出,状态写 (background)。

没有阈值,也没有参数:同样是 10 个会话等 IO,对一个库是事故,对另一个库是常态,所以 waits 只报告不判定。等锁太久由 locks 判。

空闲的主库:

~/kbdiag waits
echo EXIT_CODE=$?
waits  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:44+08:00)

not idle: 0

not shown: 3 idle, 8 background
EXIT_CODE=0

主库忙的时候,追赶中的 walsender 可能以 IO:WALRead 之类的等待出现,属正常。

在备库上

~/kbdiag waits
echo EXIT_CODE=$?
waits  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:21+08:00)

not idle: 1
  wait           state   sessions  pids
  Lock:advisory  active  1         599825

not shown: 3 idle, 4 background
EXIT_CODE=0

权限不足

用没有监控角色的 kbdiag_ro 连接:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro waits
echo EXIT_CODE=$?
waits  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:35:27+08:00)

not idle: 0

not shown: 1 background, 15 hidden (state unknown)
redacted: 15 rows of wait.summary hide wait, state (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • 别的用户的会话看不到等待事件和状态,不知道是不是 idle,所以计成 hidden (state unknown),不算作 idle。关了 track_activities 的会话出于同样原因计成 untracked (state unknown)。
  • 有看不到的会话,kbdiag 就不能说没人在等,所以结论是 UNKNOWN,退出码 3。授予 sys_monitor 后可以看全。

JSON

--json 包含所有分组(包括 idle 和后台进程的),PID 列表是全的:wait_event_type、wait_event、state、sessions、pids。

退出码

退出码含义
0OK
3UNKNOWN:数据没采到或看不到
64用法错误
69连不上数据库

返回使用手册

6 - status:实例概况

这是个什么实例、基本面是否正常:角色、复制、连接数、各库大小、磁盘。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。FAIL 的例子由故障注入脚本造出来,它把普通用户可用的连接全部占满。数值只属于本次采样。

用法

kbdiag status [--json]

status 没有自己的参数。连接参数和 sessions 相同。

只判两件事:

  • FAIL:普通用户可用的连接(max_connections 减去 superuser_reserved_connections)全部占满,业务已经连不上。
  • WARN:备库没在收 WAL,即没有 WAL 接收进程,或者它的状态不是 streaming。这时查询还能跑,但主库一旦挂掉,没有能接管的最新备库。

不报"连接快满"。连接多到什么程度算多,要看应用,所以 status 只给出数字,由你判断。

在主库上

~/kbdiag status
echo EXIT_CODE=$?
status  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:42+08:00)

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-20 22:19:13  (up 6d 15h)
  connections     5 / 97  (max_connections 100 - superuser_reserved 3)

inst.downstreams: 1
  name   address         state      sync
  node2  192.168.105.11  streaming  quorum

inst.upstream: not_applicable  (primary)

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

inst.disk  (filesystem of data_directory)
  used   14 GB / 199 GB  (7%)
  free  185 GB
EXIT_CODE=0
  • 第一行的角色(primary / standby)来自 sys_is_in_recovery()。
  • inst.info:connections 只数连到某个库的后端,不含后台进程,可以直接和普通用户可用的 97 个比。
  • inst.downstreams:本实例给哪些备库发 WAL,一个备库一行,数据来自 sys_stat_replication。sync 照数据库原样显示,repmgr 下这里是 quorum,不是 sync / async。
  • inst.upstream 只对备库适用。
  • inst.databases:非模板库,从大到小排。大小按 1024 进位,和 pg_size_pretty 一致。
  • inst.disk:data_directory 所在的文件系统,口径和 df 一样。已用加可用小于总量,差的是给 root 预留的块。只展示,不参与判定。

在备库上

~/kbdiag status
echo EXIT_CODE=$?
status  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:22+08:00)

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-23 15:44:58  (up 3d 21h)
  connections     5 / 97  (max_connections 100 - superuser_reserved 3)

inst.upstream
  status    streaming
  upstream  192.168.105.10:54321
  slot      repmgr_slot_2
  last_msg  11s ago

inst.downstreams: 0

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  kingbase   14 MB
  mydb       14 MB
  security   14 MB

inst.disk  (filesystem of data_directory)
  used   12 GB / 199 GB  (6%)
  free  187 GB
EXIT_CODE=0
  • 备库上游排在前面,数据来自 sys_stat_wal_receiver:从哪里收 WAL、走哪个槽、最后一条消息是多久前。
  • last_msg 只展示,不判。主库空闲时每 wal_receiver_status_interval(默认 10 秒)才发一条,几秒是正常值。
  • WAL 接收进程被暂停时(比如被 SIGSTOP),状态仍然是 streaming,status 不会报。如果 last_msg 一直在涨,请自己去备库上看 WAL 接收进程。slots 页有这种情况的实采。

连接全部占满

~/kbdiag status
echo EXIT_CODE=$?
status  FAIL  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:38:16+08:00)

[FAIL] inst.connections  98 connections in use, reaching the 97 ordinary users may open (max_connections 100 minus 3 reserved for superusers): ordinary users can no longer connect
  verify: kbdiag sessions  # who holds the connections: the summary at the top counts them by user, database, application and client

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-20 22:19:13  (up 6d 15h)
  connections     98 / 97  (max_connections 100 - superuser_reserved 3)

inst.downstreams: 1
  name   address         state      sync
  node2  192.168.105.11  streaming  quorum

inst.upstream: not_applicable  (primary)

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

inst.disk  (filesystem of data_directory)
  used   14 GB / 199 GB  (7%)
  free  185 GB
EXIT_CODE=2
  • 已用 98 个,超过了 97,因为超级用户还能从保留的连接里进来,kbdiag 自己用的 system 连接也在其中。
  • verify 行指向 sessions,它的汇总按用户、库、应用、客户端给连接计数。这次采样里能看到 kbdiag_ro 从 127.0.0.1 连进来 93 个 idle 会话。

备库没在收 WAL

这种情况还没在测试环境里造出来,下面的 finding 是从源码里摘的文字,不是实采。备库没有 WAL 接收进程时,status 报:

[WARN] inst.upstream  the standby has no WAL receiver and is not receiving WAL from the primary: if the primary fails now, no standby can take over
  verify: kbdiag slots  # run on the primary: is this standby's slot inactive?

有接收进程但状态不是 streaming 时,finding 里写的是那个状态。退出码是 1。

走 TCP 时

只有确定跑在数据库主机上,kbdiag 才读 inst.disk,即满足下面一条:

  • 走 Unix socket;
  • --host 是 localhost / 127.0.0.1 / ::1,并且 data_directory 在本机存在。要核对目录,是因为端口可能被转发到别的机器。

否则 inst.disk 是 not_applicable。下面用 kbdiag_ro 连主库自己的网络地址:

PGPASSWORD=... ~/kbdiag status --host 192.168.105.10 -U kbdiag_ro
echo EXIT_CODE=$?
status  OK  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-09-27T13:40:08+08:00)

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-20 22:19:13  (up 6d 15h)
  connections     5 / 97  (max_connections 100 - superuser_reserved 3)

inst.downstreams: 1
  name   address         state      sync
  node2  192.168.105.11  streaming  quorum

inst.upstream: not_applicable  (primary)

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

inst.disk: not_applicable  (remote connection)
EXIT_CODE=0

not_applicable 不影响结论。

权限不足时

kbdiag_ro 没有任何监控角色,但在 KingbaseES V8R6 上它照样能完整看到 sys_stat_replication、sys_stat_wal_receiver 和 data_directory,所以 status 给它的结果和 system 一样。能被挡住的只有库大小:对某个库没有 CONNECT 权限时,那个库的大小为空,并记进 redacted。库大小不参与判定,所以结论仍然是 OK,不是 UNKNOWN。

JSON

--json 保留原始值:大小是字节,时长是秒,版本是短版本号。inst.info 多一个 usable_connections,inst.disk 是 total_bytes、used_bytes、avail_bytes。不适用的 probe 是 "status": "not_applicable",并带原因,比如 "primary" 或 "remote connection"。

退出码

退出码含义
0OK
1WARN:备库没在收 WAL
2FAIL:普通用户可用的连接已经占满
3UNKNOWN:有数据没采到
64参数错误
69连不上数据库

返回使用手册

7 - slots:复制槽

列出复制槽:谁在消费、保留了多少 WAL、有没有压着 vacuum。

采集于 2026-09-27(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 93bf65d 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。WARN 的例子由故障注入脚本造出来:它暂停(SIGSTOP)备库的 WAL 接收进程,过了 wal_sender_timeout(这里是 30 秒)后主库上的槽变成不活跃,和备库挂掉时一样。数值只属于本次采样。

用法

kbdiag slots [--json]

没有自己的参数。连接参数和 sessions 相同。

正常

~/kbdiag slots
echo EXIT_CODE=$?
slots  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:34:45+08:00)

slots: 1
  name           type      active            retained  xmin  xmin age  restart_lsn
  repmgr_slot_2  physical  yes (pid 903372)  0 bytes   6342  0         0/A42EE580
EXIT_CODE=0
  • active 说明有没有人在消费这个槽,以及是哪个进程(这里是到备库的 walsender)。
  • retained 是这个槽让实例保留的 WAL 量,按 1024 进位,和 pg_size_pretty 一致。主库上从当前 WAL 位置算,备库上从回放位置算。
  • xmin 是这个槽要求实例保留的最老事务号。这个物理槽的 xmin 来自备库的 hot_standby_feedback。xmin age 是它落后当前事务号多少。
  • 逻辑槽还可能带 catalog_xmin,它压着系统表的 vacuum。只有某个槽带它时才出现这一列。(实验环境是 wal_level=replica,没有逻辑槽。)

备库自己没有槽时:

~/kbdiag slots
echo EXIT_CODE=$?
slots  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:21+08:00)

slots: 0
EXIT_CODE=0

不活跃的槽

~/kbdiag slots
echo EXIT_CODE=$?
slots  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-09-27T13:37:55+08:00)

[WARN] slot.inactive  replication slot repmgr_slot_2 is inactive, retaining 216 bytes WAL, xmin 6354 holding back the vacuum horizon
  verify: kbdiag status  # run on this slot's downstream node (usually a standby): if it cannot connect, the node is down; inst.upstream with no receiver or not streaming means it is not receiving WAL; if it shows streaming, run it again after 10-20s: a last_msg that keeps growing means the receiver is stuck

slots: 1
  name           type      active  retained   xmin  xmin age  restart_lsn
  repmgr_slot_2  physical  no      216 bytes  6354  0         0/A42FF338
EXIT_CODE=1
  • 不活跃的槽没人消费,却照样保留 WAL;带 xmin 的还会让 VACUUM 清不掉旧的行版本。不活跃本身就是那条线,所以没有时间阈值,也没有参数。
  • 报 WARN 而不是 FAIL:业务照常。危害(WAL 撑满磁盘、表膨胀、没有跟得上的备库)是以后的事。
  • 刚注入完几乎没保留什么 WAL,真出故障时它会一直涨。
  • repmgr 重启备库的那几秒,槽也会不活跃,同样会报。
  • 只有确认下游真的不要了才删槽。kbdiag 不会替你删。

按 verify 行往下查

verify 行让你到这个槽的下游节点上跑 kbdiag status,通常是备库(备库也可以有自己的下游)。在被暂停的备库上:

~/kbdiag status
echo EXIT_CODE=$?
status  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:37:55+08:00)

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-23 15:44:58  (up 3d 21h)
  connections     3 / 97  (max_connections 100 - superuser_reserved 3)

inst.upstream
  status    streaming
  upstream  192.168.105.10:54321
  slot      repmgr_slot_2
  last_msg  44s ago

inst.downstreams: 0

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  kingbase   14 MB
  mydb       14 MB
  security   14 MB

inst.disk  (filesystem of data_directory)
  used   12 GB / 199 GB  (6%)
  free  187 GB
EXIT_CODE=0

WAL 接收进程仍显示 streaming,因为被暂停的进程不会改自己的状态。照注释说的,隔 10–20 秒再跑一次:

~/kbdiag status
echo EXIT_CODE=$?
status  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-09-27T13:38:11+08:00)

inst.info
  version         V008R006C009B0014
  data_directory  /home/kingbase/cluster/install/kingbase/data
  port            54321
  start_time      2026-09-23 15:44:58  (up 3d 21h)
  connections     3 / 97  (max_connections 100 - superuser_reserved 3)

inst.upstream
  status    streaming
  upstream  192.168.105.10:54321
  slot      repmgr_slot_2
  last_msg  1m 0s ago

inst.downstreams: 0

inst.databases: 5, total 382 MB
  test      325 MB
  esrep      15 MB
  kingbase   14 MB
  mydb       14 MB
  security   14 MB

inst.disk  (filesystem of data_directory)
  used   12 GB / 199 GB  (6%)
  free  187 GB
EXIT_CODE=0

last_msg 从 44 秒涨到 1 分钟:接收进程卡住了。status 不判 last_msg,因为空闲的主库每 wal_receiver_status_interval(默认 10 秒)才发一条消息。如果节点根本连不上,说明它挂了;如果 inst.upstream 没有接收进程或者不是 streaming,status 会报 WARN。

退出码

退出码含义
0OK
1WARN:有不活跃的槽
3UNKNOWN:数据没采到
64用法错误
69连不上数据库

返回使用手册

8 - space:磁盘、WAL、库大小

空间账:磁盘、WAL 大小对照参数、各库和表空间大小。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。这一页的例子来自正常的实验环境,以及两个看不全的账号:没有监控角色的 kbdiag_ro,分别走 127.0.0.1 和节点的网络地址。这条命令没有做故障注入;它能报的那一条 FAIL 在实验环境里没有造出来(见最后一节)。数值只属于本次采样。

用法

kbdiag space [--json]

没有自己的参数。连接参数和 sessions 相同。

主库,正常

~/kbdiag space
echo EXIT_CODE=$?
space  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:53+08:00)

disk: 1 filesystem
  holds                used   size    free    use
  data_directory, wal  15 GB  199 GB  184 GB  7%

wal: 214 files, 3248 MB
  max_wal_size       1024 MB
  wal_keep_segments  8192 MB  (512 x 16 MB)

databases: 5, total 439 MB
  test      381 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

tablespaces: 3
  name         location             size
  sys_default  (in data_directory)  467 MB
  sys_global   (in data_directory)  735 kB
  sysaudit     (in data_directory)  24 kB
EXIT_CODE=0
  • disk 列出放数据目录、WAL 目录和表空间的文件系统,同一个文件系统上的目录合成一行(按设备号合并,所以 sys_wal 是指向另一块盘的符号链接时会单独出一行)。free 是 kingbase 这类非 root 用户能用的量。它用 statfs 读磁盘,所以只有 kbdiag 跑在数据库主机上才有(见下面的“远程连接”)。
  • wal 是 sys_wal 的大小,旁边放着 max_wal_size 和 wal_keep_segments(写成它保留的大小:512 x 16 MB)。kbdiag 不对它下结论:max_wal_size 是软上限,PG12 通常会保留两者之和再加上最近一次检查点以来写的 WAL,只超过其中一个是常态。sys_wal 超过这个和时,文本会提示去看 kbdiag slots 和 kbdiag archive。这里 3248 MB 小于 1024 + 8192 MB。
  • databases 和 status 用的是同一个 probe,所以两处数字一致。
  • tablespaces 列出每个表空间和位置(默认的写 in data_directory)。

备库

~/kbdiag space
echo EXIT_CODE=$?
space  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:00+08:00)

disk: 1 filesystem
  holds                used   size    free    use
  data_directory, wal  13 GB  199 GB  186 GB  6%

wal: 198 files, 3136 MB
  max_wal_size       1024 MB
  wal_keep_segments  8192 MB  (512 x 16 MB)

databases: 5, total 438 MB
  test      381 MB
  esrep      15 MB
  mydb       14 MB
  security   14 MB
  kingbase   14 MB

tablespaces: 3
  name         location             size
  sys_default  (in data_directory)  467 MB
  sys_global   (in data_directory)  735 kB
  sysaudit     (in data_directory)  24 kB
EXIT_CODE=0

备库照同样的方式判断。它的 WAL 目录是自己的,所以文件数和大小和主库不同。

没有权限时

kbdiag_ro 没有监控角色。它走 127.0.0.1,这是 TCP(所以第一行写 kbdiag_ro@remote),但数据库就在本机,所以磁盘照样读得到:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro space
echo EXIT_CODE=$?
space  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:07+08:00)

disk: 1 filesystem
  holds                used   size    free    use
  data_directory, wal  15 GB  199 GB  184 GB  7%

wal: skipped  (insufficient_privilege 42501: permission denied for function sys_ls_waldir)

databases: 5, total 439 MB
  test      381 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

tablespaces: 3
  name         location             size
  sys_default  (in data_directory)  467 MB
  sys_global   (in data_directory)  ?
  sysaudit     (in data_directory)  ?
redacted: 2 rows of space.tablespaces hide size_bytes (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • wal: skipped:这个账号不能调 sys_ls_waldir,WAL 大小没采到。space 是纯展示的命令,只要有一个 probe 没采到,结论就是 UNKNOWN 而不是 OK:OK 只表示“都采到了”,这里没有。
  • 表空间表里的 ? 表示这个账号看不到那个大小(pg_tablespace_size(sys_global) 被拒绝)。kbdiag 把这个调用包在 CASE 里,所以只有那几格是 NULL,整条语句不会失败;这些格子记在 redacted 里。授予 sys_monitor 后两处都能解除。

远程连接

通过节点的网络地址连接时,数据目录可能在另一台机器上,所以 kbdiag 不读磁盘:

PGPASSWORD=... ~/kbdiag --host 192.168.105.10 -U kbdiag_ro space
echo EXIT_CODE=$?
space  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:10+08:00)

disk: not_applicable  (remote connection)

wal: skipped  (insufficient_privilege 42501: permission denied for function sys_ls_waldir)

databases: 5, total 439 MB
  test      381 MB
  esrep      15 MB
  mydb       14 MB
  kingbase   14 MB
  security   14 MB

tablespaces: 3
  name         location             size
  sys_default  (in data_directory)  467 MB
  sys_global   (in data_directory)  ?
  sysaudit     (in data_directory)  ?
redacted: 2 rows of space.tablespaces hide size_bytes (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • disk: not_applicable (remote connection)。只有确定跑在数据库主机上,kbdiag 才读磁盘:走 Unix socket,或者 host 是 localhost、127.0.0.1、::1 并且 data_directory 在本机存在。端口可能被转发到别的机器,所以只看主机名不够。
  • not_applicable 不是失败,但加上上面的权限缺口,这里结论同样是 UNKNOWN。

没有造出来的 FAIL

实验环境里没有造出来,下面按源码写:space.disk_full(FAIL)。数据目录或 WAL 目录所在的文件系统,可用空间不到一个 WAL 段(这里是 16 MB)时报。要造出它得真把数据盘填满,实验环境不做这个。

  • WAL 所在盘上建不出新段,旧段用完后实例会停;数据目录所在盘上,表、事务状态文件、临时文件马上长不了(报 ERROR,实例不停)。finding 会按实际情况分别写。
  • 严格说这是“马上就会受影响”,因为离失败只差一个段,没有余地再观察,所以报 FAIL。
  • 其他盘(表空间)满了,或者“少但还超过一个段”,因库而异,只展示。
  • 每个文件系统一条 finding。段大小来自 wal probe,采不到时(比如 kbdiag_ro)这条规则不判。

status 的 inst.disk 是数据目录那块盘的简短版本,只展示。

退出码

退出码含义
0OK
2FAIL:某个文件系统的可用空间不到一个 WAL 段(实验环境没造出来)
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

9 - freeze:事务号回卷距离

各库离事务号回卷还有多远,以及当前库最老的表。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。两个节点都是正常状态,没有注入故障,所以例子全是 OK。WARN 和 FAIL 在实验环境里没有造出来(见最后一节)。数值只属于本次采样。

用法

kbdiag freeze [--limit N] [--json]
参数作用
--limit N最多显示 N 张表;默认 20,0 表示全部
--json输出 JSON

连接参数和 sessions 相同。--limit 只裁表的列表,判定始终覆盖所有库和所有表。

主库,正常

~/kbdiag freeze
echo EXIT_CODE=$?
freeze  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:54+08:00)

limits
  autovacuum_freeze_max_age            200000000
  autovacuum_multixact_freeze_max_age  400000000
  xid stop limit                       2146483647  (new transaction IDs are refused)

databases: 7
  name       xid age  of freeze max  mxid age  xids left
  esrep      5672     0%             0         2146477975
  kingbase   5672     0%             0         2146477975
  mydb       5672     0%             0         2146477975
  security   5672     0%             0         2146477975
  template0  5672     0%             0         2146477975
  template1  5672     0%             0         2146477975
  test       5672     0%             0         2146477975

tables in test: 288, oldest first
  relation                                    kind   xid age  mxid age  heap (est.)
  information_schema.sql_features             table  5672     0         56 kB
  information_schema.sql_implementation_info  table  5672     0         8192 bytes
  information_schema.sql_languages            table  5672     0         8192 bytes
  information_schema.sql_packages             table  5672     0         8192 bytes
  information_schema.sql_parts                table  5672     0         8192 bytes
  information_schema.sql_sizing               table  5672     0         8192 bytes
  information_schema.sql_sizing_profiles      table  5672     0         0 bytes
  pg_catalog._agg                             table  5672     0         24 kB
  pg_catalog._am                              table  5672     0         8192 bytes
  pg_catalog._amop                            table  5672     0         80 kB
  pg_catalog._amproc                          table  5672     0         40 kB
  pg_catalog._anonpolicy                      table  5672     0         0 bytes
  pg_catalog._att                             table  5672     0         2024 kB
  pg_catalog._attdef                          table  5672     0         24 kB
  pg_catalog._audit_blocklog                  table  5672     0         0 bytes
  pg_catalog._audit_userlog                   table  5672     0         0 bytes
  pg_catalog._authid                          table  5672     0         8192 bytes
  pg_catalog._authmem                         table  5672     0         8192 bytes
  pg_catalog._cast                            table  5672     0         24 kB
  pg_catalog._ce_col                          table  5672     0         0 bytes
  ... 268 more not shown (--limit 0 shows all)
EXIT_CODE=0
  • limits 是 kbdiag 用来比较的两条线,都来自服务器:autovacuum_freeze_max_age(WARN 线:到这里 autovacuum 就必须强制冻结)和停止线(FAIL 线:服务器拒绝分配新的事务号,写事务会失败)。停止线是 PG12 内核的常数,xid 是回卷点(2^31 - 1)之前 100 万,multixact 是 100。kbdiag 没有自己编阈值。
  • databases 一库一行:xid age、mxid age 是这个库最老的未冻结 xid 和 multixact 的年龄,of freeze max 是 xid 年龄占 autovacuum_freeze_max_age 的百分比,xids left 是离停止线还能再分配多少个事务号。
  • 判定按库做。库的年龄就是它最老的表,逐表出 finding 会把同一个问题报几十遍。tables 只列当前连接的库,最老的在前;要看别的库用 kbdiag -d <库名> freeze。
  • heap (est.) 是 relpages x block_size 的估算。精确的大小函数要给每张表加锁,而救回卷时常有 VACUUM FULL、TRUNCATE,整条 probe 会卡到 lock_timeout 失败。
  • relfrozenxid 为 0 的表(比如 _kingbase_loginfo)不列:age(0) 会读成 2147483647,会误报 FAIL。
  • 备库上的年龄是复制过来的,和主库一样(kes-node2 上的实采输出,每个库都是 5672)。要修的话,VACUUM 仍然要到主库上跑。

二进制自己打印的参数说明:

~/kbdiag freeze --help
echo EXIT_CODE=$?
How far each database is from transaction ID wraparound; the oldest tables of this one

Usage:
  kbdiag freeze [flags]

Flags:
  -h, --help        help for freeze
      --limit int   max rows to show, 0 for all (findings still cover every row) (default 20)

Global Flags:
  -d, --dbname string      database to connect to (default "test")
      --host string        server host, or socket directory (default /tmp)
      --json               print the report as JSON
  -p, --port int           server port (default 54321)
      --timeout duration   statement timeout for each query (default 10s)
  -U, --user string        database user (password from PGPASSWORD or ~/.pgpass) (default "system")
EXIT_CODE=0

WARN 和 FAIL:实验环境没有造出来

两种 finding 都没有造出来,因为要把事务计数推到几亿个 xid。下面按源码写,不是实采;id 都是 freeze.database_age(kbdiag table 里是 freeze.table_age):

  • WARN:某个库的 xid 年龄达到 autovacuum_freeze_max_age,或 multixact 年龄达到 autovacuum_multixact_freeze_max_age。防回卷的 autovacuum 该跑了,或者跑不完。
  • FAIL:xid 年龄离回卷点不到 100 万(multixact 不到 100)。服务器拒绝分配新的事务号,写操作失败。
  • 下一步指向 kbdiag txn、kbdiag slots(谁压着视界)、别的库用 kbdiag -d <库名> freeze,以及在主库上跑的 VACUUM (FREEZE)。
  • 读不到参数时,FAIL 仍然能判(停止线是常数);年龄在停止线以下就是 UNKNOWN。

退出码

退出码含义
0OK
1WARN:超过 autovacuum_freeze_max_age(实验环境没造出来)
2FAIL:到了停止线(实验环境没造出来)
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

10 - vacuum:死元组和 autovacuum

哪些表死元组多、autovacuum 会不会去清、现在有没有 vacuum 在跑。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。WARN 的例子由注入脚本造出来:它建了表 public.kbdiag_inj_dead,设为 autovacuum_enabled=off,插入 10000 行再删掉 5000 行,所以表里有 5000 个没人会清的死元组。数值只属于本次采样。

用法

kbdiag vacuum [--limit N] [--json]
参数作用
--limit N最多显示 N 张表;默认 20,0 表示全部
--json输出 JSON

连接参数和 sessions 相同。--limit 只裁表的列表,判定覆盖所有表。vacuum 看的是当前连接的库(默认 test)。

主库,正常

~/kbdiag vacuum
echo EXIT_CODE=$?
vacuum  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:54+08:00)

settings
  autovacuum    on  (3 workers, naptime 1m 0s)
  track_counts  on
  threshold     50 + 0.2 x reltuples

running: 0

tables in test: 98, most dead tuples first
  table                             dead  live  threshold  due  autovacuum  last autovacuum  last vacuum
  sysmac.sysmac_policy              0     0     50.2       -    on          never            never
  sysmac.sysmac_level               0     0     50.8       -    on          never            never
  sysmac.sysmac_compartment         0     0     50         -    on          never            never
  sysmac.sysmac_label               0     0     50.8       -    on          never            never
  sysmac.sysmac_policy_enforcement  0     0     50         -    on          never            never
  sysmac.sysmac_user                0     0     50         -    on          never            never
  sysmac.sysmac_obj                 0     0     50         -    on          never            never
  sysmac.sysmac_column_label        0     0     50         -    on          never            never
  sys_hm.check_type                 0     0     50.4       -    on          never            never
  sys_hm.hm_run_t                   0     0     50         -    on          never            never
  sys_hm.check_param                0     0     50.2       -    on          never            never
  sys.dual                          0     0     50.2       -    on          never            never
  sys_catalog._kingbase_loginfo     0     0     50         -    on          never            never
  public.t1                         0     0     50         -    on          never            never
  public.t_perf_test                0     0     20050      -    on          never            never
  kdb_schedule.kdb_jobagent         0     0     50         -    on          never            never
  kdb_schedule.kdb_jobclass         0     0     50         -    on          never            never
  kdb_schedule.kdb_action           0     0     50         -    on          never            never
  kdb_schedule.kdb_schedule         0     0     50         -    on          never            never
  kdb_schedule.kdb_schedule_job     0     0     50         -    on          never            never
  ... 78 more not shown (--limit 0 shows all)
EXIT_CODE=0
  • settings 显示 autovacuum 和 track_counts 开没开、worker 数和 naptime,以及触发线公式(threshold 加上比例系数乘 reltuples)。
  • running 列出正在跑的 VACUUM 和进度(进度细节见 progress)。这里没有。
  • tables 按死元组数排序。threshold 是这张表的 autovacuum 触发线,算法和服务器一样(用 float4,表上的 reloptions 会覆盖全局值)。due 表示死元组是否过了这条线。autovacuum 是这张表自己的开关。
  • 列表按死元组数排序,最上面的行都是 0,所以没有表过线。每张表的 last autovacuum never 只说明统计重置以来 autovacuum 没轮到过它们。

备库

~/kbdiag vacuum
echo EXIT_CODE=$?
vacuum  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:01+08:00)

settings
  autovacuum    on  (3 workers, naptime 1m 0s)
  track_counts  on
  threshold     50 + 0.2 x reltuples

running: not_applicable  (standby: autovacuum does not run here; run on the primary)

tables in test: not_applicable  (standby: table statistics are local to each node and stay 0 here; run on the primary)
EXIT_CODE=0

表统计是节点本地的,备库上全是 0,autovacuum 也不在备库上跑,所以 running 和 tables 是 not_applicable,设置照样展示。要看 vacuum 到主库上跑。

没人会清的表

~/kbdiag vacuum
echo EXIT_CODE=$?
vacuum  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:12+08:00)

[WARN] vacuum.table_disabled  table public.kbdiag_inj_dead has 5000 dead tuples, past its autovacuum threshold 2050, but autovacuum is off for it (autovacuum_enabled=off): nothing will clean it
  fix: VACUUM public.kbdiag_inj_dead  # connected to database test; turn autovacuum back on with ALTER TABLE ... RESET (autovacuum_enabled) unless it was turned off on purpose
  verify: kbdiag txn  # if dead tuples remain after VACUUM: the oldest transaction holding back the horizon
  verify: kbdiag slots  # or a replication slot's xmin

settings
  autovacuum    on  (3 workers, naptime 1m 0s)
  track_counts  on
  threshold     50 + 0.2 x reltuples

running: 0

tables in test: 99, most dead tuples first
  table                             dead  live  threshold  due  autovacuum  last autovacuum  last vacuum
  public.kbdiag_inj_dead            5000  5000  2050       yes  off         never            never
  sysmac.sysmac_policy              0     0     50.2       -    on          never            never
  sysmac.sysmac_level               0     0     50.8       -    on          never            never
  sysmac.sysmac_compartment         0     0     50         -    on          never            never
  sysmac.sysmac_label               0     0     50.8       -    on          never            never
  sysmac.sysmac_policy_enforcement  0     0     50         -    on          never            never
  sysmac.sysmac_user                0     0     50         -    on          never            never
  sysmac.sysmac_obj                 0     0     50         -    on          never            never
  sysmac.sysmac_column_label        0     0     50         -    on          never            never
  sys_hm.check_type                 0     0     50.4       -    on          never            never
  sys_hm.hm_run_t                   0     0     50         -    on          never            never
  sys_hm.check_param                0     0     50.2       -    on          never            never
  sys.dual                          0     0     50.2       -    on          never            never
  sys_catalog._kingbase_loginfo     0     0     50         -    on          never            never
  public.t1                         0     0     50         -    on          never            never
  public.t_perf_test                0     0     20050      -    on          never            never
  kdb_schedule.kdb_jobagent         0     0     50         -    on          never            never
  kdb_schedule.kdb_jobclass         0     0     50         -    on          never            never
  kdb_schedule.kdb_action           0     0     50         -    on          never            never
  kdb_schedule.kdb_schedule         0     0     50         -    on          never            never
  ... 79 more not shown (--limit 0 shows all)
EXIT_CODE=1
  • finding 是 vacuum.table_disabled:这张表有 5000 个死元组,超过触发线 2050,但表自己设了 autovacuum_enabled=off,autovacuum 永远不会清它。表里 due 是 yes,autovacuum 是 off。
  • 它是 WARN:死元组以后会造成膨胀,但现在什么都没坏。fix 是对这张表跑 VACUUM(名字需要时按 quote_ident 加引号);跑完死元组还在,说明有东西压着视界,两条 verify(kbdiag txn、kbdiag slots)就是去找它。
  • autovacuum 开着、只是过了线的表不报。那是 autovacuum 的正常队列,每个 naptime 轮一次;“等太久”需要一条时间线,而它没有客观的值。只在表里标 due。
  • 这条命令的另一个 finding vacuum.disabled(WARN)在实验环境里没有造出来,下面按源码写:autovacuum 或 track_counts 关了,除了防回卷的 vacuum 以外,没有表会被自动清理。fix 是 ALTER SYSTEM SET <那个开关> = on,再 reload。
  • track_counts 关着时表的 probe 是 skipped:计数器停了,旧值不能当成现在的。

同一张表在 table 命令里怎么显示,见那一页。

退出码

退出码含义
0OK
1WARN
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

11 - archive:WAL 归档

归档是不是在正常工作:设置、最后一次成功和失败、等着归档的 WAL。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。没有注入故障。主库的 WAL 归档在实验环境里本来就在失败(archive_command 调 sys_rman archive-push,最后一次成功在 21 天前),所以下面的 WARN 就是实验环境的真实状态;失败原因这一页没有去查,因为 kbdiag 不读服务器日志。数值只属于本次采样。

用法

kbdiag archive [--json]

没有自己的参数。连接参数和 sessions 相同。

主库:归档在失败

~/kbdiag archive
echo EXIT_CODE=$?
archive  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:55+08:00)

[WARN] archive.failing  archiving is failing: the last attempt failed (0000000300000000000000A3, 6s ago) and the last success was 21d 3h ago (0000000300000000000000A2); 22590 failures since the statistics reset. WAL that is not archived stays in sys_wal and is missing from the backups
  verify: kbdiag space  # how big sys_wal has grown; why archive_command fails is in the server log (log_directory)

settings
  archive_mode     always
  archive_command  export TZ=Asia/Shanghai;/home/kingbase/cluster/install/kingbase/bin/sys_rman --config /rman/kbbr_repo/sys_rman.conf --stanza=kingbase archive-push %p
  archive_timeout  0 (off)

archiver  (counting since 2026-09-15 23:12:34)
  archived  35     last 0000000300000000000000A2  21d 3h ago
  failed    22590  last 0000000300000000000000A3  6s ago

waiting: 38 .ready, 174 .done  (oldest .ready 21d 3h)
EXIT_CODE=1
  • archive.failing(WARN)的线是“最后一次尝试失败了”:最后一次失败晚于最后一次成功,或者从没成功过。没归档的 WAL 会留在 sys_wal,备份里缺这几段,但业务照常,所以是 WARN。
  • settings 显示 archive_mode、archive_command 和 archive_timeout。kbdiag 先排除主动配置的情况:archive_mode=off 不判;备库上 archive_mode=on 也不判,因为备库只有 always 才归档。
  • archiver 是服务器的归档统计,从统计重置时间开始算:成功和失败各多少次,各自最后一个 WAL 文件和多久前。
  • waiting 数 .ready(等着归档的 WAL)和 .done 文件,以及最老的 .ready 等了多久。它只展示,不能影响结论。
  • verify 指向 kbdiag space(看 sys_wal 撑到多大)。命令为什么失败,只在服务器日志(log_directory)里有。
  • archive_command 为空不判:PostgreSQL 文档说这时 WAL 会一直留着,但 KingbaseES 上没核实,文本只写 (empty)。

备库

~/kbdiag archive
echo EXIT_CODE=$?
archive  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:02+08:00)

settings
  archive_mode     always
  archive_command  export TZ=Asia/Shanghai;/home/kingbase/cluster/install/kingbase/bin/sys_rman --config /rman/kbbr_repo/sys_rman.conf --stanza=kingbase archive-push %p
  archive_timeout  0 (off)

archiver  (counting since 2026-10-07 16:49:26)
  archived  38  last 0000000300000000000000C8  2m 17s ago
  failed    0

waiting: 0 .ready, 212 .done
EXIT_CODE=0

备库是 archive_mode=always,所以它也归档。它从自己启动时开始计数,这里成功、没有积压,所以是 OK。

没有权限时

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro archive
echo EXIT_CODE=$?
archive  WARN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:09+08:00)

[WARN] archive.failing  archiving is failing: the last attempt failed (0000000300000000000000A3, 20s ago) and the last success was 21d 3h ago (0000000300000000000000A2); 22590 failures since the statistics reset. WAL that is not archived stays in sys_wal and is missing from the backups
  verify: kbdiag space  # how big sys_wal has grown; why archive_command fails is in the server log (log_directory)

settings
  archive_mode     always
  archive_command  export TZ=Asia/Shanghai;/home/kingbase/cluster/install/kingbase/bin/sys_rman --config /rman/kbbr_repo/sys_rman.conf --stanza=kingbase archive-push %p
  archive_timeout  0 (off)

archiver  (counting since 2026-09-15 23:12:34)
  archived  35     last 0000000300000000000000A2  21d 3h ago
  failed    22590  last 0000000300000000000000A3  20s ago

waiting: skipped  (insufficient_privilege 42501: permission denied for function sys_ls_archive_statusdir)
EXIT_CODE=1

kbdiag_ro 不能调 sys_ls_archive_statusdir,所以 waiting 是 skipped。这个 probe 只展示,不允许影响结论。finding 本身来自统计视图,这个账号读得到。

退出码

退出码含义
0OK
1WARN:最后一次归档失败
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

12 - params:改过的参数

哪些参数不是默认值、在哪设的;改了要重启才生效的报 WARN。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。WARN 的例子由注入脚本造出来:它用 ALTER SYSTEM 改了 max_files_per_process(需要重启的参数),reload 了配置,没有重启,所以运行值和文件里的不一样。数值只属于本次采样。

用法

kbdiag params [--json]

没有自己的参数,也没有按名字过滤:看单个参数用 ksql -c 'show x',或者 --json 配 jq。连接参数和 sessions 相同。

主库,正常

~/kbdiag params
echo EXIT_CODE=$?
params  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:55+08:00)

pending restart: 0

changed: 63 parameters not at their default (sources other than default, override and this connection)
  this connection sets application_name, default_transaction_read_only, lock_timeout and statement_timeout itself, so their configured values are not shown; per-role and per-database settings show only for this role and database
  name                          setting                                                       unit  source              file
  archive_command               export TZ=Asia/Shanghai;/home/kingbase/cluster/install/ki...  -     configuration file  es_rep.conf:10
  archive_mode                  always                                                        -     configuration file  es_rep.conf:9
  control_file_copy             /home/kingbase/cluster/install/kingbase/copy_file             -     configuration file  es_rep.conf:11
  DateStyle                     ISO, MDY                                                      -     configuration file  kingbase.conf:654
  default_text_search_config    pg_catalog.english                                            -     configuration file  kingbase.conf:676
  dynamic_shared_memory_type    posix                                                         -     configuration file  kingbase.conf:140
  fsync                         on                                                            -     configuration file  es_rep.conf:23
  full_page_writes              on                                                            -     configuration file  es_rep.conf:3
  hot_standby                   on                                                            -     configuration file  es_rep.conf:13
  hot_standby_feedback          on                                                            -     configuration file  es_rep.conf:14
  lc_messages                   C                                                             -     configuration file  kingbase.conf:669
  lc_monetary                   en_US.UTF-8                                                   -     configuration file  kingbase.conf:671
  lc_numeric                    en_US.UTF-8                                                   -     configuration file  kingbase.conf:672
  lc_time                       en_US.UTF-8                                                   -     configuration file  kingbase.conf:673
  listen_addresses              *                                                             -     configuration file  es_rep.conf:1
  log_autovacuum_min_duration   0                                                             ms    configuration file  es_rep.conf:40
  log_checkpoints               on                                                            -     configuration file  es_rep.conf:38
  log_connections               on                                                            -     configuration file  es_rep.conf:32
  log_destination               stderr                                                        -     configuration file  es_rep.conf:44
  log_directory                 sys_log                                                       -     configuration file  kingbase.conf:432
  log_disconnections            on                                                            -     configuration file  es_rep.conf:33
  log_filename                  kingbase-%d.log                                               -     configuration file  es_rep.conf:43
  logging_collector             on                                                            -     configuration file  es_rep.conf:15
  log_line_prefix               %t [%p]: [%l-1] [%x] user=%u,db=%d,app=%a,client=%h           -     configuration file  es_rep.conf:42
  log_lock_waits                on                                                            -     configuration file  es_rep.conf:39
  log_min_duration_statement    1000                                                          ms    configuration file  es_rep.conf:47
  log_replication_commands      on                                                            -     configuration file  es_rep.conf:18
  log_rotation_age              1440                                                          min   configuration file  es_rep.conf:46
  log_statement                 ddl                                                           -     configuration file  es_rep.conf:36
  log_temp_files                0                                                             kB    configuration file  es_rep.conf:41
  log_timezone                  Asia/Shanghai                                                 -     configuration file  kingbase.conf:540
  log_truncate_on_rotation      on                                                            -     configuration file  es_rep.conf:45
  max_connections               100                                                           -     configuration file  es_rep.conf:7
  max_prepared_transactions     100                                                           -     configuration file  es_rep.conf:21
  max_replication_slots         32                                                            -     configuration file  es_rep.conf:12
  max_stack_depth               3072                                                          kB    configuration file  kingbase.conf:133
  max_wal_senders               32                                                            -     configuration file  es_rep.conf:5
  max_wal_size                  1024                                                          MB    configuration file  kingbase.conf:224
  min_wal_size                  80                                                            MB    configuration file  kingbase.conf:225
  ora_input_emptystr_isnull     on                                                            -     configuration file  kingbase.conf:767
  ora_integer_div_returnfloat   on                                                            -     configuration file  kingbase.conf:768
  password_encryption           scram-sha-256                                                 -     configuration file  kingbase.conf:91
  port                          54321                                                         -     configuration file  es_rep.conf:2
  primary_conninfo              user=esrep connect_timeout=10 host=192.168.105.11 port=54...  -     configuration file  kingbase.auto.conf:3
  primary_slot_name             repmgr_slot_1                                                 -     configuration file  kingbase.auto.conf:4
  shared_buffers                65536                                                         8kB   configuration file  es_rep.conf:22
  shared_preload_libraries      repmgr, synonym, plsql, force_view, kdb_flashback,plugin_...  -     configuration file  kingbase.conf:766
  synchronous_commit            remote_apply                                                  -     configuration file  es_rep.conf:20
  synchronous_standby_names     ANY 1( node2)                                                 -     configuration file  kingbase.auto.conf:7
  sys_stat_statements.track     none                                                          -     configuration file  kingbase.auto.conf:5
  tcp_keepalives_count          0                                                             -     configuration file  es_rep.conf:27
  tcp_keepalives_idle           0                                                             s     configuration file  es_rep.conf:25
  tcp_keepalives_interval       0                                                             s     configuration file  es_rep.conf:26
  tcp_user_timeout              0                                                             ms    configuration file  es_rep.conf:28
  TimeZone                      PRC                                                           -     configuration file  es_rep.conf:24
  track_real_stats              on                                                            -     configuration file  kingbase.auto.conf:6
  wal_compression               on                                                            -     configuration file  es_rep.conf:19
  wal_keep_segments             512                                                           -     configuration file  es_rep.conf:6
  wal_level                     replica                                                       -     configuration file  es_rep.conf:8
  wal_log_hints                 on                                                            -     configuration file  es_rep.conf:4
  wal_receiver_status_interval  2                                                             s     configuration file  kingbase.conf:323
  wal_receiver_timeout          30000                                                         ms    configuration file  es_rep.conf:30
  wal_sender_timeout            30000                                                         ms    configuration file  es_rep.conf:29
EXIT_CODE=0
  • pending restart 列出文件里的值和正在运行的值不同的参数(服务器自己的 pending_restart 标志)。这里没有。
  • changed 只列有人设过的参数:来源不是 default、override(编译或 initdb 定的)以及本连接自己的 client/session(那是 kbdiag 自己设的,列出来是噪声)。file 是设置它的文件和行号。
  • changed 下面那行说明看不全的两处。kbdiag 连接时自己设了 application_name、default_transaction_read_only、lock_timeout、statement_timeout,所以它们的配置值看不到;按角色、按库的设置只看得到当前角色和库的。
  • archive_command 这类长值会用 ... 截断;--json 里是完整的。
  • 备库上的列表类似,primary_conninfo、primary_slot_name、synchronous_standby_names 不同(kes-node2 上实采,同样是 63 个参数)。

没有权限时

kbdiag_ro(没有监控角色,走 127.0.0.1):

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro params
echo EXIT_CODE=$?
params  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:08+08:00)

pending restart: 0

changed: 59 parameters not at their default (sources other than default, override and this connection)
  this connection sets application_name, default_transaction_read_only, lock_timeout and statement_timeout itself, so their configured values are not shown; per-role and per-database settings show only for this role and database
  name                          setting                                                       unit  source              file
  archive_command               export TZ=Asia/Shanghai;/home/kingbase/cluster/install/ki...  -     configuration file  ?
  archive_mode                  always                                                        -     configuration file  ?
  control_file_copy             /home/kingbase/cluster/install/kingbase/copy_file             -     configuration file  ?
  DateStyle                     ISO, MDY                                                      -     configuration file  ?
  default_text_search_config    pg_catalog.english                                            -     configuration file  ?
  dynamic_shared_memory_type    posix                                                         -     configuration file  ?
  fsync                         on                                                            -     configuration file  ?
  full_page_writes              on                                                            -     configuration file  ?
  hot_standby                   on                                                            -     configuration file  ?
  hot_standby_feedback          on                                                            -     configuration file  ?
  lc_messages                   C                                                             -     configuration file  ?
  lc_monetary                   en_US.UTF-8                                                   -     configuration file  ?
  lc_numeric                    en_US.UTF-8                                                   -     configuration file  ?
  lc_time                       en_US.UTF-8                                                   -     configuration file  ?
  listen_addresses              *                                                             -     configuration file  ?
  log_autovacuum_min_duration   0                                                             ms    configuration file  ?
  log_checkpoints               on                                                            -     configuration file  ?
  log_connections               on                                                            -     configuration file  ?
  log_destination               stderr                                                        -     configuration file  ?
  log_disconnections            on                                                            -     configuration file  ?
  logging_collector             on                                                            -     configuration file  ?
  log_line_prefix               %t [%p]: [%l-1] [%x] user=%u,db=%d,app=%a,client=%h           -     configuration file  ?
  log_lock_waits                on                                                            -     configuration file  ?
  log_min_duration_statement    1000                                                          ms    configuration file  ?
  log_replication_commands      on                                                            -     configuration file  ?
  log_rotation_age              1440                                                          min   configuration file  ?
  log_statement                 ddl                                                           -     configuration file  ?
  log_temp_files                0                                                             kB    configuration file  ?
  log_timezone                  Asia/Shanghai                                                 -     configuration file  ?
  log_truncate_on_rotation      on                                                            -     configuration file  ?
  max_connections               100                                                           -     configuration file  ?
  max_prepared_transactions     100                                                           -     configuration file  ?
  max_replication_slots         32                                                            -     configuration file  ?
  max_stack_depth               3072                                                          kB    configuration file  ?
  max_wal_senders               32                                                            -     configuration file  ?
  max_wal_size                  1024                                                          MB    configuration file  ?
  min_wal_size                  80                                                            MB    configuration file  ?
  ora_input_emptystr_isnull     on                                                            -     configuration file  ?
  ora_integer_div_returnfloat   on                                                            -     configuration file  ?
  password_encryption           scram-sha-256                                                 -     configuration file  ?
  port                          54321                                                         -     configuration file  ?
  primary_slot_name             repmgr_slot_1                                                 -     configuration file  ?
  shared_buffers                65536                                                         8kB   configuration file  ?
  synchronous_commit            remote_apply                                                  -     configuration file  ?
  synchronous_standby_names     ANY 1( node2)                                                 -     configuration file  ?
  sys_stat_statements.track     none                                                          -     configuration file  ?
  tcp_keepalives_count          3                                                             -     configuration file  ?
  tcp_keepalives_idle           2                                                             s     configuration file  ?
  tcp_keepalives_interval       2                                                             s     configuration file  ?
  tcp_user_timeout              9000                                                          ms    configuration file  ?
  TimeZone                      PRC                                                           -     configuration file  ?
  track_real_stats              on                                                            -     configuration file  ?
  wal_compression               on                                                            -     configuration file  ?
  wal_keep_segments             512                                                           -     configuration file  ?
  wal_level                     replica                                                       -     configuration file  ?
  wal_log_hints                 on                                                            -     configuration file  ?
  wal_receiver_status_interval  2                                                             s     configuration file  ?
  wal_receiver_timeout          30000                                                         ms    configuration file  ?
  wal_sender_timeout            30000                                                         ms    configuration file  ?
  only the parameters this account may read: superuser-only ones are not listed
redacted: 59 rows of params.changed hide sourcefile, sourceline (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3
  • file 是 ?:这个账号看不到 sourcefile 和 sourceline,记在 redacted 里。
  • 列表更短(59 个,不是 63 个),因为超级用户专属的参数这个账号根本看不到,最后一行说明了这点。这些参数的 pending_restart 也就看不到,所以没有 finding 时结论是 UNKNOWN:看不到的东西,kbdiag 不说 OK。

改了还没生效

~/kbdiag params
echo EXIT_CODE=$?
params  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:15+08:00)

[WARN] params.pending_restart  parameter max_files_per_process was changed but the instance still runs with 1000: the new value takes effect only after a restart, the next one included
  verify: select sourcefile, sourceline, setting, applied, error from sys_file_settings where name = 'max_files_per_process'  # the value waiting in the file (needs a superuser)
  fix: ALTER SYSTEM SET max_files_per_process = '1000'  # if the change was not meant: writes the running value back; after SELECT sys_reload_conf() the flag clears (a reload clears it only when the file's value equals the running one, so ALTER SYSTEM RESET alone leaves it until a restart). Otherwise plan the restart

pending restart: 1
  name                   running  file
  max_files_per_process  1000     -

changed: 64 parameters not at their default (sources other than default, override and this connection)
  this connection sets application_name, default_transaction_read_only, lock_timeout and statement_timeout itself, so their configured values are not shown; per-role and per-database settings show only for this role and database
  name                          setting                                                       unit  source              file
  archive_command               export TZ=Asia/Shanghai;/home/kingbase/cluster/install/ki...  -     configuration file  es_rep.conf:10
  archive_mode                  always                                                        -     configuration file  es_rep.conf:9
  control_file_copy             /home/kingbase/cluster/install/kingbase/copy_file             -     configuration file  es_rep.conf:11
  DateStyle                     ISO, MDY                                                      -     configuration file  kingbase.conf:654
  default_text_search_config    pg_catalog.english                                            -     configuration file  kingbase.conf:676
  dynamic_shared_memory_type    posix                                                         -     configuration file  kingbase.conf:140
  fsync                         on                                                            -     configuration file  es_rep.conf:23
  full_page_writes              on                                                            -     configuration file  es_rep.conf:3
  hot_standby                   on                                                            -     configuration file  es_rep.conf:13
  hot_standby_feedback          on                                                            -     configuration file  es_rep.conf:14
  lc_messages                   C                                                             -     configuration file  kingbase.conf:669
  lc_monetary                   en_US.UTF-8                                                   -     configuration file  kingbase.conf:671
  lc_numeric                    en_US.UTF-8                                                   -     configuration file  kingbase.conf:672
  lc_time                       en_US.UTF-8                                                   -     configuration file  kingbase.conf:673
  listen_addresses              *                                                             -     configuration file  es_rep.conf:1
  log_autovacuum_min_duration   0                                                             ms    configuration file  es_rep.conf:40
  log_checkpoints               on                                                            -     configuration file  es_rep.conf:38
  log_connections               on                                                            -     configuration file  es_rep.conf:32
  log_destination               stderr                                                        -     configuration file  es_rep.conf:44
  log_directory                 sys_log                                                       -     configuration file  kingbase.conf:432
  log_disconnections            on                                                            -     configuration file  es_rep.conf:33
  log_filename                  kingbase-%d.log                                               -     configuration file  es_rep.conf:43
  logging_collector             on                                                            -     configuration file  es_rep.conf:15
  log_line_prefix               %t [%p]: [%l-1] [%x] user=%u,db=%d,app=%a,client=%h           -     configuration file  es_rep.conf:42
  log_lock_waits                on                                                            -     configuration file  es_rep.conf:39
  log_min_duration_statement    1000                                                          ms    configuration file  es_rep.conf:47
  log_replication_commands      on                                                            -     configuration file  es_rep.conf:18
  log_rotation_age              1440                                                          min   configuration file  es_rep.conf:46
  log_statement                 ddl                                                           -     configuration file  es_rep.conf:36
  log_temp_files                0                                                             kB    configuration file  es_rep.conf:41
  log_timezone                  Asia/Shanghai                                                 -     configuration file  kingbase.conf:540
  log_truncate_on_rotation      on                                                            -     configuration file  es_rep.conf:45
  max_connections               100                                                           -     configuration file  es_rep.conf:7
  max_files_per_process         1000                                                          -     default             -
  max_prepared_transactions     100                                                           -     configuration file  es_rep.conf:21
  max_replication_slots         32                                                            -     configuration file  es_rep.conf:12
  max_stack_depth               3072                                                          kB    configuration file  kingbase.conf:133
  max_wal_senders               32                                                            -     configuration file  es_rep.conf:5
  max_wal_size                  1024                                                          MB    configuration file  kingbase.conf:224
  min_wal_size                  80                                                            MB    configuration file  kingbase.conf:225
  ora_input_emptystr_isnull     on                                                            -     configuration file  kingbase.conf:767
  ora_integer_div_returnfloat   on                                                            -     configuration file  kingbase.conf:768
  password_encryption           scram-sha-256                                                 -     configuration file  kingbase.conf:91
  port                          54321                                                         -     configuration file  es_rep.conf:2
  primary_conninfo              user=esrep connect_timeout=10 host=192.168.105.11 port=54...  -     configuration file  kingbase.auto.conf:3
  primary_slot_name             repmgr_slot_1                                                 -     configuration file  kingbase.auto.conf:4
  shared_buffers                65536                                                         8kB   configuration file  es_rep.conf:22
  shared_preload_libraries      repmgr, synonym, plsql, force_view, kdb_flashback,plugin_...  -     configuration file  kingbase.conf:766
  synchronous_commit            remote_apply                                                  -     configuration file  es_rep.conf:20
  synchronous_standby_names     ANY 1( node2)                                                 -     configuration file  kingbase.auto.conf:7
  sys_stat_statements.track     none                                                          -     configuration file  kingbase.auto.conf:5
  tcp_keepalives_count          0                                                             -     configuration file  es_rep.conf:27
  tcp_keepalives_idle           0                                                             s     configuration file  es_rep.conf:25
  tcp_keepalives_interval       0                                                             s     configuration file  es_rep.conf:26
  tcp_user_timeout              0                                                             ms    configuration file  es_rep.conf:28
  TimeZone                      PRC                                                           -     configuration file  es_rep.conf:24
  track_real_stats              on                                                            -     configuration file  kingbase.auto.conf:6
  wal_compression               on                                                            -     configuration file  es_rep.conf:19
  wal_keep_segments             512                                                           -     configuration file  es_rep.conf:6
  wal_level                     replica                                                       -     configuration file  es_rep.conf:8
  wal_log_hints                 on                                                            -     configuration file  es_rep.conf:4
  wal_receiver_status_interval  2                                                             s     configuration file  kingbase.conf:323
  wal_receiver_timeout          30000                                                         ms    configuration file  es_rep.conf:30
  wal_sender_timeout            30000                                                         ms    configuration file  es_rep.conf:29
EXIT_CODE=1
  • params.pending_restart 是 WARN,每个参数一条,线就是服务器自己的 pending_restart 标志。现在业务没受影响:实例还在跑旧值。但下一次重启(包括故障切换后的重启)会突然换成新值。
  • pending restart 里显示的是运行值;文件里等着的值这里显示 -。verify 给了一条查询(sys_file_settings,需要超级用户)。
  • fix 是把运行值写回去:ALTER SYSTEM SET x = '<运行值>',再 SELECT sys_reload_conf()。PostgreSQL 12 的 reload 只在文件里的值等于运行值时才清掉 pending 标志,只做 ALTER SYSTEM RESET 会一直挂到下次重启。如果这个改动是有意的,就该去安排重启。
  • max_files_per_process 在 changed 里来源是 default:等着重启的参数不管来源都会列出,因为改了之后它的来源仍然读成 default。
  • 配置文件有错(sys_file_settings.error)这一项没做:kbdiag_ro 读不了那个视图。

退出码

退出码含义
0OK
1WARN:有参数改了要重启才生效
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

13 - repl:本节点看复制

从本节点看复制:主库看同步设置和每个备库落后多少;备库看上游、接收和回放。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。WARN 的例子由故障注入脚本造出来:它暂停(SIGSTOP)备库的 WAL 接收进程,和 slots 页用的是同一个。数值只属于本次采样。

用法

kbdiag repl [--json]

没有自己的参数。连接参数和 sessions 相同。

主库

~/kbdiag repl
echo EXIT_CODE=$?
repl  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:56+08:00)

sync
  synchronous_standby_names  ANY 1( node2)  (any 1 of node2 must confirm)
  synchronous_commit         remote_apply
  synchronous now            1 (node2)

downstreams: 1  (bytes behind this node's current WAL position)
  name   address         state      sync    sent     flushed  replayed  replay lag  last reply
  node2  192.168.105.11  streaming  quorum  0 bytes  0 bytes  0 bytes   0s          1s ago
EXIT_CODE=0
  • sync 显示 synchronous_standby_names 和它的含义(any 1 of node2 must confirm)、synchronous_commit,以及服务器现在把几个备库算作同步的。sync 列里的 quorum 是服务器自己的 sync_state;repmgr 下实测就是 quorum,不是 sync 或 async,所以 kbdiag 不翻译。
  • downstreams 一个备库一行:发送、刷盘、回放到哪(写成落后本节点当前 WAL 位置的字节数),回放延迟的时间(备库追平且空闲时为空),以及多久前最后一次回复。
  • 延迟只展示,不判:服务器上没有客观线。

备库

~/kbdiag repl
echo EXIT_CODE=$?
repl  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:03+08:00)

upstream
  status    streaming
  upstream  192.168.105.10:54321
  slot      repmgr_slot_2
  last_msg  3s ago

replay
  received                   0/C9352A80
  replayed                   0/C9352A80  (caught up with what was received)
  last replayed transaction  1m 0s ago
  paused                     no

downstreams: 0
EXIT_CODE=0
  • upstream 和 kbdiag status 里的 inst.upstream 是同一个 WAL 接收进程视图,last_msg 是离主库最后一条消息多久。
  • replay 对比收到的和回放的。caught up with what was received 表示两个位置相等。last replayed transaction 1m 0s ago 不是延迟:空闲的主库上它能读到好几个小时而位置完全一致,所以 kbdiag 不把它当成延迟。
  • paused 是回放有没有被 sys_wal_replay_pause() 暂停。

WAL 接收进程卡住

备库的接收进程被暂停后,备库上报:

~/kbdiag repl
echo EXIT_CODE=$?
repl  WARN  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:22:58+08:00)

[WARN] inst.upstream  the standby's WAL receiver shows streaming, but nothing has come from the primary for 1m 12s, longer than wal_receiver_timeout (30s), after which a working receiver reconnects: it is stuck (stopped or blocked), so it is not receiving WAL: if the primary fails now, no standby can take over
  verify: kbdiag slots  # run on the primary: is this standby's slot inactive?

upstream
  status    streaming
  upstream  192.168.105.10:54321
  slot      repmgr_slot_2
  last_msg  1m 12s ago

replay
  received                   0/CCCC9228
  replayed                   0/CCCC9228  (caught up with what was received)
  last replayed transaction  1m 12s ago
  paused                     no

downstreams: 0
EXIT_CODE=1
  • finding 是 inst.upstream,和 kbdiag status 用的是同一条规则:接收进程写 streaming,但 last_msg 比 wal_receiver_timeout(实验环境 30 秒)还老。正常的接收进程在超时的一半时就会向主库要回复,满了就断开重连,所以只有卡住的会越过这条线。没有接收进程、或者状态不是 streaming 时,同一条 finding 也会报。
  • received 和 replayed 仍然相等:什么都没来,也就没什么可回放。是最后一条消息的年龄暴露了问题。
  • 已知的边界:接收进程在连接开始时就把收到时间设成当时,所以连接慢于超时一半、或时间线切换,可能短暂报一次。不加余量是故意的,因为余量没有客观来源。

同一时刻的主库:

~/kbdiag repl
echo EXIT_CODE=$?
repl  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:22:56+08:00)

sync
  synchronous_standby_names  (none: asynchronous only)
  synchronous_commit         remote_apply

downstreams: 0
EXIT_CODE=0
  • downstreams 里没有备库了(0),synchronous_standby_names 现在读成 (none: asynchronous only),注入前是 ANY 1( node2)。所以 repl.sync_short 没有触发。kbdiag 显示的是服务器当前的值;注入期间这个设置是 repmgr 改的:repmgr.conf 里是 synchronous='quorum' 时,备库断开约 2 秒后 repmgrd 会把 synchronous_standby_names 清空,降成异步提交,备库重连后再改回来(2026-09-28 实验环境 hamgr.log 里看到的)。这是 repmgr 做的,不是 KingbaseES 内核的行为。所以在这种集群上 repl.sync_short 只会在那一两秒里出现,备库丢了之后更常见的是"已经是异步了",repl 显示为 (none: asynchronous only)。
  • 到主库上跑 slots 看槽变成不活跃,跑 cluster 看 repmgr 的看法。

实验环境没有造出来的 WARN

按源码写,不是实采:

  • repl.replay_paused(WARN):备库上回放被暂停(sys_wal_replay_pause())。查询照常,但越落越远,故障切换时得先回放完收到的全部。除非是有意暂停,fix 是 SELECT sys_wal_replay_resume()。实验环境没有这个注入:在那里暂停回放会卡住主库的所有提交(synchronous_commit 是 remote_apply)。
  • repl.sync_short(WARN):synchronous_standby_names 要的备库数比服务器算作同步候选(sync 或 quorum)的多。文本说提交要么在等,要么已经不等了,同步副本没有保证。它是 WARN 不是 FAIL,因为实验环境里备库断开后同步提交照样过去了(repmgr 已经降成异步,见上)。kbdiag 数服务器给的 sync_state,不自己重算候选规则,并且只在 synchronous_commit 让提交等备库时才判(这是本连接的值,按角色或按库另设的看不到)。

退出码

退出码含义
0OK
1WARN:没在收 WAL、回放暂停,或同步备库不够数
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

14 - cluster:repmgr 眼里的集群

repmgr 眼里的集群(节点、角色、上游、最近事件),和本节点对照。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。集群由 repmgr 管理,元数据在 esrep 库里。WARN 的例子由故障注入脚本造出来:它暂停(SIGSTOP)备库的 WAL 接收进程,直到备库不再挂在主库上,和 slots 页用的是同一个。数值只属于本次采样。

用法

kbdiag cluster [--json]

没有自己的参数。连接参数和 sessions 相同,只有一处不同:没给 -d 时,cluster 连 esrep 库,repmgr 的元数据在那里。kbdiag 只占一个连接,不会为它再开第二个。没有 esrep 库时退回默认库(不给 69,69 只表示连不上实例)。它不调 repmgr 的二进制,所以 repmgr cluster show 里逐个连节点的 Status 列做不了。

主库

~/kbdiag cluster
echo EXIT_CODE=$?
cluster  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:56+08:00)

nodes: 2  (repmgr metadata in database esrep)
  id  name   type     upstream  active  priority  location  slot
  1   node1  primary  -         yes     100       default   repmgr_slot_1
  2   node2  standby  node1     yes     100       default   repmgr_slot_2
  this node is node1: repmgr says primary, the database is a primary
  attached here: node2

events: 20  (the latest, at most 20)
  time                 node   event                   ok   details
  2026-10-07 17:20:02  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:20:01  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:20:01  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:19:18  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:12:14  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-10-07 17:12:08  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:01:21  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:01:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:01:19  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:00:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 16:49:31  node1  child_node_new_connect  yes  new standby "node2" (ID: 2) has connected
  2026-10-07 16:49:28  node2  repmgrd_start           yes  monitoring connection to upstream node "node1" (ID: 1)
  2026-10-07 16:49:26  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 16:49:26  node2  node_rejoin             yes  node 2 is now attached to node 1
  2026-10-07 16:48:36  node1  repmgrd_start           yes  monitoring cluster primary "node1" (ID: 1)
  2026-09-29 20:06:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 8 seconds
  2026-09-29 20:06:13  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-09-29 19:22:45  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-09-29 19:22:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-09-28 15:42:40  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 106 seconds
EXIT_CODE=0
  • nodes 是 repmgr 的节点表:类型、上游、active、优先级、位置和复制槽。文本标出本节点是哪一个:先问 repmgr 的 get_local_node_id(),没有再按 primary_slot_name(repmgr_slot_N)认。认不出时不做角色对照,结论也不会是 OK。
  • this node is node1: repmgr says primary, the database is a primary 这一行就是 repmgr 元数据和数据库自己看法的对照。attached here: node2 是 repmgr 说跟着本节点的备库里、这里真有 walsender 的那些。
  • events 是 repmgr 最近 20 条事件。里面的断开、重连是这个实验环境之前几轮测试留下的。
  • 节点是不是活着、repmgrd 在不在跑,只连一个库是看不到的;到各节点上跑 kbdiag status。
  • conninfo 不采:可能带密码。

备库

~/kbdiag cluster
echo EXIT_CODE=$?
cluster  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:03+08:00)

nodes: 2  (repmgr metadata in database esrep)
  id  name   type     upstream  active  priority  location  slot
  1   node1  primary  -         yes     100       default   repmgr_slot_1
  2   node2  standby  node1     yes     100       default   repmgr_slot_2
  this node is node2: repmgr says standby, the database is a standby

events: 20  (the latest, at most 20)
  time                 node   event                   ok   details
  2026-10-07 17:20:02  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:20:01  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:20:01  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:19:18  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:12:14  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-10-07 17:12:08  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:01:21  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:01:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:01:19  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:00:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 16:49:31  node1  child_node_new_connect  yes  new standby "node2" (ID: 2) has connected
  2026-10-07 16:49:28  node2  repmgrd_start           yes  monitoring connection to upstream node "node1" (ID: 1)
  2026-10-07 16:49:26  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 16:49:26  node2  node_rejoin             yes  node 2 is now attached to node 1
  2026-10-07 16:48:36  node1  repmgrd_start           yes  monitoring cluster primary "node1" (ID: 1)
  2026-09-29 20:06:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 8 seconds
  2026-09-29 20:06:13  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-09-29 19:22:45  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-09-29 19:22:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-09-28 15:42:40  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 106 seconds
EXIT_CODE=0

备库的 repmgr 元数据是从主库复制来的,所以节点表和事件一样,只有对照那一行是它自己的。cluster.detached 只在主库上判。

显式给了 -d

~/kbdiag -d test cluster
echo EXIT_CODE=$?
cluster  UNKNOWN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:11+08:00)

nodes: skipped  (no repmgr schema in database test named by -d; repmgr keeps it in database esrep by default)

events: skipped  (no repmgr schema in database test named by -d; repmgr keeps it in database esrep by default)
EXIT_CODE=3

自己给了 -d,kbdiag 就信它。test 库里没有 repmgr schema,两个 probe 都是 skipped,结论是 UNKNOWN(没给 -d 时同样的情况是 not_applicable:不是 repmgr 集群,或者元数据在别处)。文本说明了 repmgr 默认把数据放在哪个库。

备库没挂上来

~/kbdiag cluster
echo EXIT_CODE=$?
cluster  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:22:57+08:00)

[WARN] cluster.detached  repmgr lists node2 as an active standby of this node (node1), but no walsender here has that application_name: it is not attached (repmgr cluster show would report it so), unless its conninfo sets another application_name
  verify: kbdiag status  # run on node2: is it up, is it receiving WAL
  verify: kbdiag slots  # whether its slot here is inactive

nodes: 2  (repmgr metadata in database esrep)
  id  name   type     upstream  active  priority  location  slot
  1   node1  primary  -         yes     100       default   repmgr_slot_1
  2   node2  standby  node1     yes     100       default   repmgr_slot_2
  this node is node1: repmgr says primary, the database is a primary
  not attached here: node2

events: 20  (the latest, at most 20)
  time                 node   event                   ok   details
  2026-10-07 17:22:20  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:20:02  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:20:01  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:20:01  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:19:18  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:12:14  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-10-07 17:12:08  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 17:01:21  node2  standby_recovery        yes  reconnected to local node "node2" (ID: 2), marking active
  2026-10-07 17:01:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 43 seconds
  2026-10-07 17:01:19  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 17:00:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-10-07 16:49:31  node1  child_node_new_connect  yes  new standby "node2" (ID: 2) has connected
  2026-10-07 16:49:28  node2  repmgrd_start           yes  monitoring connection to upstream node "node1" (ID: 1)
  2026-10-07 16:49:26  node1  node_recovery_success   yes  node "node2" (ID: 2) auto-recovery success
  2026-10-07 16:49:26  node2  node_rejoin             yes  node 2 is now attached to node 1
  2026-10-07 16:48:36  node1  repmgrd_start           yes  monitoring cluster primary "node1" (ID: 1)
  2026-09-29 20:06:21  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 8 seconds
  2026-09-29 20:06:13  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
  2026-09-29 19:22:45  node1  child_node_reconnect    yes  standby node "node2" (ID: 2) has reconnected after 6 seconds
  2026-09-29 19:22:38  node1  child_node_disconnect   yes  standby node "node2" (ID: 2) has disconnected
EXIT_CODE=1
  • cluster.detached(WARN):repmgr 仍然说 node2 是本节点的 active 备库,但这里没有任何 walsender 的 application_name 是它,所以它没挂上来。repmgr 自己也会这样报,除非备库的 conninfo 另设了 application_name。文本里 not attached here: node2 是同一件事。
  • 最新一条事件 child_node_disconnect(17:22:20)是 repmgr 自己对同一件事的记录。
  • 它是 WARN:业务还没受影响。它是真的挂了还是只是卡住,只有到那个节点上才看得出,所以 verify 让你到 node2 上跑 kbdiag status,在这里跑 kbdiag slots。

实验环境没有造出来的 WARN

按源码写,不是实采。都是 WARN:repmgr 按元数据做切换,不一致是隐患,但业务此刻还没受影响;是不是真脑裂要到各节点上才看得出。

  • cluster.primaries:repmgr 里有多于一个 active 的 primary。元数据说是脑裂;到每个节点上跑 kbdiag status,看哪个已经不在恢复状态。
  • cluster.inactive:repmgr 把某个节点标成 inactive,算它失败或已移除,所以集群少了一个能接管的节点。
  • cluster.role_mismatch:repmgr 说本节点是主库(或备库),但数据库是另一种。

退出码

退出码含义
0OK
1WARN
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

15 - top-objects:最大的表和索引

当前库最大的表(堆、索引、TOAST 分列)和最大的索引。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。没有注入故障。数值只属于本次采样。

用法

kbdiag top-objects [--limit N] [--json]
参数作用
--limit N每个列表最多显示 N 行;默认 20,0 表示全部
--json输出 JSON

连接参数和 sessions 相同,看的是当前连接的库。这条命令只展示,没有 finding。

主库

~/kbdiag top-objects
echo EXIT_CODE=$?
top-objects  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:57+08:00)

tables in test: 207, largest first  (total = heap + indexes + TOAST)
  table                       kind   total    heap     indexes  toast       rows (est.)
  public.orders               table  170 MB   62 MB    108 MB   -           1000000
  public.flight_psg_new_info  table  107 MB   64 MB    43 MB    -           1000000
  public.kbdiag_test          table  71 MB    43 MB    28 MB    8192 bytes  645750
  public.t_perf_test          table  8968 kB  6752 kB  2216 kB  -           100000
  pg_catalog._proc            table  4624 kB  1480 kB  712 kB   2432 kB     4650
  pg_catalog._dep             table  3816 kB  1160 kB  2656 kB  -           18518
  pg_catalog._att             table  3560 kB  2056 kB  1504 kB  -           11678
  pg_catalog._rewrite         table  2320 kB  664 kB   88 kB    1568 kB     576
  pg_catalog._desc            table  1616 kB  1296 kB  312 kB   8192 bytes  4923
  pg_catalog._stat            table  728 kB   520 kB   48 kB    160 kB      633
  pg_catalog._rel             table  640 kB   352 kB   288 kB   -           1244
  pg_catalog._typ             table  464 kB   272 kB   184 kB   8192 bytes  1304
  pg_catalog._op              table  328 kB   216 kB   112 kB   -           1062
  pg_catalog._amop            table  288 kB   112 kB   176 kB   -           1266
  pg_catalog._pkg             table  248 kB   64 kB    32 kB    152 kB      6
  pg_catalog._con             table  184 kB   80 kB    96 kB    8192 bytes  136
  pg_catalog._ind             table  176 kB   112 kB   64 kB    -           353
  pg_catalog._initprivs       table  168 kB   112 kB   48 kB    8192 bytes  777
  pg_catalog._amproc          table  160 kB   72 kB    88 kB    -           641
  pg_catalog._trigger         table  144 kB   64 kB    72 kB    8192 bytes  192
  ... 187 more not shown (--limit 0 shows all)

indexes in test: 271, largest first
  index                                     table                size
  public.kbdiag_rev_idx                     orders               56 MB
  public.idx_orders_user_status             orders               30 MB
  public.kbdiag_test_pkey                   kbdiag_test          28 MB
  public.flight_psg_new_info_pkey           flight_psg_new_info  22 MB
  public.idx_homs_flight_psg_new_info_tm    flight_psg_new_info  22 MB
  public.orders_pkey                        orders               22 MB
  public.t_perf_test_pkey                   t_perf_test          2216 kB
  pg_catalog._dep_depender_index            _dep                 1384 kB
  pg_catalog._dep_reference_index           _dep                 1224 kB
  pg_catalog._att_relid_attnam_index        _att                 888 kB
  pg_catalog._proc_proname_args_nsp_index   _proc                576 kB
  pg_catalog._att_relid_attnum_index        _att                 568 kB
  pg_catalog._desc_o_c_o_index              _desc                288 kB
  pg_catalog._proc_oid_index                _proc                136 kB
  pg_catalog._rel_relname_nsp_index         _rel                 104 kB
  pg_catalog._rel_tblspc_relfilenode_index  _rel                 88 kB
  pg_catalog._typ_typname_nsp_index         _typ                 88 kB
  pg_catalog._amop_fam_strat_index          _amop                72 kB
  pg_catalog._op_oprname_l_r_n_index        _op                  72 kB
  pg_catalog._rel_oid_index                 _rel                 72 kB
  ... 251 more not shown (--limit 0 shows all)
EXIT_CODE=0
  • tables 按总大小排序。total 是堆、索引、TOAST 加起来:total = heap + indexes + toast。拆开是因为大是因为数据、索引还是大字段,处理办法不同。heap 是 pg_table_size 减去 TOAST,所以含 FSM 和 VM。TOAST 表和它的索引不单列,算在父表里。
  • 大小是精确值,不是 relpages 估算(和 freeze 相反):这条命令就是回答“现在谁占了空间”,批量导入后没 ANALYZE 的话 relpages 是旧的。代价是大小函数要加 AccessShareLock,所以表被 VACUUM FULL 这类操作锁住时,整条 probe 会在 lock_timeout 上 skipped 并写明原因,而不是给出部分结果。查询期间被删掉的表读成 NULL 并被过滤掉,所以 ETL 反复建删临时表不会让 probe 失败。
  • rows (est.) 是 reltuples。
  • indexes 列出最大的索引和它所属的表。这里只看大小,使用次数去看 kbdiag table <表名>。
  • 分区不会按父表汇总。
  • 没有判定:多大算大没有客观线。所以都采到了才是 OK,有 probe 没采到就是 UNKNOWN。
  • 实验环境里空间主要在测试用的表上(orders、flight_psg_new_info、kbdiag_test)。

备库和没有权限时

实验环境里,备库和 kbdiag_ro 账号(没有监控角色,走 127.0.0.1)返回的行和主库一致,只有第一行(角色、用户、时间)不同。大小不需要权限,所以什么都没被遮蔽。备库的采集在 kes-node2 上,kbdiag_ro 的在 kes-node1 上。

退出码

退出码含义
0OK
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

16 - table:一张表

一张表:大小、行数、vacuum 和 analyze、冻结年龄、访问、索引。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。两个例子由注入脚本造出来:public.kbdiag_inj_dead(设了 autovacuum_enabled=off,插入 10000 行、删除 5000 行)和 public.kbdiag_inj_tbl(插入 20000 行、删除 5000 行,带主键和另一个索引)。数值只属于本次采样。

用法

kbdiag table <name> [--json]

<name> 按 SQL 规则解析:用 to_regclass(参数绑定),不带引号的名字折成小写,按 search_path 找,和在 ksql 里写的一致。要大写就像 SQL 里那样加引号:'"Name"'。连接参数和 sessions 相同,看的是当前连接的库(别的库用 -d)。

名字是空的是用法错误(退出码 64)。找不到是 UNKNOWN(3),不是用法错误,因为表可能在别的库里。

主库上的一张表

~/kbdiag table orders
echo EXIT_CODE=$?
table  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:57+08:00)

public.orders  (table)
  size        170 MB  (heap 62 MB, indexes 108 MB, no TOAST)
  rows        1000000 estimated; 1000000 live, 0 dead
  xid age     994  (autovacuum_freeze_max_age 200000000)
  mxid age    0
  reloptions  -

vacuum and analyze
  dead tuples             0, autovacuum threshold 200050
  last vacuum             9d 1h ago  (2 times)
  last autovacuum         never  (0 times)
  last analyze            9d 1h ago  (2 times)
  last autoanalyze        never  (0 times)
  modified since analyze  0

access since the statistics reset
  seq scans     21  (10000000 rows read)
  index scans   0  (0 rows fetched)
  rows written  0 inserted, 0 updated (0 HOT), 0 deleted
  heap blocks   23694 read, 108762 hit (82.1% hit)
  index blocks  6635 read, 10 hit (0.1% hit)

indexes: 3
  name                    size   scans  kind         definition
  idx_orders_user_status  30 MB  0      -            CREATE INDEX idx_orders_user_status ON public.orders USING btree (user_id, status)
  kbdiag_rev_idx          56 MB  0      -            CREATE INDEX kbdiag_rev_idx ON public.orders USING btree (md5((id)::text))
  orders_pkey             22 MB  0      primary key  CREATE UNIQUE INDEX orders_pkey ON public.orders USING btree (id)
EXIT_CODE=0
  • size 是精确值,拆成堆、索引、TOAST,定义和 top-objects 相同,所以同一张表两处数字一致。解析名字不加锁,大小是单独的 probe:有人拿 VACUUM FULL 之类锁着这张表时,只会丢掉大小(等到 lock_timeout),其余照常显示,文本会指向 kbdiag locks。
  • rows 里估算值(reltuples)旁边是统计里的活元组和死元组。xid age 是冻结年龄,对照 autovacuum_freeze_max_age。
  • vacuum and analyze:死元组对照 autovacuum 触发线,最近手工和自动的 vacuum、analyze 各多久前、几次,以及上次 analyze 之后的修改数。
  • access since the statistics reset:扫描、读写的行数、块缓存命中,命中率保留一位小数,几次读盘不会被四舍五入成 100%。
  • indexes 有大小、扫描次数、是不是主键和定义。
  • 判定复用别的命令的规则,没有新规则:年龄对照和 freeze 同样的两条线(finding id 是 freeze.table_age),表级关了 autovacuum 又过线是 vacuum.table_disabled。这里两条都没触发,所以是 OK。

同一张表在备库上

~/kbdiag table orders
echo EXIT_CODE=$?
table  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:04+08:00)

public.orders  (table)
  size        170 MB  (heap 62 MB, indexes 108 MB, no TOAST)
  rows        1000000 estimated
  xid age     994  (autovacuum_freeze_max_age 200000000)
  mxid age    0
  reloptions  -

statistics: not_applicable  (standby: table statistics are local to each node and stay 0 here; run on the primary)

indexes: 3
  name                    size   scans  kind         definition
  idx_orders_user_status  30 MB  -      -            CREATE INDEX idx_orders_user_status ON public.orders USING btree (user_id, status)
  kbdiag_rev_idx          56 MB  -      -            CREATE INDEX kbdiag_rev_idx ON public.orders USING btree (md5((id)::text))
  orders_pkey             22 MB  -      primary key  CREATE UNIQUE INDEX orders_pkey ON public.orders USING btree (id)
EXIT_CODE=0

表统计是节点本地的,所以 statistics 是 not_applicable,索引扫描次数是 -(NULL,不是 0)。大小、行数估算和年龄是复制来的,照样显示,年龄照样判。

表级关了 autovacuum

~/kbdiag table kbdiag_inj_dead
echo EXIT_CODE=$?
table  WARN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:13+08:00)

[WARN] vacuum.table_disabled  table public.kbdiag_inj_dead has 5000 dead tuples, past its autovacuum threshold 2050, but autovacuum is off for it (autovacuum_enabled=off): nothing will clean it
  fix: VACUUM public.kbdiag_inj_dead  # connected to database test; turn autovacuum back on with ALTER TABLE ... RESET (autovacuum_enabled) unless it was turned off on purpose

public.kbdiag_inj_dead  (table)
  size        712 kB  (heap 704 kB, indexes 0 bytes, TOAST 8192 bytes)
  rows        10000 estimated; 5000 live, 5000 dead
  xid age     4  (autovacuum_freeze_max_age 200000000)
  mxid age    0
  reloptions  autovacuum_enabled=off

vacuum and analyze
  dead tuples             5000, autovacuum threshold 2050: due (autovacuum is off for this table)
  last vacuum             never  (0 times)
  last autovacuum         never  (0 times)
  last analyze            1s ago  (1 time)
  last autoanalyze        never  (0 times)
  modified since analyze  5000

access since the statistics reset
  seq scans     1  (10000 rows read)
  index scans   -
  rows written  10000 inserted, 0 updated (0 HOT), 5000 deleted
  heap blocks   87 read, 15335 hit (99.4% hit)
  index blocks  -

indexes: 0
EXIT_CODE=1
  • finding 和 kbdiag vacuum 对这张表报的是同一条:vacuum.table_disabled,fix 也一样。reloptions 里能看到原因 autovacuum_enabled=off,文本写 due (autovacuum is off for this table)。
  • modified since analyze 是 5000,和删掉的 5000 行对得上。

过了线但 autovacuum 开着

~/kbdiag table kbdiag_inj_tbl
echo EXIT_CODE=$?
table  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:18+08:00)

public.kbdiag_inj_tbl  (table)
  size        2504 kB  (heap 1520 kB, indexes 976 kB, TOAST 8192 bytes)
  rows        20000 estimated; 15000 live, 5000 dead
  xid age     5  (autovacuum_freeze_max_age 200000000)
  mxid age    0
  reloptions  -

vacuum and analyze
  dead tuples             5000, autovacuum threshold 4050: due
  last vacuum             never  (0 times)
  last autovacuum         never  (0 times)
  last analyze            1s ago  (1 time)
  last autoanalyze        never  (0 times)
  modified since analyze  5000

access since the statistics reset
  seq scans     3  (20000 rows read)
  index scans   0  (0 rows fetched)
  rows written  20000 inserted, 0 updated (0 HOT), 5000 deleted
  heap blocks   189 read, 25743 hit (99.2% hit)
  index blocks  122 read, 79374 hit (99.8% hit)

indexes: 2
  name                 size    scans  kind         definition
  kbdiag_inj_tbl_n     520 kB  0      -            CREATE INDEX kbdiag_inj_tbl_n ON public.kbdiag_inj_tbl USING btree (n)
  kbdiag_inj_tbl_pkey  456 kB  0      primary key  CREATE UNIQUE INDEX kbdiag_inj_tbl_pkey ON public.kbdiag_inj_tbl USING btree (id)
EXIT_CODE=0

5000 个死元组对着 4050 的触发线,所以写 due,但这张表 autovacuum 开着,下一轮 autovacuum 会处理它:没有 finding,结论 OK。

表不存在

~/kbdiag table no_such_table
echo EXIT_CODE=$?
kbdiag: no table "no_such_table" in database "test" (unquoted names fold to lower case; quote them as in SQL: '"Name"'; use -d for another database)
table  UNKNOWN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:19+08:00)

table: not found
EXIT_CODE=3

第一行是 stderr,说明不带引号的名字会折成小写,以及用 -d 选别的库。退出码 3(UNKNOWN),报告正文只有 table: not found。

退出码

退出码含义
0OK
1WARN:freeze.table_age 超过 autovacuum_freeze_max_age,或 vacuum.table_disabled(关了 autovacuum 又过了线)
2FAIL:freeze.table_age 到了停止线(实验环境没造出来)
3UNKNOWN:有数据没采到,或者表找不到
64参数错误,包括名字为空
69连不上数据库

返回使用手册

17 - top:累计 Top SQL

sys_stat_statements 的累计 Top SQL;没在收集时明说。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。没有注入故障。实验环境两个节点上 sys_stat_statements.track 都是 none,没有在收集语句,top 没有行可显示。这一页展示的就是这种情况,也是实验环境的真实状态。统计开着的情况没有采到(见最后一节)。

用法

kbdiag top [--limit N] [--by time|mean|calls|io|temp] [--json]
参数作用
--limit N最多显示 N 条语句;默认 20,0 表示全部
--by ORDER排序方式:time(累计执行时间,默认)、mean(每次耗时)、calls(调用次数)、io(读盘块数)、temp(写临时文件块数)。它是排序,不是过滤
--json输出 JSON

--by 给了别的值是用法错误(退出码 64)。连接参数和 sessions 相同。

没在收集语句

~/kbdiag top
echo EXIT_CODE=$?
top  UNKNOWN  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:58+08:00)

statements: skipped  (sys_stat_statements.track=none: statements are not being collected; set it to top or all)
EXIT_CODE=3
  • skipped 并写明原因,结论是 UNKNOWN:空表加 OK 等于说“没有昂贵的 SQL”,而实际上什么都没测。备库(kes-node2)上打印的一样。
  • 打开它的开关是 sys_stat_statements.track(top 或 all)。另外两种原因有各自的提示:库没加载进 shared_preload_libraries(要重启),或者扩展没装在当前库(CREATE EXTENSION sys_stat_statements,或者用 -d)。
  • 视图按 sys_extension 找到的 schema 读,不走 search_path:否则别人在 public 里放一个同名视图,就能让 kbdiag 报假数据。
  • 本连接的 track=none 不等于没有数据(角色、库可以自己设,save=on 也会留着旧数据),所以 kbdiag 照样读视图,一行都没有才写 skipped。

统计开着时:没有采到

按源码写,不是实采:语句被收集时,输出是一张表,列是 total、share、calls、mean、rows、read、temp、user、database、query,表头说明数值是自上次重置以来的累计值。

  • share 是这条语句占全部执行时间的比例,直接回答“数据库的时间花在哪”。哪条 SQL 算太贵没有客观线,所以 top 只展示,没有 finding。
  • 数值是自上次统计重置以来的累计值。这个版本没有 sys_stat_statements_info,重置时间拿不到,表头直说了这点。read 和 temp 的单位是块。
  • track=all 时,函数里执行的语句会在调用它的语句里再算一次,所以比例加起来会超过 100%,文本会说明。track=none 但有行时,文本说明这些是之前收集的,或者来自自己设了 track 的角色和库。
  • 时间按量级换单位(0.09 ms、503 ms、1.75 s)。这个账号看不到的 query 显示 ?。
  • top --interval(最近 N 秒)这个版本不做。

退出码

退出码含义
0OK:语句有被收集
3UNKNOWN:有数据没采到或看不到
64参数错误,包括 --by 的值不对
69连不上数据库

返回使用手册

18 - progress:长操作进度

正在跑的 VACUUM、CREATE INDEX、CLUSTER / VACUUM FULL、CHECKPOINT 到哪了。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。进行中的例子由注入脚本造出来:它在 public.orders(100 万行)上跑 CREATE INDEX,运行期间读了三次,其中一次用 kbdiag_ro。PID 和时间只属于本次采样。

用法

kbdiag progress [--json]

没有自己的参数。连接参数和 sessions 相同。

没有在跑的

~/kbdiag progress
echo EXIT_CODE=$?
progress  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:58+08:00)

running: 0  (VACUUM, CREATE INDEX, CLUSTER and VACUUM FULL, CHECKPOINT; ANALYZE and base backups have no progress view in this version)
EXIT_CODE=0

文本写明了它看哪几种操作,也写明了看不到什么:这个版本没有 ANALYZE 和 base backup 的进度视图。备库(kes-node2)上打印的是同一行。

  • kbdiag 把 PostgreSQL 的三个进度视图(VACUUM、CREATE INDEX、CLUSTER / VACUUM FULL)合成一个 probe,因为读者问的是“那个长操作到哪了”,不关心它在哪个视图里。KingbaseES 自己的 checkpoint 视图单独一个 probe:只观察到了它的列名,它出错时不能连累另外三个。

CREATE INDEX 进行中

~/kbdiag progress
echo EXIT_CODE=$?
progress  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:24+08:00)

running: 1
  pid    command       database  relation  phase                           progress                  running
  43243  CREATE INDEX  test      orders    building index: scanning table  5058 / 7896 blocks (64%)  3s
EXIT_CODE=0

几秒之后的同一个构建:

~/kbdiag progress
echo EXIT_CODE=$?
progress  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:29+08:00)

running: 1
  pid    command       database  relation  phase                           progress                   running
  43243  CREATE INDEX  test      orders    building index: scanning table  7896 / 7896 blocks (100%)  8s
EXIT_CODE=0
  • phase 是操作自己的阶段,progress 是已做/总量加单位和百分比。已做/总量按阶段取:块计数在扫描结束后停住,接着的阶段(vacuum 的回收、建索引的排序和装载)要换计数,否则会长时间显示 100%。第二次采样的 100% 是表扫描结束,不是索引建完。
  • running 是操作已经跑了多久。
  • 它只展示。多久算慢没有客观线,vacuum 该不该跑由 kbdiag vacuum 判。CREATE INDEX CONCURRENTLY 还在等别的事务时,阶段后面会写还剩几个,并指向 kbdiag locks:这正是它看起来卡住的常见原因。

没有权限时

kbdiag_ro(没有监控角色,走 127.0.0.1)读同一个构建:

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro progress
echo EXIT_CODE=$?
progress  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:25+08:00)

running: 1
  pid    command                  database  relation  phase  progress  running
  43243  CREATE INDEX or REINDEX  test      -         ?      ?         ?
redacted: 1 row of progress.list hides phase (insufficient_privilege; grant sys_monitor)
EXIT_CODE=3

操作看得到,但 phase 被遮蔽(?),所以进度、运行时间和表都不显示,命令标成 CREATE INDEX or REINDEX。被遮蔽的格子记在 redacted 里。因为有东西没看到,结论是 UNKNOWN,虽然操作本身找到了。授予 sys_monitor 后解除。

退出码

退出码含义
0OK
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

19 - checkpoint:检查点

最近一次 checkpoint,定时和被请求的各多少,脏页是谁写的,相关参数。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。没有注入故障。数值只属于本次采样。

用法

kbdiag checkpoint [--json]

没有自己的参数。连接参数和 sessions 相同。

主库

~/kbdiag checkpoint
echo EXIT_CODE=$?
checkpoint  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:59+08:00)

last checkpoint
  time  2026-10-07 17:18:33  (2m 26s ago)
  redo  0/C651C548  (0000000300000000000000C6)

since the statistics reset 2026-09-15 23:12:34 (21d 18h ago)
  checkpoints        1606: 1606 timed, 0 requested (0%; requested covers WAL volume, CHECKPOINT, base backups, promotion)
  write, sync time   6m 54s, 490 ms
  buffers written    17029: checkpointer 10565 (62%), bgwriter 0 (0%), backends and others 6464 (38%)
  buffers allocated  37300
  backend fsyncs     0
  bgwriter stopped   0 times at bgwriter_lru_maxpages

settings
  checkpoint_timeout            5m 0s
  max_wal_size                  1024 MB
  checkpoint_completion_target  0.5
  checkpoint_warning            30s
  log_checkpoints               on
EXIT_CODE=0
  • last checkpoint 是最近一次 checkpoint 的时间和 redo 位置(带 WAL 文件名)。
  • checkpoints 数统计重置以来定时的和被请求的 checkpoint。“requested”不只是 WAL 量:手工 CHECKPOINT、基础备份(包括 repmgr clone)、promote、建库删库也算。kbdiag 只给比例,不下结论。服务器自己的“checkpoint 太频繁”看的是两次 checkpoint 的间隔(checkpoint_warning),累计计数算不出间隔。
  • buffers written 把脏页写入分成三方:checkpointer、后台写进程、“backends and others”。第三项不能读成“checkpointer 跟不上”:PG12 的 buffers_backend 还算关系扩展、VACUUM 和 COPY 的环形缓冲,以及备库的 startup 进程,空闲节点上也能占六七成(这个环境实采过 65% 和 70%)。
  • backend fsyncs 大于 0 只展示,不报 WARN。它表示 fsync 请求没能交给 checkpointer,队列满或 checkpointer 当时没在跑都会(这个环境的 node2 被 kbha 拉起过,实采过 9)。
  • settings 是相关参数。
  • 只展示,所以任何一个 probe 没采到,结论就是 UNKNOWN;OK 只表示“都采到了”,不表示数值好。

备库

~/kbdiag checkpoint
echo EXIT_CODE=$?
checkpoint  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:06+08:00)

checkpoint record the last restartpoint started from (written by the primary)
  time  2026-10-07 17:18:33  (2m 33s ago)
  redo  0/C651C548  (0000000300000000000000C6)

since the statistics reset 2026-10-07 16:49:26 (31m 40s ago)
  checkpoints        43 timed, 0 requested restartpoint attempts (a standby counts every try, one every 15s while no new checkpoint record has arrived)
  write, sync time   2m 51s, 26 ms
  buffers written    45117: checkpointer 7496 (17%), bgwriter 0 (0%), backends and others 37621 (83%)
  buffers allocated  38458
  backend fsyncs     1
  bgwriter stopped   0 times at bgwriter_lru_maxpages

settings
  checkpoint_timeout            5m 0s
  max_wal_size                  1024 MB
  checkpoint_completion_target  0.5
  checkpoint_warning            30s
  log_checkpoints               on
EXIT_CODE=0
  • 备库上这些不是 restartpoint 的计数。PG12 的 checkpointer 每次尝试都加一,没有新的 checkpoint 记录时每 15 秒试一次(这个环境里 4 天有 15917 次),所以文本写 restartpoint attempts,也不给比例。
  • 标题写明:最近一次 restartpoint 起点的 checkpoint 记录是主库写的,所以时间是主库的。

退出码

退出码含义
0OK
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

20 - wal:WAL 位置和谁让它留着

WAL 写到哪了、sys_wal 多大,以及是什么让它留着:参数、槽、归档。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。没有注入故障。数值只属于本次采样。

用法

kbdiag wal [--json]

没有自己的参数。连接参数和 sessions 相同。

主库

~/kbdiag wal
echo EXIT_CODE=$?
wal  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:20:59+08:00)

position
  lsn   0/C9352468
  file  0000000300000000000000C9

sys_wal: 214 files, 3248 MB

what keeps WAL here
  max_wal_size        1024 MB
  wal_keep_segments   8192 MB  (512 x 16 MB)
  slot repmgr_slot_2  0 bytes  (active)
  archiving           38 .ready files waiting  (kbdiag archive)
EXIT_CODE=0
  • position 是当前写到的位置和它所在的 WAL 文件。
  • sys_wal 的大小和 space 里一致:同一个 probe,同样的列。
  • what keeps WAL here 把原来要分别跑三条命令再拼起来的信息放在一屏:参数(max_wal_size,wal_keep_segments 折成它保留的大小)、每个复制槽保留的 WAL 和是否活跃、归档积压。这里槽保留 0 字节而且活跃,但有 38 个 .ready 文件在等归档(实验环境的归档本来就在失败,见 archive)。
  • 它只展示,不重复判定。槽不活跃由 kbdiag slots 报,归档失败由 kbdiag archive 报,这一屏只指过去。同一个问题在三条命令里各报一次,只会让人以为出了三件事。
  • WAL 生成速率要隔一段时间采两次,单次查询给不了,这个版本不做。

备库

~/kbdiag wal
echo EXIT_CODE=$?
wal  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:06+08:00)

position
  replayed  0/C9352A80

sys_wal: 198 files, 3136 MB

what keeps WAL here
  max_wal_size       1024 MB
  wal_keep_segments  8192 MB  (512 x 16 MB)
  slots              none
  archiving          0 .ready files waiting
EXIT_CODE=0

备库上 position 是回放位置(没有写入位置,也没有 WAL 文件名)。这个备库自己没有槽,也没有等着归档的文件。

退出码

退出码含义
0OK
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册

21 - seq:序列

当前库的序列,按用掉的比例排;取不出下一个值时报 FAIL。

采集于 2026-10-07(UTC+08),本地 KingbaseES V008R006C009B0014 主节点和备节点,数据库 test。工具是 Go 版源码提交 96c874f 编译的 ~/kbdiag(linux/amd64 静态二进制)。这是测试环境实测,不代表生产环境验收。FAIL 的例子由注入脚本造出来:它建了 public.kbdiag_inj_seq(maxvalue 3),再用 nextval 把它用完。数值只属于本次采样。

用法

kbdiag seq [--limit N] [--json]
参数作用
--limit N最多显示 N 个序列;默认 20,0 表示全部
--json输出 JSON

连接参数和 sessions 相同,看的是当前连接的库。--limit 只裁列表,判定覆盖所有序列。

主库

~/kbdiag seq
echo EXIT_CODE=$?
seq  OK  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:00+08:00)

sequences in test: 16, most used first
  sequence                                type     last     limit                used   left
  public.kbdiag_test_id_seq               integer  1311000  2147483647           0.06%  2.15e+09
  kdb_schedule.kdb_jobclass_jclid_seq     integer  5        2147483647           0.00%  2.15e+09
  perf.kwr_snapshots_snap_id_seq          integer  2        2147483647           0.00%  2.15e+09
  public.flight_psg_new_info_id_seq       bigint   1000000  9223372036854775807  0.00%  9.22e+18
  public.orders_id_seq                    bigint   1000000  9223372036854775807  0.00%  9.22e+18
  public.t_perf_test_id_seq               bigint   100000   9223372036854775807  0.00%  9.22e+18
  sysmac.sysmac_policy_oid_seq            bigint   1        9223372036854775807  0.00%  9.22e+18
  kdb_schedule.kdb_action_acid_seq        integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_exception_jexid_seq    integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_job_action_jaid_seq    integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_joblog_jlgid_seq       integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_jobsteplog_jslid_seq   integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_schedule_job_sjid_seq  integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_schedule_scid_seq      integer  -        2147483647           -      no value yet
  sys_catalog.global_chain_seq            bigint   -        9223372036854775807  -      no value yet
  sys_hm.hm_run_t_run_id_seq              integer  -        2147483647           -      no value yet
EXIT_CODE=0
  • 序列按用掉的比例排序。last 是最后分配出去的值,limit 是它往哪边数到头(自己的 MAXVALUE,递减的序列是 MINVALUE),used 是用掉的比例,left 是还剩多少个值。计算是精确的(math/big):bigint 序列跨满 int64,普通相减会溢出。
  • 从没调用过、或者 setval(..., false) 之后的序列没有 last 值:显示成 no value yet,值是 -。
  • 只判一件事:seq.exhausted(FAIL),即 nextval 已经报错。只是快用完的序列只展示,不报:多快算快没有客观线。会循环的序列不算用完,会写成 cycles(实验环境没采到)。

备库

~/kbdiag seq
echo EXIT_CODE=$?
seq  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:07+08:00)

sequences in test: 16, most used first
  on a standby a sequence reads up to 32 values ahead of the primary (and is not judged): run on the primary
  sequence                                type     last     limit                used   left
  public.kbdiag_test_id_seq               integer  1311029  2147483647           0.06%  2.15e+09
  kdb_schedule.kdb_jobclass_jclid_seq     integer  33       2147483647           0.00%  2.15e+09
  perf.kwr_snapshots_snap_id_seq          integer  33       2147483647           0.00%  2.15e+09
  public.flight_psg_new_info_id_seq       bigint   1000032  9223372036854775807  0.00%  9.22e+18
  public.orders_id_seq                    bigint   1000032  9223372036854775807  0.00%  9.22e+18
  public.t_perf_test_id_seq               bigint   100023   9223372036854775807  0.00%  9.22e+18
  sysmac.sysmac_policy_oid_seq            bigint   1        9223372036854775807  0.00%  9.22e+18
  kdb_schedule.kdb_action_acid_seq        integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_exception_jexid_seq    integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_job_action_jaid_seq    integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_joblog_jlgid_seq       integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_jobsteplog_jslid_seq   integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_schedule_job_sjid_seq  integer  -        2147483647           -      no value yet
  kdb_schedule.kdb_schedule_scid_seq      integer  -        2147483647           -      no value yet
  sys_catalog.global_chain_seq            bigint   -        9223372036854775807  -      no value yet
  sys_hm.hm_run_t_run_id_seq              integer  -        2147483647           -      no value yet
EXIT_CODE=0

备库上的序列值是 WAL 里的副本,主库每次预写 32 个,所以备库可能读到“到头了”而主库还有值。文本说明了这点(up to 32 values ahead of the primary),备库不判:要到主库上跑 seq。上面的 last 确实比主库的大。

没有权限时

kbdiag_ro(没有监控角色,走 127.0.0.1):

PGPASSWORD=... ~/kbdiag --host 127.0.0.1 -U kbdiag_ro seq
echo EXIT_CODE=$?
seq  UNKNOWN  (KingbaseES V008R006C009B0014, primary, kbdiag_ro@remote, 2026-10-07T17:21:08+08:00)

sequences in test: 16, most used first
  sequence                                type     last  limit                used  left
  kdb_schedule.kdb_action_acid_seq        integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_exception_jexid_seq    integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_job_action_jaid_seq    integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_jobclass_jclid_seq     integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_joblog_jlgid_seq       integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_jobsteplog_jslid_seq   integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_schedule_job_sjid_seq  integer  ?     2147483647           ?     ?
  kdb_schedule.kdb_schedule_scid_seq      integer  ?     2147483647           ?     ?
  perf.kwr_snapshots_snap_id_seq          integer  ?     2147483647           ?     ?
  public.flight_psg_new_info_id_seq       bigint   ?     9223372036854775807  ?     ?
  public.kbdiag_test_id_seq               integer  ?     2147483647           ?     ?
  public.orders_id_seq                    bigint   ?     9223372036854775807  ?     ?
  public.t_perf_test_id_seq               bigint   ?     9223372036854775807  ?     ?
  sys_catalog.global_chain_seq            bigint   -     9223372036854775807  -     no value yet
  sys_hm.hm_run_t_run_id_seq              integer  -     2147483647           -     no value yet
  sysmac.sysmac_policy_oid_seq            bigint   ?     9223372036854775807  ?     ?
redacted: 14 rows of seq.list hide last_value (insufficient_privilege; grant SELECT on the sequences (sys_monitor does not cover them))
EXIT_CODE=3
  • ? 是这个账号读不了的 last_value(序列上没有 SELECT 权限),所以 used 和 left 算不出。SQL 按 oid 判权限,序列中途被删掉不会让整条 probe 失败。14 个看不到的行记在 redacted 里,提示给序列授予 SELECT:sys_monitor 不覆盖序列。
  • 值是 - 的两行是从没调用过的序列(no value yet):它和权限不够造成的 NULL 不是一回事,kbdiag 把两者分开。
  • 结论是 UNKNOWN,因为没能看到这些值。

用完的序列

~/kbdiag seq
echo EXIT_CODE=$?
seq  FAIL  (KingbaseES V008R006C009B0014, primary, system@local, 2026-10-07T17:21:20+08:00)

[FAIL] seq.exhausted  sequence public.kbdiag_inj_seq (integer) is at 3, its limit is 3: nextval fails, so inserts that use it fail
  fix: ALTER SEQUENCE public.kbdiag_inj_seq MAXVALUE <higher>  # it stops at its MAXVALUE, short of what its type allows

sequences in test: 17, most used first
  sequence                                type     last     limit                used     left
  public.kbdiag_inj_seq                   integer  3        3                    100.00%  0
  public.kbdiag_test_id_seq               integer  1311000  2147483647           0.06%    2.15e+09
  kdb_schedule.kdb_jobclass_jclid_seq     integer  5        2147483647           0.00%    2.15e+09
  perf.kwr_snapshots_snap_id_seq          integer  2        2147483647           0.00%    2.15e+09
  public.flight_psg_new_info_id_seq       bigint   1000000  9223372036854775807  0.00%    9.22e+18
  public.orders_id_seq                    bigint   1000000  9223372036854775807  0.00%    9.22e+18
  public.t_perf_test_id_seq               bigint   100000   9223372036854775807  0.00%    9.22e+18
  sysmac.sysmac_policy_oid_seq            bigint   1        9223372036854775807  0.00%    9.22e+18
  kdb_schedule.kdb_action_acid_seq        integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_exception_jexid_seq    integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_job_action_jaid_seq    integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_joblog_jlgid_seq       integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_jobsteplog_jslid_seq   integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_schedule_job_sjid_seq  integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_schedule_scid_seq      integer  -        2147483647           -        no value yet
  sys_catalog.global_chain_seq            bigint   -        9223372036854775807  -        no value yet
  sys_hm.hm_run_t_run_id_seq              integer  -        2147483647           -        no value yet
EXIT_CODE=2
  • seq.exhausted 是 FAIL:nextval 已经报错,用它的插入已经失败。线就是序列自己的上限,所以没有参数。
  • fix 按是什么挡住了来给。这里序列停在自己的 MAXVALUE 3,比 integer 允许的小,所以建议把它调高。序列已经到了类型的边界时:int 或 smallint 改成 bigint(先改列,要重写表),bigint 只能换键。bigint 序列配 int 列、列先溢出的错配,这里不检测。

同一个库在备库上:

~/kbdiag seq
echo EXIT_CODE=$?
seq  OK  (KingbaseES V008R006C009B0014, standby, system@local, 2026-10-07T17:21:21+08:00)

sequences in test: 17, most used first
  on a standby a sequence reads up to 32 values ahead of the primary (and is not judged): run on the primary
  sequence                                type     last     limit                used     left
  public.kbdiag_inj_seq                   integer  3        3                    100.00%  0
  public.kbdiag_test_id_seq               integer  1311029  2147483647           0.06%    2.15e+09
  kdb_schedule.kdb_jobclass_jclid_seq     integer  33       2147483647           0.00%    2.15e+09
  perf.kwr_snapshots_snap_id_seq          integer  33       2147483647           0.00%    2.15e+09
  public.flight_psg_new_info_id_seq       bigint   1000032  9223372036854775807  0.00%    9.22e+18
  public.orders_id_seq                    bigint   1000032  9223372036854775807  0.00%    9.22e+18
  public.t_perf_test_id_seq               bigint   100023   9223372036854775807  0.00%    9.22e+18
  sysmac.sysmac_policy_oid_seq            bigint   1        9223372036854775807  0.00%    9.22e+18
  kdb_schedule.kdb_action_acid_seq        integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_exception_jexid_seq    integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_job_action_jaid_seq    integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_joblog_jlgid_seq       integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_jobsteplog_jslid_seq   integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_schedule_job_sjid_seq  integer  -        2147483647           -        no value yet
  kdb_schedule.kdb_schedule_scid_seq      integer  -        2147483647           -        no value yet
  sys_catalog.global_chain_seq            bigint   -        9223372036854775807  -        no value yet
  sys_hm.hm_run_t_run_id_seq              integer  -        2147483647           -        no value yet
EXIT_CODE=0

同样有 100.00% 这一行,备库仍然是 OK,因为它不判序列。

退出码

退出码含义
0OK
2FAIL:有序列取不出下一个值
3UNKNOWN:有数据没采到或看不到
64参数错误
69连不上数据库

返回使用手册