【PostgreSQL的CLOG解析】

同样还是这张图,之前发过shared_buffer和os cache、wal buffer和work mem的文章,今天的主题是图中的clog,即 commit log,PostgreSQL10之前放在数据库目录的pg_clog下面。PostgreSQL10之后修更名为xact,数据目录变更为pg_xact下面,表现形式是一些物理文件。

PostgreSQL为什么要使用clog呢,众所周知,PostgreSQL有着独特的MVCC机制,由于其多版本的特性,
在进行可见性判断时,需要获取事务的状态,即元组中 t_xmin 和 t_xmax 的状态,需要clog来记录事务的状态,从而判断其可见性,内存里的访问远远快于磁盘读写,因此PostgreSQL的很多机制都是运行时候在内存,然后定期持久化到磁盘。因此clog也有一块内存区域便于高效访问,即clog buffers,它也属于共享内存的这部分,平时更新clog是内存中进行的,然后满足条件后会调用pg_fsync刷数据到磁盘上的clog文件,或者等待checkpoint刷数据。数据库启动时会从磁盘的pg_xact目录下读取事务状态加载到clog buffers,并且运行过程中,vacuum会定时将不再使用的clog文件清理。
关于clog buffers 的大小,可以在 src/backend/access/transam/clog.c里看到相关定义。

所以clog buffers 占用的页的个数是NBuffers / 512,最大为128个页,最小为4个页,这里的NBuffers 在之前wal buffer这篇文章已经说过,它和shared_buffers的关系,两者计算的字节数是一致的,感兴趣可以去看下 (PostgreSQL的wal_buffers - 墨天轮)。
因此,这里clog buffers的大小可以理解为 shared_buffers的1/512。
PostgreSQL中通过clog来存储事务的状态。所以,当在Postgresql中如果想要取消一个执行了很长时间的事务,基本上是瞬间完成的,而不是像Oracle中一样需要等到undo表空间中内容回滚完,因为PostgreSQL里只需要将事务的状态由IN_PROGRESS修改为ABORTED即可。
PG中,事务号最多占用32位,有三个是比较特殊的,在access/xlogdefs.h下可以看到,这里的BootstrapTransactionId是用于“bootstrap”操作的XID,FrozenTransactionId用于非常老的元组。FirstNormalTransactionId是第一个“正常”的事务id。

一、事务状态
在clog.h里定义了需要提交日志clog来记录事务的状态,从而判断其可见性,在PostgreSQL里总共有四种事务状态。分别是:IN_PROGRESS、COMMITED、ABORTED和SUB_COMMITED。例如事务正在运行中,那么它的状态就是IN_PROGRESS。全部是0是初始状态,SUB_COMMITTED状态表示已提交的子事务,其父事务尚未提交或中止。每个状态只需要两位(2 bit)就可以表示。

二、clog文件里事务id和状态信息的空间占用
对于上述提到的四种状态,可以用2 bit来表示。因此四个事务的状态就占用了8 bit 即一个字节。
在src/backend/access/transam/clog.c里一样可以找到关于这块空间占用的定义。

CLOG_BITS_PER_XACT:每个事务占用几个 bit(默认为2,因为4种状态用2bit就可以完全表示)
CLOG_XACTS_PER_BYTE :每个字节可以存几个事务的状态(默认为4,因为1bytes=8bit,1个事务状态需要占用2bit)
CLOG_XACTS_PER_PAGE:每个页可以存几个事务的状态(8KB*4=32K=2^15)
CLOG_XACT_BITMASK:位掩码
三、如何根据事务ID查看在clog日志里的事务的状态
在PostgreSQL中,事务id并不是在事务开始时就会被真正分配,它会先分配一个虚拟事务号,当有数据要发生变化时才会真正分配xid,而当事务提交或回滚时,其事务状态便会被写入clog中。比如你显式开启事务,什么都不做或者只做查询操作,commit之后,是不会消耗xid的。而当你有对数据的变更操作,则会消耗xid。
举个例子如下,当我们执行 select txid_current();的时候,他每次也要使用一个事务号,而当我们显式开启事务,然后什么都不做或者只执行select操作后,commit以后,事务号是不会增加的。我测试中增加了1是因为执行了select txid_current();的原因。而当显示事务里有对数据的变更操作,则下次执行select txid_current();的时候,事务号直接跳了两个,减去一个select txid_current();的,剩下那个增加的事务号则是我这个insert的事务占用的。
postgres=# select txid_current();txid_current
--------------2119
(1 row)postgres=# select txid_current();txid_current
--------------2120
(1 row)postgres=# begin;
BEGIN
postgres=*# select 1;?column?
----------1
(1 row)
postgres=*# commit;
COMMIT
postgres=# select txid_current();txid_current
--------------2121
(1 row)postgres=# begin;
BEGIN
postgres=*# insert into t1 values(5);
INSERT 0 1
postgres=*# commit;
COMMIT
postgres=# select txid_current();txid_current
--------------2123
(1 row)
在src/backend/access/transam/clog.c里同同样也存在着事务ID存放位置的定义和计算方法,如下所示

