一、CLOG是什么
CLOG(COMMIT log)——事务提交日志,它是保存PG数据库中事务的状态,从而判断事务的可见性。事务提交日志分配于共享内存中,并作用于事务处理的全过程。
二、CLOG中事务状态
CLOG中只记录四种事务状态,分别是IN_PROGRESS(进行中),CMMITTED(已提交),ABORTED(回滚,中断)以及SUB_COMMITTED(子事务已提交)。
在源码/src/include/access/clog.h 中定义的数据结构

三、CLOG是怎么工作的

如上图:
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 -l
total 16
-rw-------. 1 halo halo 8192 Mar 1 04:53 0000CLOG日志文件命名是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日志记录实操
以回滚操作作为实操,如下图

执行checkpoint刷新CLOG,把数据落盘。
然后使用hexdemp工具dump出该bytes。命令格式如下:
hexdump -C -n length -s skip file_name
常用参数:
-C 定义了导出的格式,
-s skip 指定了从文件头跳过多少字节,或者说是偏移量,默认是十进制。如果是0x开头,则是十六进制。
-n 指定了导出多少长度实际操作如下图

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




