KES 数据库开发运维手记:部署、安全、备份与监控实战

0 阅读22分钟

KES 数据库开发运维手记:部署、安全、备份与监控实战

写在开头

干数据库这行有些年头了,从最早用商业库到后来折腾各种国产库,踩过的坑说多了都是泪。这两年信创项目越来越多,KES 数据库在政企、金融、能源领域铺得挺广,身边不少朋友开始接触它。说实话,刚上手的时候我也摸不着头脑——文档虽然有,但很多细节得靠自己踩坑才能搞明白。有些配置参数改了之后要重启才生效,有些不用;有些功能要装扩展才能用,有些默认就开着。这些东西文档里都有写,但散落在各个章节里,找起来费劲。

这篇文章算是一个阶段性的总结,把部署配置、安全管理、备份恢复、日常监控这几个方面的心得记下来。适合有一定数据库基础、刚开始接触 KingbaseES 的开发和运维人员。内容偏实操,理论部分点到为止,重点还是那些命令和配置。如果你是正在做信创项目选型或者刚接手一个 KES 数据库的运维工作,这篇文章应该能帮你少走一些弯路。

安装部署与环境初始化

装库这事本身不难,但有些细节不注意后面会吃苦头。KES 支持主流国产操作系统,麒麟、统信、中科方德都没问题,x86 和 ARM 架构也都能跑。我一般在 CentOS 和麒麟 V10 上装得比较多,流程差不多。有一点要提前确认:操作系统的内核参数和网络配置要符合数据库的安装要求,特别是大页内存(hugepages)的设置,生产环境下开启大页对性能有帮助。

安装包获取与准备

安装介质从电科金仓官方渠道获取,一般是 ISO 或者 tar.gz 格式。拿到之后先校验一下 MD5,别因为下载不完整浪费时间。解压之后目录结构大致是这样的:

tar -xzf KingbaseES_V9_xxx.tar.gz
cd KingbaseES_V9_xxx

# 看一下目录结构
ls -l
# setup.sh 是安装脚本
# license.dat 是授权文件,没这个装不了

装之前确认系统用户和环境变量。建议用专门的 kingbase 用户来安装和运行数据库服务,别用 root。

# 创建专用用户
useradd -m kingbase
passwd kingbase

# 设置目录权限
chown -R kingbase:kingbase /opt/Kingbase

执行安装

KES 提供图形界面安装和静默安装两种方式。服务器环境下我推荐用静默安装,快且不容易出错。图形界面那个在远程终端里跑起来卡得很,没必要。

# 静默安装示例
./setup.sh -i console \
  -d /opt/Kingbase/ES/V9 \
  -p server \
  -U system \
  -W "YourPassword123" \
  --license /opt/license.dat

安装过程中会让你选择兼容模式,这个比较关键。KingbaseES 支持 Oracle 兼容、MySQL 兼容和标准模式三种。选哪种取决于你的业务原来用的是什么库。如果是新开发的项目,标准模式就挺好,SQL 行为最规范;如果是从 Oracle 迁过来的,选 Oracle 兼容模式会省很多事,存储过程、包、自定义类型基本上不用怎么改就能跑。MySQL 兼容模式同理,对 MySQL 的方言和函数做了适配。不过要注意,兼容模式选定之后不能随便切换,建议在项目初期就确定好。

初始化与启动

装完之后初始化数据库实例,这个过程跟其他关系型数据库类似:

# 切到 kingbase 用户
su - kingbase

# 初始化数据目录
initdb -D /data/kingbase/data \
  -U system \
  -W \
  --encoding=UTF8 \
  --locale=zh_CN.UTF-8

# 启动服务
sys_ctl -D /data/kingbase/data start

# 确认服务状态
sys_ctl -D /data/kingbase/data status

启动之后第一件事是改默认密码和配置 ksql 的访问权限。ksql 是 KES 自带的命令行交互工具,跟其他数据库的 CLI 工具用法差不多,SQL 语句直接敲进去就能执行。

-- 通过 ksql 连接
-- ksql -U system -d test -p 54321