这四个分别为
TransactionIdToPage (事务id对应在哪个CLOG页)
计算方法为:(xid) / (TransactionId) CLOG_XACTS_PER_PAGE,这个CLOG_XACTS_PER_PAGE是第二部分看到的每个页可以存几个事务的状态,它默认是2^15。因此。事务id/ (2^15)得到的就是事务id对应在哪个CLOG页,当然,是要取整的。从0号页开始。
TransactionIdToPgIndex(事务id对应在上面页中的偏移量)
计算方法为:(xid) % (TransactionId) CLOG_XACTS_PER_PAGE,即事务id%(2^15)得到的是在页里的偏移量。
TransactionIdToByte(事务id对应在上面页中第几个的字节)
计算方法为:TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE,这里的TransactionIdToPgIndex(xid)是刚才计算的偏移量。而CLOG_XACTS_PER_BYTE是第二部分定义的每个字节可以存几个事务的状态,默认是4,所以事务在页里的偏移量/4得到的是事务id对应在页中第几个的字节。
TransactionIdToBIndex(事务id对应在上面字节中的哪个bit)
计算方法为:(xid) % (TransactionId) CLOG_XACTS_PER_BYTE。这里 CLOG_XACTS_PER_BYTE依旧是每个字节可以存几个事务的状态,默认为4,此处不用偏移量。直接用事务id%4来得到在一个byte里的哪个bit。(1byte=8bit)
这里做一个验证,
开启一个session

另开一个session,查看clog

计算四个值,我们该条记录是一个新的bytes里的
事务id对应在哪个CLOG页=2108/(2^15)=0
事务id对应在上面页中的偏移量=2108%(2^15)=2108
事务id对应在上面页中第几个的字节=2108/4=527
事务id对应在上面字节中的哪个bit=2108%4=0(表示这个事务在一bytes的第一组bits)


在commit后,原本的值应该变为01,但我们查看对应的clog文件部分是00,但是这可能并不代表事务在进程中,因为所有的状态初始值都是00,clog的数据还没有从内存写到磁盘。而且clog分配于共享内存的clog_buffer中,当申请新的CLOG PAGE时所有的clog_buffer都没有刷出脏页,才需要主动选择一个page并调用pg_fsync刷出对应的pg_clog到磁盘中,除此之外,checkpoint会将clog buffer刷到磁盘。因此我这里为了观察选择使用checkpoint。

此时clog buffer刷到了磁盘,可以看到此事务的状态是01,对照开头的状态,是已经提交的状态。

上边的例子是一个TransactionIdToByte计算为整数的,当TransactionIdToByte计算带有小数的时候,我们只看整数取整就可以了,例如如下的例子。


15从16进制转换成2进制为 0001 0101 ,而上边这个2110的事务,其计算的TransactionIdToBIndex(事务id对应在上面字节中的哪个bit)=2110%4=2,所以他在第3组bit上(取值是0为第一组),为01。因此在这个bytes里,我们的三个事务都是提交的状态。

等到一个byte的四组事务全部都是commited的时候,hexdump -C 0000 -s 527 -n 1查看到的值应该是55,例如下面这种大量的55,如果不是55则表示这一bytes里的四组事务,不是全部提交的,存在IN PROCESS、ABORTED或者SUB_COMMITTED的事务。

