金仓数据库使用sys_walfile_name函数时的时间线问题排查指南
1. 问题现象:备库升主后查询的WAL文件名时间线不符
某次主备切换后,执行以下操作:
- 原主库时间线为
00000001
,备库正常同步。
记录一个lsn和对应的wal日志
select sys_current_wal_lsn();
SELECT sys_walfile_name('0/BD49920');
- 主库故障,触发备库升主,新主库时间线变为
00000002
。 - 在新主库上,尝试查询旧LSN(
0/BD49920
)对应的WAL文件名:SELECT sys_walfile_name('0/BD49920'); -- 返回结果:00000002000000000000000B
- 检查旧主库的WAL日志,发现实际文件名应为
00000001000000000000000B
。
现象总结:
函数返回的时间线(00000002
)与LSN实际所属的时间线(00000001
)不符!
2. 问题分析:为什么会时间线对不上?
2.1 时间线的核心作用
- **时间线(Timeline)**是kingbaseES的“版本分支标识”。
- 每次主备切换会生成新时间线(如
00000001
→00000002
),防止WAL日志覆盖或混淆历史数据分支。 - 关键规则:新时间线的WAL文件名必须包含新的时间线号,且旧时间线的WAL日志会保留。
2.2 sys_walfile_name()
的设计限制
- 函数逻辑:仅通过数学公式计算LSN对应的文件名,不检查历史时间线!
文件名 = 时间线(8位) + 逻辑日志号(8位) + 段号(8位)
- 存在的问题:函数输出的时间线部分始终是当前数据库的时间线,而非LSN实际所属的时间线。
- 本例问题:新主库时间线为
00000002
,函数强制将任何LSN的时间线部分填充为00000002
,导致结果错误。
2.3 时间线切换记录在哪里?
- 每次时间线切换会生成
.history
文件(如sys_wal/00000002.history
),记录时间线切换点的LSN。 - 此文件是追踪LSN与时间线映射关系的唯一依据,但
sys_walfile_name()
未关联此信息!
3. 解决方案:如何正确获取历史LSN对应的WAL文件名?
3.1 手动查询时间线历史
定位时间线切换点:
-- 查询新时间线对应的.history文件
SELECT * FROM sys_read_file('pg_wal/00000003.history') AS tli_history;
输出示例:
- 含义:时间线
00000002
从LSN0/D0000A0
开始生效。 - 若目标LSN(如
0/BD49920
)小于0/D0000A0
,则属于旧时间线00000001
。
3.2 使用工具解析WAL元数据
通过sys_waldump
直接解析WAL文件,查看LSN与时间线的真实关系:
./sys_waldump ../data/sys_wal/00000001000000000000000B
输出中会明确显示时间线信息:
[kingbase@localhost bin]$ ./sys_waldump ../data/sys_wal/00000001000000000000000B |grep 'BD49920'
rmgr: Heap len (rec/tot): 56/ 2226, tx: 1131, lsn: 0/0BD49920, prev 0/0BD498F0, desc: INSERT off 177 flags 0x00, blkref #0: rel 1663/14731/16467 blk 4424 FPW
rmgr: Heap len (rec/tot): 59/ 59, tx: 1131, lsn: 0/0BD4A1F0, prev 0/0BD49920, desc: INSERT off 178 flags 0x00, blkref #0: rel 1663/14731/16467 blk 4424...
3.3 理解函数的使用场景
- 适用场景:查询当前时间线下新生成的LSN对应的WAL文件名(例如当前事务的LSN)。
- 不适用场景:查询历史LSN或跨时间线的WAL文件名。
4. 注意事项
- 主备切换后的WAL生成规则:
- 新主库生成的WAL文件名时间线号一定比旧主库大。
- 旧时间线的WAL文件不会被删除,但新主库不会写入旧时间线文件。
- 若使用
sys_walfile_name()
查询历史LSN需注意:- 该函数仅用于计算,不关联历史时间线数据。
5. 总结
- 核心原因:
sys_walfile_name()
函数设计上不关联时间线历史,仅依赖当前时间线生成文件名。 - 正确姿势:
- 查询历史LSN时,需结合
.history
文件或工具解析。 - 将该函数仅用于当前时间线的LSN计算(如监控当前WAL生成状态)。
- 查询历史LSN时,需结合