-- 改掉默认密码
ALTER USER system WITH PASSWORD 'NewStrongP@ss2026';

-- 看一下当前数据库列表
SELECT datname, datowner, encoding FROM sys_database;

配置文件调整

初始化完成后的默认配置只能跑跑测试,生产环境得改几个关键参数。配置文件在数据目录下的 kingbase.conf:

-- 这几个参数改完需要重启
shared_buffers = 4GB
work_mem = 64MB
maintenance_work_mem = 512MB
effective_cache_size = 12GB

-- 连接数根据实际并发来定
max_connections = 200

-- 日志相关
logging_collector = on
log_directory = 'sys_log'
log_filename = 'kingbase-%Y-%m-%d.log'
log_min_duration_statement = 1000
log_rotation_age = 1d

shared_buffers 一般设成物理内存的 25% 左右,不要贪大。我有次设到 60% 结果系统缓存不够用,IO 反而变高了。work_mem 注意它是每个排序操作各自分配的,并发高的话别设太猛,不然内存会被吃光。

网络访问配置

默认只允许本机连接,要让其他机器访问得改两个地方。一个是 kingbase.conf 里的 listen_addresses,另一个是 sys_hba.conf 里的访问控制规则:

# kingbase.conf
listen_addresses = '*'
port = 54321

# sys_hba.conf
# 允许内网段访问
host  all  all  192.168.1.0/24  scram-sha-256

改完这两个文件要 reload 一下配置,不用重启:

sys_ctl -D /data/kingbase/data reload

sys_hba.conf 这个文件相当于数据库的防火墙规则,格式是"连接类型 数据库 用户 地址 认证方式"。scram-sha-256 是目前推荐的密码认证方式,比老的 md5 更安全。如果涉及跨公网的访问,建议走 SSL 连接,在 sys_hba.conf 里用 hostssl 代替 host,强制走加密通道。KES 默认支持 SSL,只需要把证书和密钥放到数据目录下并在 kingbase.conf 里开启 ssl = on 就行。

SQL 开发与日常操作

KES 的 SQL 语法对标准 SQL 的支持很完整,日常开发用到的 DDL、DML、事务控制都没什么问题。这部分不打算写教科书式的内容,重点记一些实际项目中容易忽略的点。

建表与数据类型选择

建表的时候数据类型选择挺有讲究的。我见过不少项目清一色 VARCHAR + INT + TIMESTAMP,把数据库当 Excel 用了。KES 支持的类型比大多数人用得到的要多不少。

CREATE TABLE device_info (
    id          BIGSERIAL PRIMARY KEY,
    device_code VARCHAR(64) NOT NULL UNIQUE,
    device_name VARCHAR(200) NOT NULL,
    category    SMALLINT DEFAULT 1,
    specs       JSONB,
    tags        TEXT[],
    location    POINT,
    status      SMALLINT DEFAULT 1,
    created_at  TIMESTAMP DEFAULT now(),
    updated_at  TIMESTAMP DEFAULT now()
);

-- JSONB 类型特别适合存半结构化的配置信息
INSERT INTO device_info (device_code, device_name, specs)
VALUES (
    'DEV-20260101-001',
    '温湿度传感器-A3',
    '{"protocol": "MQTT", "interval": 30, "unit": "celsius"}'::jsonb
);

-- 查询 JSONB 里的字段
SELECT device_code,
       specs->>'protocol' AS protocol,
       (specs->>'interval')::int AS report_interval
FROM device_info
WHERE specs ? 'protocol';

数组类型存标签、角色列表这类东西很方便,省得建额外的关联表。JSONB 用来存配置项、扩展属性这种半结构化数据,比搞一堆 VARCHAR 列强多了。

事务与并发控制

KES 的事务管理跟标准 SQL 一致,BEGIN / COMMIT / ROLLBACK 这套东西没什么好说的。说一个实际遇到的问题。

有个项目上线后发现频繁出现死锁。排查下来是因为两个业务模块同时更新同一批数据,但更新顺序不一样——模块 A 先更新订单表再更新库存表,模块 B 反过来先更新库存表再更新订单表,并发一高就死锁了。解决方法是保证所有涉及多行更新的业务逻辑按固定顺序操作,开发团队约定了一个统一的表操作优先级规范。