相关文章:
【PostgreSQL的CLOG解析】
同样还是这张图,之前发过shared_buffer和os cache、wal buffer和work mem的文章,今天的主题是图中的clog,即 commit log,PostgreSQL10之前放在数据库目录的pg_clog下面。PostgreSQL10之后修更名为xact,数据目录变更为pg_xact下面&…...
腾讯云国际站代充-阿里云ECS怎么一键迁移到腾讯云cvm?
今天主要来介绍一下如何通过阿里云国际ECS控制台一键迁移至腾讯云国际CVM。腾讯云国际站云服务器CVM提供全面广泛的服务内容。无-需-绑-定PayPal,代-充-值腾讯云国际站、阿里云国际站、AWS亚马逊云、GCP谷歌云,官方授权经销商!靠谱࿰…...
东方晶源亮相第十一届半导体设备年会,共话发展“芯”机遇
8月11日,以“协力同芯抢机遇,集成创新造设备”为主题的第十一届(2023年)中国电子专用设备工业协会半导体设备年会暨产业链合作论坛(CSEAC)在无锡太湖国际博览中心圆满闭幕。为期3天的CSEAC,通过…...
git修改历史commit信息
修改历史提交 commit 的信息 操作步骤: git rebase -i 列出 commit 列表找到需要修改的 commit 记录,把 pick 修改为 edit 或 e,:wq 保存退出修改 commit 的具体信息git commit --amend,保存并继续下一条git 4. 4. rebase --cont…...
基于K8S环境部署Dolphinscheduler及简单应用
一、Dolphinscheduler简介 Apache DolphinScheduler 是一个分布式易扩展的可视化DAG工作流任务调度开源系统。适用于企业级场景,提供了一个可视化操作任务、工作流和全生命周期数据处理过程的解决方案。 Apache DolphinScheduler 旨在解决复杂的大数据任务依赖关系,并为应用…...
Linux的ln命令
ln是link的缩写,在Linux中 ln 命令的功能是为某一个文件在另外一个位置建立一个同步的链接,当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录࿰…...
深入了解Bear Necessities Hackathon黑客松的优胜者们
生态系统中的资深建设者皆知道Moonbeam是大型黑客松狂热爱好者,不论是线上虚拟的还是现场的。然而,很少有黑客松能达到Moonbeam和AWS举办的Bear Necessities黑客松这样的规模和吸引力。本次黑客松共有755人参与,共提交了62份参赛作品。其中22…...
mysql-tokudb使用qa
一、使用前提 安装tokudb引擎的前提条件是物理机要关闭大页,并需要注意物理机所剩内存和配置文件中tokudb_cache_size(内存主要占用部分),innodb_buffer_pool_size的使用,另外tokudb的安装一定要安装libjemalloc依赖&…...
对比学习论文综述总结
第一阶段:百花齐放(18-19中) 有InstDisc(Instance Discrimination)、CPC、CMC代表工作。在这个阶段方法模型都还没有统一,目标函数也没有统一,代理任务也没有统一,所以说是一个百花齐放的时代 1 判别式代理任务---个体判别任务 1.1 Inst Dict---一个编码器+一个memory…...
【BASH】回顾与知识点梳理(二十三)
【BASH】回顾与知识点梳理 二十三 二十三. Linux 账号管理(二)23.1 账号管理新增与移除使用者: useradd, 相关配置文件, passwd, usermod, userdelusermoduserdel 23.2 用户功能(普通用户可使用)idfingerchfnchsh 23.3…...
用 Python 写一个 NoSQL 数据库
NoSQL 这个词在近些年正变得随处可见. 但是到底 “NoSQL” 指的是什么? 它是如何并且为什么这么有用? 在本文, 我们将会通过纯 Python (我比较喜欢叫它, “轻结构化的伪代码”) 写一个 NoSQL 数据库来回答这些问题. OldSQL 很多情况下, SQL 已经成为 “数据库” (database)…...
Spring Security自定义登陆界面和密码验证逻辑
maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency> 创建配置文件处理跳转拦截等功能以及密码比对功能 package com.example.demo2.demos.web1;…...
Android布局【LinearLayout】
文章目录 常见属性orientation的选择项解释项目结构主要代码 常见属性 orientation:布局中组件的排列方式gravity:控制组件所包含的子元素的对齐方式,可多个组合layout_gravity:控制该组件在父容器里的对齐方式background&#x…...
搭建grafana+loki+promtail日志收集系统
准备工作 下载地址 https://github.com/grafana/loki/releases 安装包放在服务器目录:/opt wget https://github.com/grafana/loki/releases/download/v2.4.2/loki-linux-amd64.zip wget https://github.com/grafana/loki/releases/download/v2.4.2/promtail-lin…...
Electron+vue3项目使用SQLite3数据库
SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,我们不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个独立的进程&am…...
SpringSpringBoot常用注解
目录 一、核心注解二、Spring Bean 相关2.1 Autowired2.2 Component, Repository, Service, Controller2.3 RestController 与 Controller2.4 Configuration 与 Component2.5 Scope 三、处理常见的 HTTP 请求类型3.1 GET 请求3.2 POST 请求3.3 PUT 请求3.4 DELETE 请求3.5 PATC…...
题目:2566.替换一个数字后的最大差值
题目来源: leetcode题目,网址:2566. 替换一个数字后的最大差值 - 力扣(LeetCode) 解题思路: 将从左到右第一个非 9 数字全部修改为 9 以得到最大值。将从左到右第一个数字全部修改为 0 以得到最小值&a…...
使用 NLP 进行文本摘要
一、说明 文本摘要是为较长的文本文档生成简短、流畅且最重要的是准确摘要的过程。自动文本摘要背后的主要思想是能够从整个集合中找到最重要信息的一小部分,并以人类可读的格式呈现。随着在线文本数据的增长,自动文本摘要方法可能会非常有用,…...
vue3挂载全局方法和组件
话不多说直接上代码 main.js import { createApp } from vue import App from ./App.vueconst app createApp(App)// 注册全局方法和组件 function myMethod(){console.log(Hello, world!); } app.provide("myMethod", myMethod) // provide注册全局方法 inject获取…...
mybatisplus学习笔记
1.踩过的坑 1.MybatisPlus 要与其代码生成器的版本一致; 2.要使用新版代码(3.5.1及以上)生成器则要使用springboot3,如果用springboot2使用新版代码生成器会导致builder.parent(“com.sdfsf”) // 设置父包名》重复!&…...
【实战】手搓一个极简MCP服务,最后交给小龙虾调用
未来已来,只需一句指令,养龙虾专栏导航,持续更新ing… 一、MCP 协议核心概念 MCP(Model Context Protocol) 是由 Anthropic 提出的开放式 AI 模型工具连接标准,旨在解决 AI 模型与外部工具之间的标准化通信问题: 本质:基于 JSON-RPC 2.0 协议 构建的轻量级通信框架 核…...
Python flask django高校毕业生公职资讯系统 考公辅导系统
目录同行可拿货,招校园代理 ,本人源头供货商功能模块设计考公辅导核心功能后台管理功能技术实现要点扩展功能建议项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块设计 用户管理…...
Net Insight推出可编程视频制作网络解决方案
随着实时媒体工作流程在设施、合作伙伴网络和云环境之间日益分布化,技术进步正在运营域之间创建可编程的分界点。基于这一动态趋势,Net Insight推出了可编程信任边界技术,使实时媒体互连在设施、网络和云环境之间传输时变得可预测。解释此次发…...
LongCat-Image 图像生成模型,编辑能力登顶开源SOTA
在技术领域,我们常常被那些闪耀的、可见的成果所吸引。今天,这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力,让我们得以一窥未来的轮廓。然而,作为在企业一线构建、部署和维护复杂系统的实践者,我们深知…...
16 指挥AI写数据库SQL代码:增删改查与存储过程实现
指挥AI写数据库SQL代码:增删改查与存储过程实现 摘要 本文为《30天掌控AI编程:从指令到落地,手把手教你指挥AI写代码》系列第十六篇,属于第三阶段多场景实战核心内容。本篇聚焦企业级SQL代码生成,针对零基础、无数据库开发经验的使用者,拆解指挥AI编写规范、高效、可直…...
19 多语言切换实操:一个指令,让AI适配任意编程语言
多语言切换实操:一个指令,让AI适配任意编程语言 摘要 本文为《30天掌控AI编程:从指令到落地,手把手教你指挥AI写代码》系列第十九篇,属于第三阶段多语言实战核心内容。本篇专注AI代码跨语言无缝切换这一高频痛点,针对零基础开发者、多技术栈项目人员,拆解如何通过结构…...
ST7789显示屏驱动实战指南:从基础配置到高级应用
ST7789显示屏驱动实战指南:从基础配置到高级应用 【免费下载链接】st7789py_mpy 项目地址: https://gitcode.com/gh_mirrors/st/st7789py_mpy ST7789显示屏驱动是一款专为嵌入式系统设计的高性能TFT LCD控制器解决方案,支持多种分辨率与丰富显示…...
UE5 开发神器:蓝图节点预设插件 — 支持多节点打组 / 快捷键 / 拖拽插入 / 材质编辑器
插件名称:UPNodePresets 插件包含以下功能 Action Palette 搜索:右键空白处搜索预设名称,回车即插入快捷键插入:按住数字键 0~9 鼠标左键点击任意位置,瞬间插入(Blueprint / Material 独立绑定ÿ…...
探索基于支持向量数据描述 (SVDD) 的多类分类算法
基于支持向量数据描述 (SVDD) 的多类分类算法附matlab代码.zip最近我发现了一个超有趣的基于支持向量数据描述 (SVDD) 的多类分类算法,还附带了Matlab代码呢!今天就来和大家分享一下我的探索过程。首先说说这个算法本身吧。SVDD是一种用于异常检测和单类…...
利用快马平台五分钟搭建openmaic网页版图像描述演示原型
最近在调研多模态AI框架时,发现OpenMAIC这个开源项目很有意思。它整合了视觉理解和文本生成能力,特别适合做图像描述这类应用。不过对于想快速验证效果的新手来说,本地部署整套环境还是有点门槛。正好发现InsCode(快马)平台能极速搭建演示原型…...
