本文已参与「新人创作礼」活动,一起开启掘金创作之路
PostgreSQL LSN即Log sequence number,日志序列号,这是WAL日志唯一的、全局的标识。
那么pg中LSN究竟有什么作用呢?我们都知道wal日志中写入是有顺序的,比方说一条记录是先加100再乘200,如果顺序错乱变成先乘200再加100,那结果可是差之千里了,所以必须得记录wal日志的写入顺序。
而LSN就是负责这个的,给每条产生的wal日志记录一个编号。熟悉Oracle的朋友可能清楚,这和Oracle中redo的LRBA和HRBA有点类似。
LSN和WAL:
我们先来看下LSN是啥样的:
bill@bill=>select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
1/133E80B8
(1 row)
既然LSN是wal日志的序列号,那么它和wal日志有什么关系呢?
wal日志LSN编号规则:
1/920001F8(高32位/低32位)
wal日志文件命名规则:
我们看到的wal日志是这样的:000000010000000100000092
- 其中前8位:00000001表示timeline;
- 中间8位:00000001表示logid;
- 最后8位:00000092表示logseg
对照关系:
- wal日志的logseg前6位始终是0,后两位是LSN低32位/16MB(2*24),即LSN的前两位。如上例中logseg最后两位是92,LSN低32前两位也是92。
- LSN在wal日志中的偏移量即LSN低32位中后24位对应的十进制值。
例如当前wal日志偏移量为504
bill=# select pg_walfile_NAME_OFFSET(pg_current_wal_lsn());
pg_walfile_name_offset
--------------------------------
(000000010000000100000092,504)
(1 row)
bill=# select x'1F8'::int;
int4
------
504
(1 row)
LSN常用脚本:
我们可以使用下面的一些脚本查看LSN相关的信息。
查看当前wal日志中LSN:
select pg_current_wal_lsn();
查看当前LSN对应的wal日志文件:
select pg_walfile_name(pg_current_wal_lsn());
查看wal日志文件名和偏移量:
select pg_walfile_name_offset(pg_current_wal_lsn());
查看表page中的LSN(需要安装pageinspect扩展):
SELECT lsn FROM page_header(get_raw_page('t1', 0));
LSN与数据恢复:
当数据库出现故障需要进行数据恢复时,首先从检查点开始,回放WAL日志,如果数据页面的LSN小于WAL记录的LSN,则说明数据页面比较旧,需要进行回放,反之则不需要回放,就会跳过回放过程。
从检查点开始,回放WAL日志,如果数据页面的LSN小于WAL记录的LSN,则说明数据页面比较旧,需要进行回放,反之则不需要回放,就会跳过回放过程。
参考链接: