• postgresql源码学习(33)—— 事务日志⑨ - 从insert记录看日志写入整体流程


    一、 整体流程

           前面我们分开看了每一个步骤的具体函数,这里再通过一个简单insert语句的跟踪,来看看整体的流程。目前只看WAL相关的部分,因为insert整体涉及到非常多东西,有些是还没学习到的。

    https://img-blog.csdnimg.cn/72828373ea934685b1705d89c879e367.png

    https://img-blog.csdnimg.cn/9568ffb848f94e68a38d286c4c75a977.png

    最简单的insert语句对应函数是 heap_insert,其中跟WAL相关的代码:

    1. XLogBeginInsert();
    2. XLogRegisterData((char *) &xlrec, SizeOfHeapInsert);
    3. xlhdr.t_infomask2 = heaptup->t_data->t_infomask2;
    4. xlhdr.t_infomask = heaptup->t_data->t_infomask;
    5. xlhdr.t_hoff = heaptup->t_data->t_hoff;
    6. /*
    7. * note we mark xlhdr as belonging to buffer; if XLogInsert decides to
    8. * write the whole page to the xlog, we don't need to store
    9. * xl_heap_header in the xlog.
    10. */
    11. XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags);
    12. XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
    13. /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
    14. XLogRegisterBufData(0,
    15. (char *) heaptup->t_data + SizeofHeapTupleHeader,
    16. heaptup->t_len - SizeofHeapTupleHeader);
    17. /* filtering by origin on a row level is much more efficient */
    18. XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
    19. recptr = XLogInsert(RM_HEAP_ID, info);
    20. PageSetLSN(page, recptr);

    二、 代码调试

    1. 调试方法

    会话1

    1. postgres=# create table t_insert(a int);
    2. CREATE TABLE
    3. postgres=# select pg_backend_pid();
    4.  pg_backend_pid
    5. ----------------
    6.            8632

    会话2

    vscode跟踪8632进程

    会话1

    postgres=# insert into t_insert values(1);

    加一个断点到WAL相关部分,点击继续

    2. 调试过程

    • 首先是XLogBeginInsert做代码安全检查工作,另外是设置begininsert_called标志,防止递归调用日志生成函数。

    • XLogRegisterData,将WAL日志数据注册到rdatas数组。

           参数的xlrec为xl_heap_insert结构体(日志记录中的main data部分),因此这一步是在构建并注册main data数据到WAL记录中。

    • 构建xl_heap_header(block data)

    • XLogRegisterBuffer:注册数据页,将被修改的buffer页面信息注册到registerd_buffers数组。由于XLOG是page-oriented log,所以在注册元组之前需要注册数据页。

    • XLogRegisterBufData:注册xl_heap_header(block data),这里的xlhdr参数就是前面构建的xl_heap_header

    • 注册实际元组数据

    heaptup->t_data + SizeofHeapTupleHeader为实际元组

    • 组装WAL记录并写入wal buffer

            XLogInsert函数中调用日志组装函数XLogRecordAssemble 以及 XLogInsertRecord完成上述工作,最后返回的是写入的EndPos。

    • 设置PageLSN

           设置页面头PageLSN为recptr(即EndPos)。每个页面都会有PageLSN,页面中所有LSN<=Page LSN的WAL表示对应的操作都已经落盘。因此在崩溃恢复时,这些操作都不需要执行redo。

    参考

    https://blog.csdn.net/obvious__/article/details/119242908?spm=1001.2014.3001.5502

    postgresql源码学习(23)—— 事务日志④-日志组装_Hehuyi_In的博客-CSDN博客_postgresql事务日志

    https://blog.csdn.net/Hehuyi_In/article/details/125447500  postgresql源码学习(22)—— 事务日志③-日志的注册_Hehuyi_In的博客-CSDN博客

  • 相关阅读:
    Python——Python程序的文件头部声明
    文件(夹)批量重命名数字、字母、日期、中文数字大写小写
    57.【全排列的详细分析】
    【三十】springboot项目上高并发解决示例
    乾坤基础教程
    springboot基于WEB的高校文档打印系统毕业设计源码101004
    Antlr4 语法存在错误但语法分析器不报错的问题
    CleanMyMac2028永久破解版苹果mac电脑垃圾清理软件
    风控模型黑箱可解释,试下这个方法来演示
    11.22 - 每日一题 - 408
  • 原文地址:https://blog.csdn.net/Hehuyi_In/article/details/126072200