另外,KES 支持 NOWAIT 和 SKIP LOCKED 语法,在高并发抢锁的场景下很有用:

-- 抢不到锁就立即返回错误,不傻等
SELECT * FROM task_queue
WHERE status = 0
FOR UPDATE NOWAIT;

-- 跳过已被其他事务锁定的行,处理下一批
SELECT * FROM task_queue
WHERE status = 0
FOR UPDATE SKIP LOCKED
LIMIT 10;

SKIP LOCKED 特别适合做任务队列这种场景,多个消费者同时取任务,各自拿到不重复的任务去处理,不会互相阻塞。之前有个项目用一张表做消息队列,没有 SKIP LOCKED 之前经常因为锁等待导致任务分发延迟,加上之后吞吐量直接翻了两倍多。所以如果你的业务有类似的并发模型,这两个语法一定要用起来。

批量操作性能

批量插入数据的时候别一条一条 INSERT,用 COPY 命令会快几个数量级。这个经验适用于大多数关系型数据库。COPY 走的是二进制协议,跳过了 SQL 解析和优化的开销,百万级数据的导入通常在十几秒内就能完成:

-- 从 CSV 文件批量导入,速度比 INSERT 快得多
COPY device_info (device_code, device_name, category)
FROM '/data/import/devices.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ',');

-- 如果是程序里拼接批量 INSERT,至少用多值语法
INSERT INTO device_info (device_code, device_name, category)
VALUES
    ('DEV-001', '温度传感器', 1),
    ('DEV-002', '压力传感器', 2),
    ('DEV-003', '流量计', 3);

更新和删除大量数据的时候也有讲究。一次性 DELETE 几千万行会长时间持有大量锁,影响线上业务。建议分批操作,每次处理一小批,中间让出锁:

-- 分批删除过期数据
DO $$
DECLARE
    batch_size INT := 5000;
    deleted INT;
BEGIN
    LOOP
        DELETE FROM sensor_data
        WHERE ctid IN (
            SELECT ctid FROM sensor_data
            WHERE record_time < '2024-01-01'
            LIMIT batch_size
        );
        GET DIAGNOSTICS deleted = ROW_COUNT;
        COMMIT;
        EXIT WHEN deleted < batch_size;
        -- 暂停一下,给其他事务让路
        PERFORM pg_sleep(0.5);
    END LOOP;
END $$;

安全管理:三权分立与数据加密

安全这块是 KES 比较强的地方,毕竟过了等保四级认证的产品。很多政企项目对数据库安全有硬性要求,不达标验收都过不了。KingbaseES 在安全方面做了很多工作,从访问控制到数据加密到审计追踪,形成了一套比较完整的安全防护体系。

三权分立

KES 支持三权分立的安全管理模式,把数据库管理权限拆分成三个角色:系统管理员(SYSSO)负责日常运维和对象管理,安全管理员(SECO)负责安全策略和审计配置,审计管理员(AUDSO)负责审计日志的查看和管理。三个角色互相制约,任何一个人拿不到全部权限。

-- 启用三权分立需要修改配置
-- kingbase.conf 中设置
-- enable_sec_admin = on
-- 改完重启生效

-- 查看当前角色和权限分配
SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolcanlogin
FROM sys_roles
ORDER BY rolname;

三权分离这个设计思路其实跟企业管理里的"不相容职务分离"是一个道理。系统管理员能建表建用户但看不到审计日志,审计管理员能看到所有人的操作记录但改不了数据和配置,安全管理员管策略但碰不到业务数据。

用户和权限管理

权限分配遵循最小化原则,别图省事给普通应用账号 SUPERUSER 权限。我见过好几个项目为了调试方便直接给 dba 权限上线的,后面审计的时候全被打了回来。

-- 创建只读用户
CREATE ROLE readonly_user WITH LOGIN PASSWORD 'Read@2026';
GRANT CONNECT ON DATABASE production TO readonly_user;
GRANT USAGE ON SCHEMA public TO readonly_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;

