PostgreSQL WAL日志名解析
日志名组成
在PG中日志名是一串数字,刚开始接触PG的朋友对名字都有些疑惑,在PG中日志名是由16进制命名总共24个字符由三部分组成:
0000000100000001000000C400000001 //时间线ID00000001 //LogId000000C4 //logSeg
如何计算?
我们知道由三部分组成,那么又是如何计算呢?公式如下:
WAL segment file name = timelineId +(uint32)LSN−1 / (16M ∗ 256) + (uint32)(LSN − 1 / 16M) % 256
我们算一个试一试.查看当前LSN位置
postgres=# select pg_current_wal_lsn();pg_current_wal_lsn--------------------1/C469AA30(1 row)
这里的LSN是’ 1/C469AA30’ 我们转换为十进制数:
postgres=# select x'1C469AA30'::bigint;int8------------7590226480(1 row)
利用公式计算:
logSeg:postgres=# select ((7590226480 - 1) / (16 * 1024 * 1024 )) % 256 ;?column?----------196(1 row)196是十进制数 转换为16 进制为 c4postgres=# select to_hex(196);to_hex--------c4(1 row)LogId:postgres=# select ((7590226480 - 1) / (16::bigint * 1024::bigint * 1024::bigint * 256::bigint) :: int8);?column?----------1(1 row)得出的LogId等于1时间线ID:postgres@coredumped ~ pg_controldata|grep TimeLineLatest checkpoint's TimeLineID: 1Latest checkpoint's PrevTimeLineID: 1
算出来的值与通过函数查询的一致:
postgres=# select pg_walfile_name('1/C469AA30');pg_walfile_name--------------------------0000000100000001000000C4(1 row)
通过源码分析
上述的公式也是在网站中看到,特意查看了下PG代码确认下正确性:
// 这里是计算一个logSegNo#define XLByteToPrevSeg(xlrp, logSegNo) \logSegNo = ((xlrp) - 1) / XLogSegSize//XLOG_SEG_SIZE 定义#define XLOG_SEG_SIZE (16 * 1024 * 1024)//这块是拼文件名地方#define XLogFilePath(path, tli, logSegNo) \snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,¦(uint32) ((logSegNo) / XLogSegmentsPerXLogId),¦(uint32) ((logSegNo) % XLogSegmentsPerXLogId))LogId与logSeg 分别是LogSegNo除XLogSegmentsPerXLogId或者是对XLogSegmentsPerXLogId取模,那么XLogSegmentsPerXLogId又是什么呢?//看到XLogSegmentsPerXLogId的定义我们可以自己计算下#define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE)postgres=# select x'100000000'::bigint / (16 * 1024 * 1024);?column?----------256(1 row)这个值就是256
总结
WAL日志命名感觉上并不像MySQL Binlog日志那么直观,有时候感觉会容易混乱,大家学习时可以多进行研究多做实验,这样对自己也是一种提高。
本站文章,未经作者同意,请勿转载,如需转载,请邮件customer@csudata.com.
0 评论
添加一条新评论