0
点赞
收藏
分享

微信扫一扫

PostgreSQL数据库WAL——XLogRegisterBuffer 注册页面


在PostgreSQL 9.5之前,与数据页面相关的信息同样会被注册到rdatas(上一篇博客中提到的数组),这种实现逻辑不清晰。PostgreSQL 9.5之后改进了日志记录的产生和组织方式,它通过XLogRegisterBuffer函数把受写操作影响的页面注册到registerd_buffers数组中,每个页面在registerd_buffers数组中都占一个槽位。registerd_buffers是由registered_buffer结构体构成的数组。

数据结构

static registered_buffer *registered_buffers;
static int max_registered_buffers; /* allocated size */
static int max_registered_block_id = 0; /* highest block_id + 1 currently registered */

/* For each block reference registered with XLogRegisterBuffer, we fill in a registered_buffer struct. */
typedef struct {
bool in_use; /* is this slot in use? 槽位使用中 */
uint8 flags; /* REGBUF_* flags */
RelFileNode rnode; /* identifies the relation and block 页面对应的物理信息 */
ForkNumber forkno;
BlockNumber block;
Page page; /* page content 页面内容指针 */
uint32 rdata_len; /* total length of data in rdata chain XLogRegisterBufData会注册进来的长度 */
XLogRecData *rdata_head; /* head of the chain of data registered with this block XLogRegisterBufData会注册数据到这个链表 */
XLogRecData *rdata_tail; /* last entry in the chain, or &rdata_head if empty XLogRegisterBufData会注册进来的最后一个 */
// 在XLogRecordAssemble函数中不方便再调用XLogRegister*函数,这里设定两个临时变量
XLogRecData bkp_rdatas[2]; /* temporary rdatas used to hold references to
* backup block data in XLogRecordAssemble() */

/* buffer to store a compressed version of backup block image 压缩页面使用的临时空间 */
char compressed_page[PGLZ_MAX_BLCKSZ];
} registered_buffer;

XLogRegisterBuffer

作用:将涉及到的buff注册到wal记录,比如insert语句的目标buff、update语句的目标buff和源buff。
实现过程:找到registered_buffer数组中第一个空的的位置,并将这个位置的数据填充

/* Register a reference to a buffer with the WAL record being constructed. This must be called for every page that the WAL-logged operation modifies. */
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags) {
registered_buffer *regbuf;
/* NO_IMAGE doesn't make sense with FORCE_IMAGE */
Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
Assert(begininsert_called);

if (block_id >= max_registered_block_id) { // 检查registered_buffers槽位合法性
if (block_id >= max_registered_buffers) elog(ERROR, "too many registered buffers");
max_registered_block_id = block_id + 1;
}

regbuf = &registered_buffers[block_id];
BufferGetTag(buffer, &regbuf->rnode, &regbuf->forkno, &regbuf->block);
regbuf->page = BufferGetPage(buffer);
regbuf->flags = flags;
regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head; // XLogRegisterBufData会注册进来链表首尾重置
regbuf->rdata_len = 0; // XLogRegisterBufData会注册进来链表长度为零
regbuf->in_use = true;
}

PostgreSQL数据库WAL——XLogRegisterBuffer 注册页面_链表


PostgreSQL数据库WAL——XLogRegisterBuffer 注册页面_postgresql_02


举报

相关推荐

0 条评论