-- 设置默认权限,以后新建的表也自动有 SELECT 权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO readonly_user;

-- 创建应用用户,只给增删改查权限
CREATE ROLE app_user WITH LOGIN PASSWORD 'App@2026';
GRANT CONNECT ON DATABASE production TO app_user;
GRANT USAGE, CREATE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;

透明数据加密 TDE

KES 支持透明数据加密,也就是 TDE。开启之后数据在磁盘上是加密存储的,读写的时候由数据库引擎自动加解密,应用层完全无感知。对于存储敏感信息的场景,这个功能是刚需。

-- 创建加密表空间
CREATE TABLESPACE encrypted_ts
LOCATION '/data/kingbase/encrypted'
WITH (encrypt_type = 'SM4');

-- 在加密表空间上建表
CREATE TABLE user_identity (
    id          BIGSERIAL PRIMARY KEY,
    user_name   VARCHAR(100) NOT NULL,
    id_card     VARCHAR(18) NOT NULL,
    phone       VARCHAR(20),
    created_at  TIMESTAMP DEFAULT now()
) TABLESPACE encrypted_ts;

加密算法支持国密 SM4,也支持 AES。选型的时候根据合规要求来定,政务类项目一般要求国密算法。需要注意的是,加密表空间对性能有一定影响,大概在 5% 到 10% 左右,具体看数据量和读写比例。

审计配置

审计功能可以记录指定用户或指定操作的访问日志,事后追溯谁在什么时间做了什么操作。开启方式不复杂:

-- 通过安全管理员配置审计策略
-- 记录所有 DDL 操作
SELECT audit_set_rule('audit_ddl', 'on');

-- 记录对敏感表的访问
SELECT audit_set_object('public.user_identity', 'select,insert,update,delete');

-- 查看审计日志
SELECT event_time, username, event_type, object_name, statement
FROM sys_audit_log
WHERE event_time > now() - INTERVAL '1 day'
ORDER BY event_time DESC
LIMIT 50;

审计日志量大的话记得定期归档和清理,别让审计表把磁盘撑满了。我就遇到过这种事,审计开了半年没人管,某天磁盘报警才发现审计日志占了 200 多 G。

备份恢复与高可用

数据备份这事不用多说了,没备份的数据库就是在裸奔。KES 自带的备份工具叫 sys_rman,功能跟 Oracle 的 RMAN 差不多,支持全量备份、增量备份和时间点恢复。

物理备份

# 全量备份
sys_rman -F /data/kingbase/backup backup full

# 增量备份(基于上次全量或增量)
sys_rman -F /data/kingbase/backup backup incremental

# 查看备份集信息
sys_rman -F /data/kingbase/backup show

# 清理过期备份(保留最近 7 天)
sys_rman -F /data/kingbase/backup delete --older-than 7d

建议的备份策略是每周一次全量,每天一次增量,备份保留周期根据业务需要和磁盘空间来定。备份完了别忘了验证,sys_rman 支持 validate 命令:

# 验证备份完整性
sys_rman -F /data/kingbase/backup validate

不验证的备份跟没有备份区别不大。之前有个客户的数据库硬盘坏了,拿备份出来恢复的时候才发现三个月前的某次备份文件就坏了,中间一直没验证过。最后只能恢复到更早的时间点,丢了不少数据。

时间点恢复 PITR

误删数据是 DBA 的噩梦。KES 支持 PITR(Point-In-Time Recovery),可以把数据库恢复到过去任意一个时间点,前提是归档日志要完整。

# 恢复步骤概要
# 1. 停库
sys_ctl -D /data/kingbase/data stop

# 2. 恢复基础备份
sys_rman -F /data/kingbase/backup restore --target-time "2026-06-04 15:30:00"

# 3. 配置恢复目标
# 在 kingbase.auto.conf 中设置
# recovery_target_time = '2026-06-04 15:30:00'
# recovery_target_action = 'promote'

# 4. 启动恢复
sys_ctl -D /data/kingbase/data start

