Whoami:5年+金融、政府、医疗领域工作经验的DBA
Certificate:OCP、PCP
Skill:Oracle、Mysql、PostgreSQL
Platform:CSDN、墨天伦、公众号(呆呆的私房菜)
复制
阅读本文可以了解PostgreSQL的MVCC概念和实现。
到底什么是MVCC呢?
1. MVCC即多版本并发控制,是一种用于处理数据库中并发操作的机制;
2. 在MVCC中,每个数据库事务在读取数据时会看到一个特定的版本,这使得事务之间可以同时进行读写操作,并且不会相互干扰。每个事务可以操作自己的数据版本,从而实现了更高的并发性和更好的性能;
3. MVCC核心思想是对每个修改此操作,不是直接在原始数据上进行修改,而是创建一个新的数据版本,并将修改操作应用于新版本,这样其它事务仍可以访问旧版本数据,而不会受到正在进行的修改的影响。只有在事务提交时,新版本的数据才会替代旧版本,从而实现数据的一致性。
4. MVCC在数据库中起作用的原理是通过使用版本号、时间戳或类似的标识来管理数据版本,并通过一定的规则来决定哪些版本对于每个事务是可见的。
第一种:写新数据时,元数据移到一个单独的位置,如回滚段中,其他用户读数据时,从回滚段中把元数据读出来。
第二种:写新数据时,原数据不删除,而是把新数据插入进来。
PostgreSQL数据库是通过把原数据保留在数据文件中,新插入一条数据来实现多版本并发功能的。
我们可以通过pageinspect插件来窥视PostgreSQL的多版本控制工作过程。
## 为实现MVCC,PostgreSQL数据库的每张表上都存在4个系统字段:
## 1. xmin:表示记录的第一个可见事务的 XID;
## 2. xmax:表示记录的最后一个修改它的事务的 XID;
## 3. cmin:表示命令ID的最小值;
## 4. cmax:表示命令ID的最大值。
postgres=# create extension pageinspect;
CREATE EXTENSION
postgres=# create table a1 (id int);
CREATE TABLE
postgres=# insert into a1 values (1),(2);
INSERT 0 2
## 不收集统计信息前,看不到当前元组使用的数据页和元组数量
postgres=# select relname, relpages, reltuples from pg_class where relname = 'a1';
relname | relpages | reltuples
---------+----------+-----------
a1 | 0 | -1
(1 row)
## 收集统计信息
postgres=# analyze a1;
ANALYZE
## 表a1占用了1个数据页,一共有2个元组
testdb=# select relname, relpages, reltuples from pg_class where relname = 'a1';
relname | relpages | reltuples
---------+----------+-----------
a1 | 1 | 2
(1 row)
## heap_page_items函数用于获取数据库堆表页上条目的信息
## lp: 指向下一条记录的指针。如果这是页上的最后一条记录,这个值通常是指向页末尾的偏移量。
## lp_off: 记录在页上的偏移量。
## lp_flags: 记录的一些状态标志,比如是否是脏页(dirty)。
## lp_len: 记录的长度。
## t_xmin: 插入这条记录的事务的最小事务 ID(XID)。如果这个值是 InvalidTransactionId(0),表示这条记录是可见的。
## t_xmax: 最后一次删除或更新这条记录的事务的事务 ID。如果这个值是 0,表示这条记录没有被当前事务删除或更新。
## t_field3: 这个字段通常用于存储额外的事务信息,但具体内容取决于 PostgreSQL 的版本。
## t_ctid: 当前记录的复合索引,包含块号和行号。
## t_infomask2: 一个掩码,用于存储记录的额外信息,比如是否是只读副本。
## t_infomask: 另一个掩码,用于存储记录的元数据信息,比如是否是压缩的或是否包含 OID。
## t_hoff: 指向记录头信息的偏移量。
## t_bits: 一个位图,用于存储记录的可见性和其他信息。
## t_oid: 如果记录包含 OID 列,则这个字段存储该值。
## t_data: 记录的实际数据,通常以字节序列的形式存储。
## 输出解读:
## 1. 两条记录的t_xmin,说明是由同个事务插入的
## 2. t_xmax没有记录代表没有事务更新或删除这条记录
## 3. t_ctid显示了记录的当前位置
## postgres=# select * from heap_page_items(get_raw_page('a1',0));
lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data
----+--------+----------+--------+------------+--------+----------+--------+-------------+------------+--------+--------+-------+------------
1 | 8160 | 1 | 28 | 2146483941 | 0 | 0 | (0,1) | 1 | 2304 | 24 | | | \x01000000
2 | 8128 | 1 | 28 | 2146483941 | 0 | 0 | (0,2) | 1 | 2304 | 24 | | | \x02000000
(2 rows)
## 更新一条数据
postgres=# update a1 set id = 22 where id = 2;
UPDATE 1
## 输出解读:
## 1. 新增了一条xid为2146483943的记录,并且记录了更新后的数据
## 2. 被更新的记录并没有被删除,而是被标记为旧版本,数据仍保存在原数据文件中。
postgres=# select * from heap_page_items(get_raw_page('a1',0));
lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data
----+--------+----------+--------+------------+------------+----------+--------+-------------+------------+--------+--------+-------+------------
1 | 8160 | 1 | 28 | 2146483941 | 0 | 0 | (0,1) | 1 | 2304 | 24 | | | \x01000000
2 | 8128 | 1 | 28 | 2146483941 | 2146483943 | 0 | (0,3) | 16385 | 256 | 24 | | | \x02000000
3 | 8096 | 1 | 28 | 2146483943 | 0 | 0 | (0,3) | 32769 | 10240 | 24 | | | \x16000000
(3 rows)
复制
动动手,做做试验吧!通过上边小小的实验我们就可以看到PostgreSQL的多版本并发控制的实现原理啦!
本文内容就到这啦,阅读完本篇,相信你也对PostgreSQL的MVCC实现有了初步的了解了吧!我们下篇再见!

文章转载自呆呆的私房菜,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
外国CTO也感兴趣的开源数据库项目——openHalo
小满未满、
621次阅读
2025-04-21 16:58:09
9.9 分高危漏洞,尽快升级到 pgAdmin 4 v9.2 进行修复
严少安
360次阅读
2025-04-11 10:43:23
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
345次阅读
2025-04-15 14:48:05
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
318次阅读
2025-04-07 12:14:29
MogDB 发布更新,解决 openGauss 数据库在长事务情况下Ustore表膨胀问题
MogDB
289次阅读
2025-04-17 10:41:41
转发有奖 | PostgreSQL 16 PGCM高级认证课程直播班招生中!
墨天轮小教习
155次阅读
2025-04-14 15:58:34
墨天轮PostgreSQL认证证书快递已发(2025年3月批)
墨天轮小教习
134次阅读
2025-04-03 11:43:25
SQL 优化之 OR 子句改写
xiongcc
100次阅读
2025-04-21 00:08:06
融合Redis缓存的PostgreSQL高可用架构
梧桐
91次阅读
2025-04-08 06:35:40
PostgreSQL拓展PGQ实现解析
chirpyli
89次阅读
2025-04-07 11:23:17