聊聊PostgreSQL中的WAL-了解WAL

2022-08-17 12:41:52 浏览数 (1)

  • PostgreSQL数据库中的WAL的主要用途是用于故障恢复,针对数据库的数据insert/delete/update操作都会形成一些列的WAL日志记录,多个WAL日志组成WAL的日志序列,这些日志记录记录了哪些page做了什么修改。如果此时数据库发生故障(主机),哪些未被提交的事务或者需要回滚的事务可以从WAL中进行恢复。
  • PostgreSQL针对数据的更改先会写入到内存,但是事务提交后一定是要把数据更改信息写入到WAL日志。比如做update一条记录,现在内存中构建update tuple,然后插入到内存的page中,执行commit,从update tuple构造WAL日志记录,刷新数据到WAL日志,完成此次更新操作
  • PG中WAL日志记录数据库修改的记录,每一个针对数据库的更改操作都会对应一个WAL日志条目。WAL日志的写入是采用append方式,这样能很好规避随机写带来的性能问题。这里会有一个问题,如果数据库在一个事务内不断的进行数据更改,内存中的脏page不断的积累,WAL日志不断的被写入,如果WAL变得很大,这时候PG崩溃了,那么数据库恢复不得是需要从WAL日志第一个文件开始恢复直到最后一个WAL日志文件吗?PG的实现实际不是这样的,在启动PG时候会启动一个checkpoint进程,它的目的脏page刷新到磁盘,同时告诉wal日志文件刷新了哪些脏page,即使这时候数据库崩溃,也是从没有刷到磁盘page开始恢复。就是把PG故障恢复实现了ARIES论文提到的模型,构造脏页已经checkpoint技术来简化实现WAL日志的逻辑,降低故障时间。
  • 官方的PostgreSQL版本中是没有undo日志,只有redo日志(wal日志)。PG的MVCC多版本是把记录的前后多个版本数据保存在表的page,根据一定的条件来判断可见性,选择对应的记录的版本返回。wal日志是位于{PG_DATA}/pg_wal目录,每个wal文件名称占用24字节。wal文件名称如0000000100000000000000A0,前8个字节代表时间信息,中间8个字节代表日志逻辑ID,每个逻辑ID被划分为多个日志段segment,最后8个字节中最后2个字节表示该日志中包含的segment数量。
  • 每条WAL日志记录都会有一个lsn号(日志序列号),比如0/A00D20C8日志号,0代表日志逻辑ID(对应Wal文件名称中中间8个字节),后面的A00D20C8代表中前2位是段ID,后面的是段内偏移量.0/A00D20C8的日志记录对应的是逻辑日志ID=0,A0是对应段ID,0D20C8是对应段内的偏移量。0/A00D20C8对应的日志记录位置是0000000100000000000000A0这个日志文件。
代码语言:javascript复制
postgres=# show wal_segment_size;
 wal_segment_size 
------------------
 16MB
(1 row)

postgres=# select pg_current_wal_insert_lsn();
 pg_current_wal_insert_lsn 
---------------------------
 0/A00D20C8
(1 row)

postgres=# select pg_walfile_name(pg_current_wal_insert_lsn());
     pg_walfile_name      
--------------------------
 0000000100000000000000A0
(1 row)

0 人点赞