PITR 的前提是持续归档要正常。归档配置在 kingbase.conf 里:

archive_mode = on
archive_command = 'cp %p /data/kingbase/archive/%f'

归档目录别跟数据目录放在同一块盘上,盘坏了就全没了。有条件的话用 NFS 或者对象存储做归档目的地。

高可用集群

生产环境的 KES 一般部署成主备集群。主库处理读写请求,备库通过流复制实时同步数据。主库挂了可以手动切换也可以自动切换。KES 自带的高可用组件能实现自动故障检测和切换,RTO 通常控制在 30 秒以内。

# 备库搭建:基于主库做基础备份
sys_basebackup -h primary_host -p 54321 -U replication_user \
  -D /data/kingbase/standby \
  -Fp -Xs -P

# 备库配置 recovery 参数
# kingbase.auto.conf
primary_conninfo = 'host=primary_host port=54321 user=replication_user password=xxx'
hot_standby = on

流复制有两种模式:同步复制保证 RPO 为零,每条事务至少在备库写了一份 WAL 才算提交成功;异步复制性能更好但可能丢少量数据。关键业务用同步,非关键业务用异步,看具体取舍。

-- 查看复制状态
SELECT pid, usename, application_name, client_addr,
       state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM sys_stat_replication;

这里有个要注意的地方:同步复制对网络延迟很敏感。如果主备之间网络延迟超过 5 毫秒,写入性能就会明显下降。跨机房部署的时候测一下延迟再决定用同步还是异步。

日常监控与性能诊断

数据库监控做得好不好直接决定你能不能提前发现问题。等用户打电话说"系统怎么这么慢"再去查,往往已经晚了。我习惯把监控分成三层:第一层是操作系统级别的,CPU、内存、磁盘 IO、网络带宽;第二层是数据库实例级别的,连接数、事务量、锁等待、缓存命中率;第三层是 SQL 级别的,慢查询、执行计划、索引使用情况。这篇文章重点说后两层。

KWR 性能报告

KES 内置了一个叫 KWR(Kingbase Workload Repository)的性能采集工具,功能跟 Oracle 的 AWR 报告很像。它会周期性地给数据库拍快照,记录各种性能指标的累积值。对比两个快照之间的差异就能看出这段时间数据库的负载情况。

-- 确认 KWR 扩展已安装
CREATE EXTENSION IF NOT EXISTS sys_kwr;

-- 手动创建一个快照
SELECT sys_kwr_snapshot();

-- 生成两个快照之间的性能报告
-- 先查看快照 ID
SELECT snap_id, snap_time FROM sys_kwr_snapshots ORDER BY snap_id DESC LIMIT 10;

-- 生成报告(输出到文件)
\o /tmp/kwr_report.html
SELECT sys_kwr_report(101, 105, 'html');
\o

KWR 报告里的信息量很大,我一般重点看几个部分:等待事件排名、TOP SQL(按总耗时和调用次数排序)、缓存命中率、检查点统计。如果某个等待事件突然飙升,基本就能定位到瓶颈在哪。

活跃会话分析

KSH(Kingbase Session History)记录每个活跃会话在采样时刻的等待事件和执行信息,粒度比 KWR 更细。适合排查某个时间点的性能抖动。

-- 启用 KSH
CREATE EXTENSION IF NOT EXISTS sys_ksh;

-- 查看最近 5 分钟最耗时的等待事件
SELECT wait_event_type, wait_event, count(*)
FROM sys_ksh
WHERE sample_time > now() - INTERVAL '5 minutes'
GROUP BY 1, 2
ORDER BY 3 DESC
LIMIT 10;

-- 查看某段时间内执行最慢的 SQL
SELECT query_id, query, calls, total_time, mean_time
FROM sys_ksh_statements
WHERE sample_time > now() - INTERVAL '1 hour'
ORDER BY mean_time DESC
LIMIT 10;

实时会话与锁监控

日常巡检的时候经常要看当前有没有长时间运行的事务、有没有锁等待。几条常用查询:

-- 当前活跃会话
SELECT pid, usename, application_name, client_addr,
       state, wait_event_type, wait_event,
       now() - query_start AS duration, query
