从一次磁盘告警说起:我是如何用KingbaseES系统函数排查并清理‘空间刺客’的
从磁盘告警到精准清理:KingbaseES空间治理实战手记
凌晨三点,手机突然响起刺耳的告警声——生产环境磁盘使用率突破95%红线。作为运维负责人,这种深夜告警往往意味着不眠之夜。但这次经历让我对KingbaseES的空间治理有了全新认知。本文将完整还原从告警触发到问题根治的全过程,不仅包含实用的系统函数应用技巧,更会分享如何建立预防性监控体系,让"空间刺客"无所遁形。
1. 危机响应:告警初现与快速定位
当磁盘空间告警响起时,首要任务是确定问题范围。通过df -h确认是数据盘爆满后,立即连接到KingbaseES实例进行初步诊断:
-- 查看所有数据库大小排序 SELECT datname, sys_size_pretty(sys_database_size(datname)) AS size FROM sys_database ORDER BY sys_database_size(datname) DESC;查询结果显示主业务库kapp已达1.6TB,远超正常水平。进一步分析各schema占比:
-- 按schema统计空间占用 SELECT schemaname, sum(sys_total_relation_size(relid)) AS total_bytes, sys_size_pretty(sum(sys_total_relation_size(relid))) AS total_size FROM sys_stat_user_tables GROUP BY schemaname ORDER BY total_bytes DESC;关键发现:loggingschema占用了总空间的72%,明显异常。这提示我们可能遇到了日志表无限增长的问题。
2. 深度排查:定位"空间刺客"真身
锁定问题schema后,需要精确找到具体的问题表。KingbaseES提供了多层次的尺寸分析函数:
-- 查看logging schema下前10大表 SELECT relname, sys_size_pretty(sys_relation_size(relid)) AS table_size, sys_size_pretty(sys_total_relation_size(relid)) AS total_size FROM sys_stat_user_tables WHERE schemaname = 'logging' ORDER BY sys_total_relation_size(relid) DESC LIMIT 10;查询结果揭示了一个惊人的事实:api_request_log表单独占用了890GB空间!进一步分析表结构:
-- 查看表定义和索引情况 \d+ logging.api_request_log -- 查看表膨胀情况 SELECT n_dead_tup, last_vacuum, last_autovacuum FROM sys_stat_user_tables WHERE relname = 'api_request_log';问题确诊:
- 该表未设置任何保留策略,存储了5年来的全量API日志
- 从未进行过vacuum操作,死元组占比高达40%
- 缺乏有效索引导致查询性能低下
3. 清理方案:安全释放空间的三步策略
面对近1TB的日志表,简单执行TRUNCATE可能引发业务风险。我们采用了渐进式清理方案:
3.1 阶段一:历史数据归档
-- 创建归档表 CREATE TABLE logging.api_request_log_archive (LIKE logging.api_request_log); -- 迁移两年外数据 INSERT INTO logging.api_request_log_archive SELECT * FROM logging.api_request_log WHERE request_time < now() - interval '2 years'; -- 验证数据一致性 SELECT count(*) FROM logging.api_request_log_archive;3.2 阶段二:分区表改造
-- 创建按月分区表 CREATE TABLE logging.api_request_log_new ( LIKE logging.api_request_log ) PARTITION BY RANGE (request_time); -- 创建默认分区 CREATE TABLE logging.api_request_log_default PARTITION OF logging.api_request_log_new DEFAULT; -- 数据迁移 INSERT INTO logging.api_request_log_new SELECT * FROM logging.api_request_log WHERE request_time >= now() - interval '2 years';3.3 阶段三:自动化清理策略
-- 设置表自动vacuum参数 ALTER TABLE logging.api_request_log_new SET ( autovacuum_enabled = on, autovacuum_vacuum_threshold = 5000, autovacuum_analyze_threshold = 2000 ); -- 创建定期清理函数 CREATE OR REPLACE FUNCTION logging.clean_old_logs() RETURNS void AS $$ BEGIN DROP TABLE IF EXISTS logging.api_request_log; ALTER TABLE logging.api_request_log_new RENAME TO api_request_log; -- 自动创建下个月分区 EXECUTE format('CREATE TABLE logging.api_request_log_%s PARTITION OF logging.api_request_log FOR VALUES FROM (%L) TO (%L)', to_char(now() + interval '1 month', 'YYYY_MM'), date_trunc('month', now() + interval '1 month'), date_trunc('month', now() + interval '2 month')); END; $$ LANGUAGE plpgsql;4. 防御体系:构建空间监控生态
经历此次事件后,我们建立了三层防御体系:
4.1 实时监控看板
-- 创建空间监控视图 CREATE VIEW admin.storage_monitor AS SELECT schemaname, relname, sys_size_pretty(sys_total_relation_size(relid)) AS size, n_live_tup, n_dead_tup, round((n_dead_tup::float/n_live_tup)*100,2) AS dead_ratio FROM sys_stat_user_tables ORDER BY sys_total_relation_size(relid) DESC;4.2 自动化告警规则
#!/bin/bash # 每日空间检查脚本 CRITICAL=$(ksql -U monitor -d kapp -t -c \ "SELECT count(*) FROM admin.storage_monitor WHERE size ~ 'GB' AND dead_ratio > 20 OR size ~ 'TB';") if [ $CRITICAL -gt 0 ]; then send_alert "发现空间异常表:$CRITICAL 个" fi4.3 定期维护流程
维护日历表示例:
| 任务类型 | 执行频率 | 检查项 |
|---|---|---|
| Vacuum分析 | 每周 | 死元组>10%的表 |
| 分区维护 | 每月 | 自动创建新分区 |
| 归档检查 | 每季度 | 确认归档策略有效性 |
| 容量规划 | 每半年 | 预测未来增长需求 |
5. 进阶技巧:空间优化锦囊
在实际运维中,我们还发现了一些值得分享的优化技巧:
索引瘦身方案:
-- 重建膨胀索引 REINDEX INDEX CONCURRENTLY logging.idx_api_request_time; -- 使用部分索引优化 CREATE INDEX idx_api_active_requests ON logging.api_request_log (request_id) WHERE status != 'completed';TOAST表优化:
-- 检查TOAST表大小 SELECT relname, sys_size_pretty(sys_total_relation_size(reltoastrelid)) AS toast_size FROM sys_class WHERE relkind = 'r' AND sys_total_relation_size(reltoastrelid) > 0;压缩大对象:
-- 启用压缩存储 ALTER TABLE logging.api_request_log ALTER COLUMN request_body SET STORAGE EXTERNAL;这次事件给我们的最大启示是:数据库空间管理不是一次性任务,而是需要持续优化的系统工程。现在,我们团队每周都会例行检查admin.storage_monitor视图,就像查看天气预报一样自然。当再次看到磁盘使用率图表时,不再是紧张而是从容——因为我们知道,每一个字节都在掌控之中。
