首页
产品
CLup:PostgreSQL高可用集群平台CData高性能数据库云一体机CBackup数据库备份恢复云平台CPDA高性能双子星数据库机
解决方案
数据库专业技术服务全栈式PostgreSQL解决方案Oracle分布式存储化数据库云
文章
客户及伙伴
中启开源
关于我们
公司简介 联系我们
中启开源

WAL日志文件名组成

在PG中日志名是一串数字,刚开始接触PG的朋友对名字都有些疑惑,在PG中WAL日志名是由16进制的数字命名总共24个字符由三部分组成(本例中WAL日志文件名为0000000100000001000000C4):

如何计算?

我们知道由三部分组成,那么又是如何计算呢?公式如下:

  1. WAL segment file name = timelineId +(uint32)LSN1 / (16M 256 + (uint32)(LSN 1 / 16M) % 256

我们算一个试一试.查看当前LSN位置

  1. postgres=# select pg_current_wal_lsn();
  2. pg_current_wal_lsn
  3. --------------------
  4. 1/C469AA30
  5. (1 row)

这里的LSN是1/C469AA30 我们转换为十进制数:

  1. postgres=# select x'1C469AA30'::bigint;
  2. int8
  3. ------------
  4. 7590226480
  5. (1 row)

利用公式计算:

logSeg:

  1. postgres=# select ((7590226480 - 1) / (16 * 1024 * 1024 )) % 256 ;
  2. ?column?
  3. ----------
  4. 196
  5. (1 row)

196是十进制数 转换为16 进制为 c4

  1. postgres=# select to_hex(196);
  2. to_hex
  3. --------
  4. c4
  5. (1 row)

LogId:

  1. postgres=# select ((7590226480 - 1) / (16::bigint * 1024::bigint * 1024::bigint * 256::bigint) :: int8);
  2. ?column?
  3. ----------
  4. 1
  5. (1 row)

得出的LogId等于1
时间线ID:

  1. postgres@coredumped ~ pg_controldata|grep TimeLine
  2. Latest checkpoint's TimeLineID: 1
  3. Latest checkpoint's PrevTimeLineID: 1

算出来的值与通过函数查询的一致:

  1. postgres=# select pg_walfile_name('1/C469AA30');
  2. pg_walfile_name
  3. --------------------------
  4. 0000000100000001000000C4
  5. (1 row)

通过源码分析

上述的公式也是在网站中看到,特意查看了下PG代码确认下正确性:

  1. // 这里是计算一个logSegNo
  2. #define XLByteToPrevSeg(xlrp, logSegNo) \
  3. logSegNo = ((xlrp) - 1) / XLogSegSize
  4. //XLOG_SEG_SIZE 定义
  5. #define XLOG_SEG_SIZE (16 * 1024 * 1024)
  6. //这块是拼文件名地方
  7. #define XLogFilePath(path, tli, logSegNo) \
  8. snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
  9. ¦(uint32) ((logSegNo) / XLogSegmentsPerXLogId),
  10. ¦(uint32) ((logSegNo) % XLogSegmentsPerXLogId))

LogId与logSeg 分别是LogSegNo除XLogSegmentsPerXLogId或者是对XLogSegmentsPerXLogId取模,那么XLogSegmentsPerXLogId又是什么呢?
//看到XLogSegmentsPerXLogId的定义我们可以自己计算下

  1. #define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE)
  1. postgres=# select x'100000000'::bigint / (16 * 1024 * 1024);
  2. ?column?
  3. ----------
  4. 256
  5. (1 row)

这个值就是256

总结

WAL日志命名感觉上并不像MySQL Binlog日志那么简单,如果对其原理不了解,会感觉其名称比较怪异。大家学习时可以多进行研究多做实验,这样对自己也是一种提高。