Postgres2015全国用户大会将于11月20至21日在北京丽亭华苑酒店召开。本次大会嘉宾阵容强大,国内顶级PostgreSQL数据库专家将悉数到场,并特邀欧洲、俄罗斯、日本、美国等国家和地区的数据库方面专家助阵:
- Postgres-XC项目的发起人铃木市一(SUZUKI Koichi)
- Postgres-XL的项目发起人Mason Sharp
- pgpool的作者石井达夫(Tatsuo Ishii)
- PG-Strom的作者海外浩平(Kaigai Kohei)
- Greenplum研发总监姚延栋
- 周正中(德哥), PostgreSQL中国用户会创始人之一
- 汪洋,平安科技数据库技术部经理
- ……
|
|
异步提交是指不需要等待事务对应的wal buffer fsync到磁盘,即返回,而且写CLOG时也不需要等待XLOG落盘。
而pg_clog和pg_xlog是两部分存储的,那么我们想一想,如果一个已提交事务的pg_clog已经落盘,而XLOG没有落盘,刚好此时数据库CRASH了。
数据库恢复时,由于该事务对应的XLOG缺失,数据无法恢复到最终状态,但是PG_CLOG却显示该事务已提交,这就出问题了。
所以对于异步事务,CLOG在write前,务必等待该事务对应的XLOG已经FLUSH到磁盘。
PostgreSQL如何记录事务和它产生的XLOG的LSN的关系呢?
其实不是一一对应的关系,而是记录了多事务对一个LSN的关系。
src/backend/access/transam/clog.c
LSN组,每32个事务,记录它们对应的最大LSN。也就是32个事务,只记录最大的LSN。节约空间?/* We store the latest async LSN for each group of transactions */#define CLOG_XACTS_PER_LSN_GROUP 32 /* keep this a power of 2 */
每个CLOG页需要分成多少个LSN组。#define CLOG_LSNS_PER_PAGE (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP)
#define GetLSNIndex(slotno, xid) ((slotno) * CLOG_LSNS_PER_PAGE + \((xid) % (TransactionId) CLOG_XACTS_PER_PAGE) / CLOG_XACTS_PER_LSN_GROUP)
LSN被存储在这个数据结构中
src/include/access/slru.h
/** Shared-memory state*/typedef struct SlruSharedData{....../** Optional array of WAL flush LSNs associated with entries in the SLRU* pages. If not zero/NULL, we must flush WAL before writing pages (true* for pg_clog, false for multixact, pg_subtrans, pg_notify). group_lsn[]* has lsn_groups_per_page entries per buffer slot, each containing the* highest LSN known for a contiguous group of SLRU entries on that slot's* page. 仅仅pg_clog需要记录group_lsn*/XLogRecPtr *group_lsn; // 一个数组,存储32个事务组成的组中最大的LSN号。int lsn_groups_per_page;
......
src/backend/access/transam/clog.c
* lsn must be the WAL location of the commit record when recording an async* commit. For a synchronous commit it can be InvalidXLogRecPtr, since the* caller guarantees the commit record is already flushed in that case. It* should be InvalidXLogRecPtr for abort cases, too.
voidTransactionIdSetTreeStatus(TransactionId xid,