FROM sys_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;

-- 锁等待分析
SELECT blocked.pid AS blocked_pid,
       blocked.query AS blocked_query,
       blocking.pid AS blocking_pid,
       blocking.query AS blocking_query,
       now() - blocked.query_start AS wait_duration
FROM sys_stat_activity blocked
JOIN sys_locks l ON blocked.pid = l.pid AND NOT l.granted
JOIN sys_locks granted ON l.locktype = granted.locktype
    AND l.database IS NOT DISTINCT FROM granted.database
    AND l.relation IS NOT DISTINCT FROM granted.relation
    AND granted.granted = true
JOIN sys_stat_activity blocking ON granted.pid = blocking.pid
WHERE blocked.pid != blocking.pid;

-- 长时间未提交的事务(超过 5 分钟)
SELECT pid, usename, now() - xact_start AS xact_duration, query
FROM sys_stat_activity
WHERE state = 'idle in transaction'
  AND now() - xact_start > INTERVAL '5 minutes'
ORDER BY xact_duration DESC;

idle in transaction 这种状态特别值得警惕。事务打开了但没有提交,一直挂着,持有的锁不释放。如果挂太久,VACUUM 都没法回收死元组,表会越来越大。建议在 kingbase.conf 里设个超时:

idle_in_transaction_session_timeout = 300000  -- 5 分钟,单位毫秒

磁盘和表空间监控

写个简单的巡检脚本定期跑一下,把表空间使用情况、大表列表、索引膨胀率这些都采集出来。不用搞得太复杂,shell 脚本加上 ksql 就够用:

#!/bin/bash
# db_check.sh - 简单巡检脚本
DATA_DIR="/data/kingbase/data"
KSQL="ksql -U system -d production -t -A -c"

echo "===== 磁盘使用 ====="
df -h $DATA_DIR

echo ""
echo "===== 数据库大小 ====="
$KSQL "SELECT datname, sys_size_pretty(sys_database_size(datname))
       FROM sys_database ORDER BY sys_database_size(datname) DESC;"

echo ""
echo "===== TOP 10 大表 ====="
$KSQL "SELECT schemaname||'.'||relname AS table_name,
       sys_size_pretty(sys_total_relation_size(relid)) AS total_size,
       n_live_tup AS row_count
       FROM sys_stat_user_tables
       ORDER BY sys_total_relation_size(relid) DESC LIMIT 10;"

echo ""
echo "===== 未使用的索引 ====="
$KSQL "SELECT schemaname||'.'||indexrelname AS index_name,
       sys_size_pretty(sys_relation_size(indexrelid)) AS size,
       idx_scan AS scan_count
       FROM sys_stat_user_indexes
       WHERE idx_scan = 0
       ORDER BY sys_relation_size(indexrelid) DESC LIMIT 10;"

echo ""
echo "===== 表膨胀估算 ====="
$KSQL "SELECT schemaname||'.'||relname AS table_name,
       n_dead_tup AS dead_tuples,
       round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_ratio
       FROM sys_stat_user_tables
       WHERE n_dead_tup > 10000
       ORDER BY n_dead_tup DESC LIMIT 10;"

这种脚本配合 crontab 每天跑一次,结果发个邮件或者写到共享目录里,巡检效率会高很多。

常见问题与排查思路

最后记几个实际遇到过的典型问题。

连接数打满

应用突然连不上数据库,报错 "sorry, too many clients already"。第一反应是查 max_connections,但光加大这个参数治标不治本。

-- 看看到底是哪些连接占着
SELECT state, count(*) FROM sys_stat_activity GROUP BY state;
-- 看各个来源 IP 的连接数
SELECT client_addr, count(*) FROM sys_stat_activity
WHERE client_addr IS NOT NULL
GROUP BY client_addr ORDER BY 2 DESC;

常见原因有这么几种:应用端连接池没配好,连接泄漏了没归还;idle in transaction 的连接太多占着坑不干活;max_connections 本身设太小了。如果并发确实高,在前面挡一层连接池中间件比直接加 max_connections 靠谱得多。

