ITPub博客

首页 > > > WAL日志文件名称格式详解

WAL日志文件名称格式详解

作者:wangliyun 时间:2020-02-20 18:21:12 0 删除 编辑

PostgreSQL的WAL日志文件在pg_xlog目录下,一般情况下,每个文件为16M大小:

osdba-mac:~ osdba$ ls -l $PGDATA/pg_xlog

total 262144

-rw------- 1 osdba osdba 16777216 Oct 8 10:57 0000000100000000000000B6

-rw------- 1 osdba osdba 16777216 Jun 17 22:12 0000000100000000000000B7

-rw------- 1 osdba osdba 16777216 Jun 17 22:12 0000000100000000000000B8

-rw------- 1 osdba osdba 16777216 Jun 17 22:12 0000000100000000000000B9

-rw------- 1 osdba osdba 16777216 Jun 17 22:12 0000000100000000000000BA

-rw------- 1 osdba osdba 16777216 Jun 17 22:12 0000000100000000000000BB

-rw------- 1 osdba osdba 16777216 Jun 17 22:13 0000000100000000000000BC

-rw------- 1 osdba osdba 16777216 Jul 23 19:01 0000000100000000000000BD

drwx------ 2 osdba osdba 68 Mar 9 2015 archive_status

文件名称为16进制的24个字符组成,每8个字符一组,每组的意义如下:

00000001 00000000 000000BC

-------- -------- --------

时间线 LogId LogSeg

时间线:英文为timeline,是以1开始的递增数字,如1,2,3...

LogId:32bit长的一个数字,是以0开始递增的数字,如0,1,2,3...

LogSeg:32bit长的一个数字,是以0开始递增的数字,如0,1,2,3...


然而需要注意的是,数据库刚建好时,LogSeg第一次是从1开始的数字,到达一个最大的数字后,会重头开始,但以后再从头开始时,不再从1开始,而是从0开始。为什么这样呢?下面我们会讲解到这个问题。


WAL日志的位置是一个无限长的位置,数据库一建立后,不断的开始写WAL日志,此位置就不断的增加,即使数据库重启后,此位置也不会重新开始,只会一直增加,所以这个位置值显然如果用32bit的一个数字是不够的,32bit最多表示4GB的日志,所以大家很容易可以想到用一个64bit的数字来表示这个WAL日志的位置,这当然就足够了(因为要写4G*4G的数据才会用完64bit的长度)。


这个WAL日志的位置称之为LSN,即Log Sequence Number。


看起来,LogId+LogSeg好象刚好组成一个64bit的LSN,是否是LogId是这个64bit的LSN中的高32bit字节,而LogSeg就是低32bit的字节呢?LogId确实是LSN的高32字节,但LogSeg却不是低32bit的字节,另我们可以观察到LogSeg的值是从00000000到000000FF后,就重新从00000000开始了,并不会出现00000100这样的数值,也就是LogSeg的8个字符中,前6个字符始终是0,这是为什么?


原来LogSeg是按文件递增,每增加一个文件,LogSeg就增加1,而每个WAL文件的大小是16M,LogSeg是LSN的低32bit的字节的值再除以16M的结果,这样4G/16M结果是256,所以LogSeg最大的值为256,即16进制的0xFF,这样就解释了LogSeg的前6字节都是零的原因。


另原本LSN起始位置可以从0开始,但为了表示一些无效的位置,LSN的起始值并不是从0开始,也不是从1开始,而是跳过了一个WAL文件大小,即16M的位置开始,这样第一次时LogSeg是从1开始的,而不是从0开始了。


我们知道了WAL日志文件名中的意义,但很多时候我们会发现在PostgreSQL中会用两个十六进制的数字中间用斜杠“/”分隔表示WAL日志位置,即表示LSN,如函数pg_current_xlog_location、pg_current_xlog_insert_locatione及pg_start_backup的返回结果,如下所示:


postgres=# select pg_current_xlog_location(), pg_current_xlog_insert_location();

pg_current_xlog_location | pg_current_xlog_insert_location

--------------------------+---------------------------------

0/12B00B48 | 0/12B00B48

(1 row)


postgres=# select pg_start_backup('osdba_backup201510082130');

pg_start_backup

-----------------

0/14000100

(1 row)


同时我们在主库上通过查询视图pg_stat_replication来看replication的状态时,一些字段也显示成这样的格式:


postgres=# select sent_location, write_location, flush_location, replay_location, sync_state from pg_stat_replication;

sent_location | write_location | flush_location | replay_location | sync_state

---------------+----------------+----------------+-----------------+------------

0/1177A9F0 | 0/1177A9F0 | 0/1177A320 | 0/11779818 | async

(1 row)

以上这些表示WAL日志位置的方法,就是用两个32bit的数字来表示LSN,前一个数字LSN的高32bit,而另一个数字则是LSN的低32bit。在PostgreSQL9.4之后,增加了一个专门的类型pg_lsn用于表示WAL日志的位置,在PostgreSQL9.4之前,则用字符串来表示这个位置。


象上面的例子中,函数pg_current_xlog_location返回0/12B00B48,如果当前timeline为1,那么当前的WAL日志文件名是什么呢?


logId就是“0/12B00B48”中的第一个数字,即0

logSeg就是“0/12B00B48”中的第二个数字除以16M的大小,即12B00B48除以16M,而16M相当于2的24次方,相当于十六进制数“12B00B48”右移6位,即“12B00B48”中的最高两位“12”

那么根据WAL文件的格式timeline+logId+logSeg,则相当于:“00000001”+“00000000”+“00000012”,即为:“000000010000000000000012”

写的位置是在文件“000000010000000000000012”中的偏移量是多少呢?实际上是在“0/12B00B48”中第二个数字“12B00B48”后六位“B00B48”,换算成十进制为“11537224”。


当然PostgreSQL已准备了函数pg_xlogfile_name_offset帮我们做以上的转换,如下所示:


postgres=# select pg_xlogfile_name_offset('0/12B00B48');

pg_xlogfile_name_offset

-------------------------------------

(000000010000000000000012,11537224)

(1 row)


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917105/viewspace-3135850/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-19

  • 博文量
    213
  • 访问量
    317