PostgreSQL预写日志标志位的使用和影响

原创
2019/10/07 09:50
阅读数 265

本篇继续演示和讲解如何从代码中翻出自己需要的功能,以逻辑复制插件为例。过程中不可避免的会读很多无关的代码,这部分不需要啰嗦,随着代码熟悉程度的提高,这些开发过程中的开销会减少。

1、插件初始化设置callback函数commit_cb

它处理事务提交信息,但这里拿不到太多,LogicalDecodingContext 中并没有包含事务状态。

2、逻辑解码

src/backend/replication/logical/logical.c

callback函数 commit_cb 封装在 commit_cb_wrapper 中,设置到下一层的callback中:

/* commit callback signature */
typedef void (*ReorderBufferCommitCB) (
									   ReorderBuffer *rb,
									   ReorderBufferTXN *txn,
									   XLogRecPtr commit_lsn);

定义就不多说了,我们的目标是找到事务是否有控制标志,设置流程是什么,代码细节有兴趣自己看吧。

3、解码

再继续看下去,解码事务提交的函数是:DecodeCommit

src/backend/replication/logical/decode.c

这里可以看到,对于回滚掉的事务,也有一个专门的处理函数:DecodeAbort,它直接释放已经解码的结构。

4、事务标志位

  if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
  {
    origin_lsn = parsed->origin_lsn;
    commit_time = parsed->origin_timestamp;
  }

随着代码的深入,它终于出现。扩展标志位xinfo,说扩展是由名字猜测。

/* does this record have a 'xinfo' field or not */
#define XLOG_XACT_HAS_INFO			0x80

而有没有xinfo由这个标志来确认,更多信息可以根据代码或者注释来了解。

5、它是什么时候设置的

src/backend/access/transam/xact.c 函数 XactLogCommitRecord

事务提交时根据状态写入。

6、我们还能看出什么

根据过滤器跳过部分事务

  if (SnapBuildXactNeedsSkip(ctx->snapshot_builder, buf->origptr) ||
    (parsed->dbId != InvalidOid && parsed->dbId != ctx->slot->data.database) ||
    ctx->fast_forward || FilterByOrigin(ctx, origin_id))
  {
    for (i = 0; i < parsed->nsubxacts; i++)
    {
      ReorderBufferForget(ctx->reorder, parsed->subxacts[i], buf->origptr);
    }
    ReorderBufferForget(ctx->reorder, xid, buf->origptr);

    return;
  }

那么,如果我们想自行控制事务是否解码,就可以使用这段逻辑,丝毫不用担心。

7、还有更多

继续上一点,不管事务是不是需要复制,都是要解码的,根据过滤条件再释放,也就是有一些无意义的开销。

其实这个过程还有很多不相关代码的阅读,确定无关就忽略掉,这里只列出有影响的部分。

没有开发文档,只能依靠代码和注释的解读。有更好的方法、经验、建议,请分享给我。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部