慢查询定位

用户反馈某个功能特别慢。先在日志里找慢 SQL——前面配置了 log_min_duration_statement = 1000,超过 1 秒的查询都会记到日志里。日志文件在数据目录下的 sys_log 子目录里,用 grep 搜 "duration" 关键字就能快速定位。当然,如果你的慢查询阈值设得比较低(比如 500 毫秒),日志量会比较大,建议只在排查问题的时候临时调低,排查完了改回来。

-- 也可以直接从视图里查
SELECT query, calls, total_time, mean_time, rows
FROM sys_stat_statements
WHERE mean_time > 500
ORDER BY mean_time DESC
LIMIT 20;

拿到慢 SQL 之后用 EXPLAIN ANALYZE 看执行计划,重点关注是不是走了全表扫描、Nested Loop 嵌套层数是不是太多、有没有临时文件排序。大多数性能问题都是缺索引或者索引选错了导致的。

-- 看执行计划
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT d.device_name, avg(s.temperature) AS avg_temp
FROM sensor_data s
JOIN device_info d ON s.device_id = d.id
WHERE s.record_time > now() - INTERVAL '7 days'
GROUP BY d.device_name
ORDER BY avg_temp DESC;

VACUUM 相关问题

KES 用 MVCC 机制管理数据版本,删除和更新操作不会真正移除旧数据行,而是标记为死元组。VACUUM 负责回收这些死元组占用的空间。如果 VACUUM 跟不上写入速度,表就会持续膨胀,查询性能也会下降——因为扫描的时候要跳过大量的死元组,白白浪费 IO。

这个问题平时不容易发现,等到表膨胀得很厉害了才会暴露出来。我碰到过一个表,业务上每天大量更新,autovacuum 一直追不上写入速度,半年下来表的物理大小涨了将近三倍,但实际有效数据行只多了 30%。

-- 查看哪些表需要 VACUUM
SELECT schemaname||'.'||relname AS table_name,
       n_dead_tup AS dead_tuples,
       n_live_tup AS live_tuples,
       last_vacuum, last_autovacuum
FROM sys_stat_user_tables
WHERE n_dead_tup > 10000
  AND n_dead_tup > n_live_tup * 0.1
ORDER BY n_dead_tup DESC;

-- 手动 VACUUM 某个表(带分析)
VACUUM ANALYZE sensor_data;

-- 看 autovacuum 是否正常工作
SELECT pid, query, now() - query_start AS duration
FROM sys_stat_activity
WHERE query LIKE 'autovacuum%'
ORDER BY duration DESC;

autovacuum 一般不用手动干预,但对于写入量特别大的表,默认的 autovacuum 参数可能不够激进,可以适当调大 autovacuum_vacuum_scale_factor 和 autovacuum_analyze_scale_factor。

总结

这篇文章覆盖了 KES 数据库从安装到日常运维的主要操作环节。部署环节的关键是环境初始化和参数调优,特别是内存参数和兼容模式的选择,这两项一旦定下来后面改动成本很高;安全方面三权分立和 TDE 是 KingbaseES 比较有特色的功能,政务和金融项目基本都要用上,审计日志的存储规划也要提前做好;备份恢复要形成制度,全量加增量的组合策略加上定期验证,确保关键时刻真的能恢复出来;监控诊断靠 KWR 和 KSH 这两个内置工具就能搞定大部分场景,配合一个简单的巡检脚本基本够用了。

KES 这几年迭代速度挺快,从 V8 到 V9 在性能和易用性上都有明显进步。用的过程中遇到问题多看官方文档,文档中心 help.kingbase.com.cn 上的内容还是比较全的。另外社区里也有不少实践经验可以参考,碰到坑的时候搜一搜往往能找到类似的解决思路。

数据库运维这个活儿说到底就是"预防为主、治疗为辅"。备份做好、监控到位、定期巡检,大部分问题都能在酿成事故之前处理掉。与其花三天时间恢复一个本可以避免的故障,不如每天花十分钟看看监控数据。这话虽然老生常谈,但真正做到的人确实不多。共勉。