|
大家都知道开源PG数据库使用的事务ID是32位的,国内的众多PG系国产数据库也是如此。经常使用互联网,大家对IPV4和IPV6地址不会太陌生。IPV4只有32位,老美当年为了自身的利益,分配大量的公网IPV4地址给自己的大学和研究机构、政府机构用,导致后来者其它国家能够分配的公网地址越来越少,一些公司不得不使用NAT上网。后来IPV6地址为128位,IPV6地址多到海边一粒沙子都可以分配到一个。作为数据库DBA,我们的第一感觉是事务ID不够用,扩展长度就行了。至于为什么事务ID不使用64位,笔者在查询灿总老师翻译的postgresql 14 internals电子书中给出了的答案,内容如下所示。
在 PostgreSQL 中,事务 ID 占用 32 位。四十亿似乎是一个相当大的数字,但如果系统使用频繁,那么可能很快便会耗尽。例如,对于平均每秒 1000 个事务的负载 (不包括虚拟事务),在连续运行大约六周后就会发生这种情况。
一旦用完所有的数字,那么计数器必须重置以开始下一轮 (这种情况被称为"回卷")。但是,只有分配的数字在始终增加的情况下,才能认为具有较小 ID 的事务比具有较大 ID 的事务更老。因此,计数器在重置后不能简单地开始重新使用相同的数字。
为事务 ID 分配 64 位本可以彻底解决这个问题,那为什么 PostgreSQL 不使用呢?问题在于,每个元组头必须存储两个事务 ID:xmin 和 xmax。元组头目前已经相当大了 (如果考虑到数据对齐,至少 24 字节),增加更多位将会再增加 8 字节。
PostgreSQL 确实实现了 64 位事务 ID 1,通过一个 32 位 epoch 扩展了常规 ID,但它们仅在内部使用,并且从不进入数据页。
从灿总的技术文档看,开源PG数据库64位事务ID仅在内部使用,并没在数据页中使用。作为DBA,有时可能要从内核的角度看一些问题,才能找到答案。现在我们对比的一下PG18数据库的事务ID和国产数据库红石PG事务ID长度差别,如下所示。
[postgres@localhost ~]$ psql
psql (18beta1)
Type "help" for help.
postgres=# select txid_current();
txid_current
--------------
979
(1 row)
Last login: Thu Sep 25 21:13:32 EDT 2025 on pts/0
[postgres@localhost ~]$ psql
psql (17.4 - redrock 3.2)
Type "help" for help.
postgres=# select txid_current();
txid_current
--------------
4296146990
(1 row)
但如何查看PG数据库的事务ID的长度?语句是什么?由于我接触PG数据库的时间不长,个人技术水平不足,只能在百度和DS找具体的语句,语句如下。
你可以通过查询系统目录表 pg_type 来获取事务ID的数据类型及其长度。
SELECT typname, typlen
FROM pg_type
WHERE oid = 'pg_catalog.xid'::regtype;
两个数据库的事务ID对比如下所示
postgres=# SELECT typname, typlen
postgres-# FROM pg_type
postgres-# WHERE oid = 'pg_catalog.xid'::regtype;
typname | typlen
---------+--------
xid | 4
(1 row)
postgres=# SELECT typname, typlen
postgres-# FROM pg_type
postgres-# WHERE oid = 'pg_catalog.xid'::regtype;
typname | typlen
---------+--------
xid | 8
(1 row)
可以看到国产数据库红石PG的事务ID长度是开源PG数据库的事务ID的2倍,占用8个字节表示事务长度。
注:国产数据库中PG系的数据库很多,这些国产数据库已经对某些PG版本进行大量修改和优化,早已不是吴下阿蒙了,还是要好好学习国产数据库。
合作电话:010-64087828
社区邮箱:greatsql@greatdb.com