PostgreSQL中commitlog有什么作用

本篇内容主要讲解“PostgreSQL中commit log有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中commit log有什么作用”吧!

创新互联专注为客户提供全方位的互联网综合服务,包含不限于网站制作、成都网站设计、潮安网络推广、小程序开发、潮安网络营销、潮安企业策划、潮安品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联为所有大学生创业者提供潮安建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com

Concurrency Control并发控制是一种机制,在并发进行多个事务时维护一致性(Consistency)和隔离性(Isolation),一致性和隔离性是数据库事务ACID(Atomicity, Consistency, Isolation, Durability) 属性中的C和I。
多版本并发控制(MVCC)是广泛使用的并发控制技术,其主要优势是读不会阻塞写,而写也不会阻塞读。MVCC有很多种变体,PostgreSQL使用一种称为快照隔离Snapshot Isolation (SI)的MVCC变体实现并发控制。
在MVCC中,每个DML操作创建一个数据(包括Index)的新版本,同时保留之前的旧版本。当事务读取数据时,选择其中一个“正确”的版本,以确保各个事务之间的隔离。
在 Multi Version Heap Tuple 这一章节中提到事务回滚后,新写入的数据仍存储在heap中,PostgreSQL如何识别产生这些数据的事务的状态(提交/回滚/进行中),从而确定哪些tuple可见不可见?PG通过clog(commit log)存储每个事务的状态,在数据库启动时,clog文件会加载到共享内存中,checkpoint时会把共享内存中的事务状态信息刷新到磁盘上.

一、基本概念

事务ID
当一个事务开启时,PostgreSQL事务管理器会为该事务分配一个唯一的事务ID(txid,无符号32bit整型).
通过txid_current()函数可获取当前事务号.

testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current 
--------------
         2308
(1 row)
testdb=#

在PG中,以下为系统保留使用的txid:
txid = 0,表示 Invalid txid,用于判断txid的有效性
txid = 1,表示 Bootstrap txid,在intidb初始化数据库时使用
txid = 2,表示 Frozen txid,在事务ID回卷时,通过vacuum进程处理时使用

事务状态
PostgreSQL定义了四种事务状态,分别是IN_PROGRESS(进行中), COMMITTED(已提交), ABORTED(已回滚), 和 SUB_COMMITTED(子事务已提交).

/*
 * Possible transaction statuses --- note that all-zeroes is the initial
 * state.
 * 可能的事务状态 --- 注意初始状态全部为ASCII 0
 *
 * A "subcommitted" transaction is a committed subtransaction whose parent
 * hasn't committed or aborted yet.
 * "subcommitted"事务是指已提交的子事务,而该子事务所在的父事务尚未提交或者回滚.
 */
typedef int XidStatus;
#define TRANSACTION_STATUS_IN_PROGRESS      0x00
#define TRANSACTION_STATUS_COMMITTED        0x01
#define TRANSACTION_STATUS_ABORTED          0x02
#define TRANSACTION_STATUS_SUB_COMMITTED    0x03

二、clog文件

物理文件
clog文件存储在$PGDATA/pg_xact目录中

[xdb@localhost pg_xact]$ ll
total 8
-rw-------. 1 xdb xdb 8192 Jan  8 15:55 0000
[xdb@localhost pg_xact]$

clog segment
如前所述,事务号是无符号的32bit整型,PG通过以下公式逻辑上把clog划分为N个segment:
N = 0xFFFFFFFF/CLOG_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT
其中:
CLOG_XACTS_PER_PAGE定义为

/* We need two bits per xact, so four xacts fit in a byte */
#define CLOG_BITS_PER_XACT  2 -->每个事务状态使用2bits表示
#define CLOG_XACTS_PER_BYTE 4 -->每个Byte可存储4个事务状态
#define CLOG_XACTS_PER_PAGE (BLCKSZ * CLOG_XACTS_PER_BYTE) -->每个page可存储8192*4个事务状态

即CLOG_XACTS_PER_PAGE = 8192*4
SLRU_PAGES_PER_SEGMENT定义为

#define SLRU_PAGES_PER_SEGMENT  32

代入公式中:
N = 0xFFFFFFFF/CLOG_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT
 = 0xFFFFFFFF/(8192*4)/32
 = 4096

物理上,每个segment有32个Pages(SLRU_PAGES_PER_SEGMENT = 32),则每个segment file大小为8K*32=256K.

三、txid & clog

给定一个事务号,如何获取该事务对应的状态?
PG首先通过该事务号获得该事务状态存储在clog中哪个page中(即pageno),然后再定位存储事务状态的Byte在该page中的偏移以及在该Byte中的偏移.

 #define TransactionIdToPage(xid)    ((xid) / (TransactionId) CLOG_XACTS_PER_PAGE)
 #define TransactionIdToPgIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)
 #define TransactionIdToByte(xid)    (TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)
 #define TransactionIdToBIndex(xid)  ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)

如给定事务号2308,根据上述公式可得到:
Page = 2308 / (8192*4) = 0 —> 第0号page
PageIndex = 2308 % (8192*4) = 2308 —> Page内偏移
ByteInPage = 2308 / 4 = 577 —> 该Page内的第577个Byte
ByteIndex = 2304 % 4 = 0 —> 该字节中的首2bits
下面通过实际案例验证
开启事务

testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current 
--------------
         2308
(1 row)

查看clog

[xdb@localhost pg_xact]$ hexdump -C ./0000 -s 577 -n 1
00000241  00                                                |.|
00000242

0x00 —> TRANSACTION_STATUS_IN_PROGRESS

提交事务
执行checkpoint,刷新到磁盘上

testdb=# commit;
COMMIT
testdb=# checkpoint;
CHECKPOINT

查看clog

[xdb@localhost pg_xact]$ hexdump -C ./0000 -s 577 -n 1
00000241  01                                                |.|
00000242

值为0x01 —> TRANSACTION_STATUS_COMMITTED

重新开启一个事务2309,回滚该事务,clog中的值应为0x09(二进制值为:0000 1001)

testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current 
--------------
         2309
(1 row)
testdb=# select 2308%4;
 ?column? 
----------
        0
(1 row)
testdb=# rollback;
ROLLBACK
testdb=# checkpoint;
CHECKPOINT
testdb=#

clog文件中的内容0x09,与预期中的一致.

[xdb@localhost pg_xact]$ hexdump -C ./0000 -s 577 -n 1
00000241  09                                                |.|
00000242
[xdb@localhost pg_xact]$

到此,相信大家对“PostgreSQL中commit log有什么作用”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


当前名称:PostgreSQL中commitlog有什么作用
分享链接:http://pwwzsj.com/article/gdhosp.html