Halo Tech

CLOG初学

一、CLOG是什么

    CLOG(COMMIT log)——事务提交日志,它是保存PG数据库中事务的状态,从而判断事务的可见性。事务提交日志分配于共享内存中,并作用于事务处理的全过程。

二、CLOG中事务状态

    CLOG中只记录四种事务状态,分别是IN_PROGRESS(进行中),CMMITTED(已提交),ABORTED(回滚,中断)以及SUB_COMMITTED(子事务已提交)。

在源码/src/include/access/clog.h 中定义的数据结构

#define TRANSACTION_STATUS_IN_PROGRESS           0x00        /*事务进行中,普通事务中使用*/#define TRANSACTION_STATUS_COMMITTED             0x01        /*事务已提交,普通事务中使用*/#define TRANSACTION_STATUS_ABORTED               0x02        /*事务已回滚,普通事务中使用*/#define TRANSACTION_STATUS_SUB_COMMITTED         0x03        /*子事务已提交,嵌套事务中使用,父事务没有提交,子事务提交就设置为这个状态*/

三、CLOG是怎么工作的

Image

如上图:

T1:txid 200 提交;txid 200的状态从IN_PROGRESS状态改变为CMMITTED状态。

T2:txid 201 回滚或中止;txid 201的状态就从IN_PROGRESS状态变为了ABORTED状态。

注:引用了《PostgreSQL指南:内幕探索》5.4.2节内容

四、CLOG文件能记录多少记录

在源码/src/backend/access/transam/clog.c中,定义了

/* * Defines for CLOG page sizes.  A page is the same BLCKSZ as is used * everywhere else in Postgres. * * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF, * CLOG page numbering also wraps around at 0xFFFFFFFF/CLOG_XACTS_PER_PAGE, * and CLOG segment numbering at * 0xFFFFFFFF/CLOG_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT.  We need take no * explicit notice of that fact in this module, except when comparing segment * and page numbers in TruncateCLOG (see CLOGPagePrecedes). */
/* We need two bits per xact, so four xacts fit in a byte */#define CLOG_BITS_PER_XACT 2 /*一个事务状态占用2个bit位*/#define CLOG_XACTS_PER_BYTE 4 /*一个字节可以存放4个事务状态(默认4,8 bit/2)*/#define CLOG_XACTS_PER_PAGE (BLCKSZ * CLOG_XACTS_PER_BYTE) /*一个页块可以存放多少个事务状态(默认8KB*8b/2b=32K=2^15个)*/#define CLOG_XACT_BITMASK ((1 << CLOG_BITS_PER_XACT) - 1)

    从源码中的定义可以知道记录一个事务状态信息需要2比特,一个字节存储了4个事务状态的记录。一个页面(默认是8KB),可记录CLOG记录条数为8K*8b/2b=32K,所以一个CLOG日志文件为256KB,在一个段中由32个页面组成,可记录的CLOG日志条数为32*2^15=2^20条记录。

    事务ID为32bit,可表示的事务数有2^32个,CLOG日志文件是以段文件为单位的,CLOG段的数量为2^32/2^20=2^12。CLOG日志文件以段号命名,所以只需要12位即可,postgresql以4位的十六进制数来表示段号,并作为日志段文件的名称。

五、CLOG存储在哪里

CLOG存储在PG数据目录下的pg_xact子目录中(pg9.4之前是存储在clog子目录,pg10之后才改成pg_xact子目录),文件中主要记录的是事务号(xid)和事务最终状态。

看下pg_xact目录下clog文件:

[halo@halo168 pg_xact]$ pwd/data/halo/pg_xact[halo@halo168 pg_xact]$ ls -ltotal 16-rw-------. 1 halo halo 8192 Mar  1 04:53 0000

CLOG日志文件命名是0000,0001,0002,......。

六、怎么定位CLOG日志中记录

我们先来看下源码/src/backend/access/transam/clog.c中

#define TransactionIdToPage(xid)    ((xid) / (TransactionId) CLOG_XACTS_PER_PAGE)         /*使用事务ID计算该事务在第几个页面*/#define TransactionIdToPgIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)        /*使用事务ID计算该事务在页面上的偏移量是多少*/#define TransactionIdToByte(xid)    (TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)   /*使用事务ID计算该事务在面页上的字节偏移,就是第几个的字节*/#define TransactionIdToBIndex(xid)    ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)       /*使用事务ID计算该事务在记录其CLOG记录的字节内的偏移量,即字节内的哪个bit*/

根据这四元组定义我们可以用来定位某条CLOG日志记录。

七、定位CLOG日志记录实操

    以回滚操作作为实操,如下图

Image

执行checkpoint刷新CLOG,把数据落盘。

然后使用hexdemp工具dump出该bytes。命令格式如下:

hexdump -C -n length -s skip file_name常用参数:-C 定义了导出的格式,-s skip 指定了从文件头跳过多少字节,或者说是偏移量,默认是十进制。如果是0x开头,则是十六进制。-n 指定了导出多少长度

实际操作如下图

Image

其他状态验证类似,不再验证。