干了这么多年的数据库运维,我越来越觉得归档重做日志这东西就像汽车的行车记录仪------平时没人注意,但一旦出事故,它就是唯一的"证人"。今天我就把这几年跟金仓数据库归档重做日志打交道的经验,从概念、配置到运维,一次性聊透。
前言:为什么归档重做日志如此重要
去年有个项目,客户的生产环境因为误操作删了一张核心业务表,急得团团转。我远程连上去一看,还好之前配置了归档重做日志,最终通过时间点恢复把数据找回来了。那一刻我就意识到,归档重做日志是数据库最后一道防线。
KingbaseES(金仓数据库)的归档重做日志记录了数据库所有事务的变更历史,有了它,你就可以:
- 实现时间点恢复(PITR):恢复到故障发生前的任意时刻
- 构建高可用集群:主备同步的基础
- 满足合规审计要求:金融、政务等行业的数据追溯需求
但很多运维人员对归档重做日志的管理还是一知半解,要么不知道怎么开启,要么开启了不维护,最后归档日志堆积把磁盘撑爆。这篇文章就是要把这些问题一次性讲清楚。
一、归档重做日志的基本概念
在开始动手之前,咱们先搞清楚什么是归档重做日志。

KingbaseES数据库采用**预写式日志(WAL,Write-Ahead Logging)**机制:所有数据修改操作必须先写入WAL日志,然后才更新数据文件【turn0search26】。WAL日志也称为重做日志,因为当数据库出现宕机发生数据丢失时,可以重新执行WAL日志来达到恢复数据库的目的【turn0search9】。
归档重做日志,简单来说,就是将发生切换的重做日志段文件存储到其他位置的过程【turn0search12】【turn0search22】【turn0search30】。从逻辑上来看,KingbaseES数据库会产生一个无限长的顺序重做日志记录序列。KingbaseES在物理上把这个重做日志记录序列分割成多个重做日志段(每个重做日志为一个重做日志段),重做日志段文件被重用或删除时进行归档备份操作,把将被重用的重做日志段中的日志记录保存到其他位置【turn0search22】。
默认情况下,单个WAL预写日志文件的大小是16MB【turn0search9】。WAL日志文件名称为16进制的24个字符组成,每8个字符一组,分别代表时间线、逻辑ID和物理ID【turn0search9】。
二、开启和关闭归档模式
在KingbaseES数据库启动之前,必须决定是否开启归档模式【turn0search12】【turn0search22】【turn0search30】。是否启用归档的选择取决于在数据库上运行的应用程序的可用性和可靠性要求。如果由于故障发生时,您想回退到发生故障之前的位置,请开启归档重做日志文件【turn0search22】。
2.1 开启归档重做日志
当开启归档重做日志文件,重做日志将在发生切换的时候进行归档【turn0search12】【turn0search22】【turn0search30】。当使用物理备份方式对数据库进行备份,归档重做日志可以使数据库在启动恢复的时候恢复到之前的位置【turn0search22】。
要开启归档模式,需要修改kingbase.conf配置文件,设置以下关键参数【turn0search3】【turn0search6】【turn0search13】:
ini
# 开启归档模式
archive_mode = on
# 配置归档命令,将WAL日志复制到指定目录
archive_command = 'cp %p /data/kingbase/archive/%f'
# 设置WAL级别,至少设置为replica
wal_level = replica
注意 :archive_command中的%p会被替换成要被归档的文件的路径名,%f会被替换成文件名(路径名是相对于服务器的工作目录,即集簇的数据目录)【turn0search22】。
修改配置后,需要重启数据库使配置生效【turn0search3】:
bash
sys_ctl restart -D /data/kingbase/data
或者使用在线重载方式(如果版本支持):
sql
SELECT sys_reload_conf();
2.2 关闭归档重做日志
当关闭归档重做日志,重做日志将在回收或删除的时候,没有重做日志的拷贝【turn0search12】【turn0search22】【turn0search30】。在没有使用归档重做日志时,KingbaseES通常只创建少量段文件,并且通过重命名不再使用的重做日志段文件为更高的段编号来"回收"它们【turn0search22】。
关闭归档模式只需要将archive_mode设置为off即可:
ini
archive_mode = off
同样需要重启数据库才能生效。
2.3 归档模式的选择:on、off和always
archive_mode参数有多个选项【turn0search12】【turn0search22】【turn0search30】:
- on :开启归档模式。在普通操作期间,与
always参数没有区别。 - off:禁用归档模式。
- always :在普通操作期间,与
on参数没有区别。但是当设置为always时,重做日志归档进程在归档恢复或者后备模式下也会被启用,所有从归档恢复或者用流复制传来的重做日志文件将被(再次)归档。
建议 :生产环境通常设置为on或always。如果使用主备集群,建议设置为always,这样备库也会归档日志,避免单点故障。
三、控制归档
KingbaseES提供了多种控制归档的方式,包括自动触发、定时触发和手动执行【turn0search12】【turn0search22】【turn0search30】。
3.1 自动触发归档
当启动归档模式时,重做日志文件写满后开始写下一个重做日志文件,此时KingbaseES将执行archive_command配置参数指定的shell命令将写满的重做日志段文件进行归档【turn0search22】。
这是最常用的归档方式,无需人工干预。
3.2 定时触发归档
KingbaseES中可以通过archive_timeout配置参数来强制服务器定期切换到新的重做日志段文件【turn0search22】。如果指定值时没有单位,则以秒为单位。这个参数只能在kingbase.conf文件中或在服务器命令行上设置。
当archive_timeout配置参数大于0时,只要从上次段文件切换后过了参数所设置的时间量,并且已经有过任何数据库活动(包括一个单一检查点),服务器将切换到一个新的段文件(如果没有数据库活动则会跳过检查点)【turn0search22】。
适用场景:写入量很少的系统,确保归档日志不会间隔太长时间,减少数据丢失窗口。
ini
# 每5分钟强制切换一次日志并归档
archive_timeout = 300s
3.3 手动执行归档
在KingbaseES中,当使用sys_switch_wal系统函数时切换重做日志,这时将触发重做日志归档【turn0search22】。
sql
SELECT sys_switch_wal();
使用场景:需要在特定时间点确保归档完成,比如备份前。
四、指定归档目标
在归档重做日志之前,您必须确定要归档的目标【turn0search12】【turn0search22】【turn0search30】。KingbaseES不对如何归档做任何假设,而是让管理员提供一个shell命令来拷贝一个完整的重做日志文件到备份存储位置【turn0search22】。
4.1 设置存档目标的初始化参数
您可以在kingbase.conf指定归档重做日志的拷贝命令【turn0search12】【turn0search22】【turn0search30】。KingbaseES使用archive_command配置参数指定本地shell命令,执行一个完成的重做日志文件段的归档【turn0search22】。
archive_command中的控制符【turn0search22】:
%p被替换成要被归档的文件的路径名%f只被文件名替换(路径名是相对于服务器的工作目录,即集簇的数据目录)- 如果要在命令里嵌入一个真正的%字符,可以使用
%%
配置示例:
ini
# 简单拷贝到本地目录
archive_command = 'cp %p /data/kingbase/archive/%f'
# 使用rsync远程归档到备份服务器
archive_command = 'rsync -a %p backup_server:/archive/%f'
# 带校验的归档命令,防止重复归档
archive_command = 'test ! -f /data/kingbase/archive/%f && cp %p /data/kingbase/archive/%f'
重要提示 :archive_command指定的shell命令只在成功时返回一个零作为退出状态【turn0search22】。如果命令执行失败,归档会被临时禁用,但服务器仍会继续累计重做日志段文件,期待着一个命令被提供【turn0search22】。
4.2 归档目录规划与权限
归档目录需要提前创建,并设置正确的权限【turn0search3】:
bash
# 创建归档目录
mkdir -p /data/kingbase/archive
# 设置目录权限,确保数据库用户有读写权限
chown -R kingbase:kingbase /data/kingbase/archive
chmod 700 /data/kingbase/archive
生产环境建议:
- 归档目录应与数据目录分离,避免单点故障
- 使用独立的磁盘或存储,避免归档IO影响数据库性能
- 定期监控归档目录空间使用情况
五、查看归档重做日志状态
KingbaseES在数据集簇的sys_wal/archive_status目录下记录了每一重做日志段文件的状态文件【turn0search12】【turn0search22】【turn0search30】。状态文件的前缀与段文件同名,以表示时间顺序的整数形式命名。状态文件后缀为.ready或者.done,代表段文件的归档状态【turn0search22】。
5.1 归档状态文件
.ready:等待归档.done:已完成归档
bash
# 查看等待归档的文件
ls -l $KINGBASE_DATA/sys_wal/archive_status/*.ready
# 查看已归档的文件
ls -l $KINGBASE_DATA/sys_wal/archive_status/*.done
5.2 归档状态查询
在数据库内部,可以使用系统视图查看归档状态:
sql
-- 查看归档进程状态
SELECT * FROM sys_stat_archiver;
-- 查看当前WAL位置
SELECT sys_current_wal_lsn();
-- 查看WAL文件名
SELECT sys_walfile_name(sys_current_wal_lsn());
5.3 归档失败状态
配置参数archive_command指定的shell命令执行失败,或未指定归档命令(默认为空),重做日志归档会被临时禁用,但服务器仍会继续累计重做日志段文件【turn0search22】。
警告 :长期归档失败会导致磁盘空间耗尽。如果将archive_command设置为一个只返回真但不做任何事的命令(例如/bin/true),实际上会禁用归档,也会打破归档恢复所需的重做日志文件链,因此只有在极少数情况下才能用【turn0search22】。
六、运维实践与故障排查
干了这么多年运维,我踩过不少坑。这一节我把平时怎么监控归档、遇到问题怎么排查的经验掰开揉碎讲给你听。
6.1 日常监控指标
我平时会盯着这几个指标看,其实说白了就是看归档到底有没有在正常干活。
第一个是看归档到底成功了没。金仓里面有个视图叫sys_stat_archiver,你查一下last_archived_time,就知道最近一次归档是什么时候完成的。这个值要是离现在太远,那就有问题了,得赶紧看看怎么回事。
第二个是归档延迟。也就是说,从WAL切换到归档完成,中间隔了多长时间。这个时间差太长的话,说明归档过程可能卡住了,或者磁盘IO太慢。
第三个得看归档目录占了多少空间。这个简单,直接用df -h命令就行了。我一般把告警阈值设在80%,到了就去看看到底是什么情况。
第四个是WAL产生的速度。其实就是要知道每分钟会蹦出来多少个WAL文件。心里有数了,你才能算出来归档目录大概要用多大的磁盘。
6.2 空间规划与清理
归档日志这东西有个特点,就是会一直涨,你不清理它就一直占着地方。我之前有个客户,归档目录配了200G,结果三个月就满了,数据库直接变慢,业务部门天天打电话催。
所以空间规划得提前算好。我的算法是这样的:
所需空间 = WAL产生速度(GB/h) × 保留时间(h) × 安全系数(1.2~1.5)
给你举个例子吧。假设你的系统每小时产生2GB的WAL,你想保留7天,也就是168小时。那么算下来就是2乘以168再乘以1.3,大概需要436.8GB的空间。也就是说,你至少得准备500GB的磁盘,不然迟早会满。
清理策略嘛,我一般用两种。一种是按时间来,超过30天的直接删掉。另一种是看备份情况,已经备份到远端的,本地就可以清理了。
清理命令我常这么写:
bash
# 清理30天前的归档日志
find /data/kingbase/archive -mtime +30 -delete
# 使用sys_archivecleanup工具清理(需要指定基础备份后的第一个WAL文件)
sys_archivecleanup /data/kingbase/archive 000000010000000000000001
其实第一种方法最简单,也最不容易出错。第二种方法得知道基础备份后的第一个WAL文件是什么,稍微麻烦点,但清理得更精准。
6.3 常见故障排查
这部分我讲几个我实际碰到过的故障,都是真实案例,希望你别再踩我踩过的坑。
故障一:归档失败
这个故障的现象很明确,sys_stat_archiver视图里failed_count增加了,或者你去看归档目录,发现好久没有新文件进来了。
碰到这种情况,我一般这么排查。先检查archive_command配置对不对,有没有拼写错误。然后我会手动去执行一遍归档命令,看看报什么错。接着看归档目录的权限对不对,数据库用户能不能写进去。最后看磁盘空间够不够。
我记得有个项目,归档命令里路径写错了,导致归档一直失败,但没人发现,结果WAL文件在数据目录里堆了一大堆,差点把数据盘也撑爆了。所以这个问题得及时发现,及时处理。
故障二:归档目录磁盘满
这个更直接,数据库会变慢,甚至写不进去数据。
碰到这种情况,我先用df -h看看归档目录所在的磁盘到底用了多少。然后确认一下归档是不是失败了,导致文件没清走。还得检查一下WAL产生速度是不是异常,有没有什么大事务在疯狂写日志。
处理方法很简单,就是赶紧清理掉过期的归档日志,让空间释放出来。然后看看是不是有异常事务在捣乱,该杀的杀掉。如果长期看空间还是不够,那就得考虑加磁盘了。
故障三:归档日志断档
这个故障最隐蔽,平时你看不出来,等你需要恢复的时候才发现找不到所需的WAL文件,那时候就晚了。
我碰到过一次,客户需要恢复到某个时间点,结果发现归档日志中间缺了一段,死活恢复不过去。排查发现是那段时间归档命令配置错了,导致某些WAL文件没归档成功,但也没有人发现。
所以我的建议是,定期检查一下归档目录里的WAL文件是不是连续的。看看归档日志里面有没有报错。如果是主备集群的话,还得确认主备同步是不是正常。
解决办法嘛,看看能不能从备份或者其他节点补齐缺失的WAL文件。然后赶紧修复归档配置,防止以后再断档。
6.4 归档日志与备份集成
归档日志这东西,单独用其实意义不大,得跟物理备份配合起来,才能真正发挥作用,实现时间点恢复。
我常用的备份策略是这样的:
- 周日:做一个全量备份
- 周一到周六:每天做增量备份
- 持续进行:归档WAL日志
这样配合起来,你就可以恢复到过去一周内的任意时间点了。恢复流程也很简单,先把基础备份恢复回去,然后按时间顺序把归档的WAL日志重放一遍,直到你想要的那个时间点。
具体命令大概长这样:
bash
# 恢复全量备份
sys_rman --backup-path /data/kingbase_backup restore --set=full_backup_2025_01_01
# 应用归档日志
sys_rman --backup-path /data/kingbase_backup restore --type=time --target='2025-01-02 10:00:00'
我有个客户用这套方案,有一次误删了一张表,我用归档日志帮他们恢复到了误删前的状态,前后不到半小时,客户特别满意。
七、最佳实践总结
干了这么多年,我总结了归档重做日志管理的几点心得,都是实打实的经验,希望对你有帮助。
第一点,生产环境一定要开归档模式。不开归档的话,你连时间点恢复都做不了,出了问题只能恢复到最近一次备份的时间点,中间的数据全丢了。
第二点,归档目录要跟数据目录分开。最好用不同的磁盘,这样万一数据盘坏了,归档日志还在,你还能恢复。我用一个客户的例子,数据盘坏了,但归档日志放在另一块盘上,最后数据全找回来了。
第三点,归档命令要写好。我会加个校验,防止重复归档。就像这样:test ! -f /data/kingbase/archive/%f && cp %p /data/kingbase/archive/%f。
第四点,平时要盯着点归档状态。我一般会写个脚本,定期查一下sys_stat_archiver视图,看看归档有没有失败,顺便看看归档目录空间还剩多少。
第五点,过期归档要定期清理。别等磁盘满了才想起来,那时候就晚了。我会设个定时任务,每周清理一次超过保留期的归档日志。
第六点,归档要跟备份策略结合起来。光有归档没备份,或者光有备份没归档,都不行。两者配合起来,才能实现完整的数据保护。
第七点,恢复流程要定期演练。别以为配置好了就万事大吉,你得真的去测一下,确保归档日志真的能用。我见过太多配置了归档但从来没测试过恢复的,真出问题了才发现根本恢复不了。
第八点,主备集群两边都要开归档。特别是设置成always模式,这样备库也会归档日志,避免单点故障。
第九点,低写入系统要设置合理的archive_timeout。有些系统写入量很少,可能几天都切换不了一个WAL文件,这时候就得设置个超时,强制归档,减少数据丢失窗口。
第十点,归档配置的变更要记录下来。什么时候改的配置,改了什么,都要记下来。不然出了问题,你都不知道是什么时候改的配置导致的。
结语
归档重做日志这东西,说白了就是数据库的"行车记录仪"。平时没人在意它,但真出了事故,它就是救命的稻草。
这篇文章我写了归档的基本概念、怎么配置、怎么运维、出问题了怎么排查,都是我这些年的实际经验。希望能帮你把归档重做日志管起来,别像我刚入行那会儿,等到出了问题才发现归档没配置,或者配置了但从来没维护过。
有具体问题的话,比如归档目录怎么规划、清理策略怎么定、故障怎么排查,欢迎留言,我看到会回复。