9.5 WAL记录的写入

完成了热身练习后,现在我们已经做好理解XLOG记录写入过程的准备了。因此在本节中,我将尽可能仔细地描述。首先,以下列语句的执行为例,让我们来看一看PostgreSQL的内幕。
testdb=# INSERT INTO tbl VALUES ('A');

通过发出上述语句,内部函数exec_simple_query()会被调用,其伪代码如下所示:

exec_simple_query() @postgres.c
(1) ExtendCLOG()    @clog.c     /* 将当前事务的状态"IN_PROGRESS"写入CLOG */
(2) heap_insert()    @heapam.c    /* 插入元组,创建一条XLOG记录并调用函XLogInsert. */
(3)   XLogInsert()    @xlog.c     /* (9.5 以及后续的版本为 xloginsert.c) */
                                /* 将插入元组的XLOG记录写入WAL缓冲区,更新页面的 pd_lsn */
(4) finish_xact_command() @postgres.c    /* 执行提交 */   
      XLogInsert() @xlog.c              /* (9.5 以及后续的版本为 xloginsert.c) */
                                        /* 将该提交行为的XLOG记录写入WAL缓冲区 */
(5)   XLogWrite() @xlog.c                /* 将WAL缓冲区中所有的XLOG刷写入WAL段中 */
(6) TransactionIdCommitTree() @transam.c  
                            /* 在CLOG中将当前事务的状态由"IN_PROGRESS"修改为"COMMITTED" /*

在接下来的段落中将会解释每一行伪代码,从而理解XLOG记录写入的过程。如图9.11和图9.12所示。

  1. 函数ExtendCLOG()将当前事务的状态IN_PROGRESS写入内存中的CLOG。
  2. 函数heap_insert()向共享缓冲池的目标页面中插入堆元组,创建当前页面的XLOG记录,并执行函数XLogInsert()
  3. 函数XLogInsert()会将heap_insert()创建的XLOG记录写入WAL缓冲区LSN_1处,并将被修改页面的pd_lsnLSN_0更新为LSN_1
  4. 函数finish_xact_command()会在该事务被提交时被调用,用于创建该提交动作的XLOG记录,而这里的XLogInsert()函数会将该记录写入WAL缓冲区LSN_2处。 图9.11 XLOG记录的写入顺序上图的XLOG格式是9.4版本的
  5. 函数XLogWrite()会冲刷WAL缓冲区,并将所有内容写入WAL段文件中。如果wal_sync_method参数被配置为open_syncopen_datasync,记录会被同步写入(译者注:而不是提交才会刷新WAL缓冲区),因为函数会使用带有O_SYNCO_DSYNC标记的open()系统调用。如果该参数被配置为fsyncfsync_writethroughfdatasync,相应的系统调用就是fsync(),带有F_FULLSYNC选项的fcntl(),以及fdatasync()。无论哪一种情况,所有的XLOG记录都会被确保写入存储之中。
  6. 函数TransactionIdCommitTree()将提交日志clog中当前事务的状态从IN_PROGRESS更改为COMMITTED图9.12 XLOG记录的写入顺序(续图9.11)图9.12 XLOG记录的写入顺序(续图9.11)

在上面这个例子中,COMMIT操作致使XLOG记录写入WAL段文件。但发生在下列任一情况时,都会执行这种写入操作:

  1. 一个运行中的事务提交或中止。
  2. WAL缓冲区被写入的元组填满(WAL缓冲区的大小由参数wal_buffers控制)
  3. WAL写入者进程周期性执行写入(参见 下一节

如果出现上述情况之一,无论其事务是否已提交,WAL缓冲区上的所有WAL记录都将写入WAL段文件中。

DML操作写XLOG记录是理所当然的,但非DML操作也会产生XLOG。如上所述,COMMIT操作会写入包含着提交的事务ID的XLOG记录。另一个例子是Checkpoint操作会写入关于该检查点概述信息的XLOG记录。此外,尽管不是很常见,SELECT语句在一些特殊情况下也会创建XLOG记录。例如在SELECT语句处理的过程中,如果因为HOT(Heap Only Tuple)需要删除不必要元组并拼接必要的元组时,修改对应页面的XLOG记录就会写入WAL缓冲区。