有在网上找过一些关于vacuum_freeze_min_age参数是如何影响vacuum冻结旧行的文章。类似的参考资料可以参看链接:
http://blog.csdn.net/luojinbai/article/details/45848381但是自己在做类似的测试时发现,并没有出现相同的结果,反复测试几次,仍然不同。后来咨询了下德哥说,看源码,行冻结的信息不再通过改变xmin来实现行冻结的信息。当时就觉得绝望了,对于一个完全不懂任何高级开发语言的人来说,这个等于对PG又多了个谜。后来想到,是不是可以通过查看page中的信息,来确认,冻结的信息到底是怎么反应到infomask中。最后想到还从来没有用过pageinspect呢。看了下官网对pageinspect的介绍:
https://www.postgresql.org/docs/9.4/static/pageinspect.html
可以通过函数heap_page_items(page bytea)来查看行头部的信息内容。非常开心的发现,在这个章节中,里面有很负责任地指出可以在那些源码文件中找到相关的信息,接下来,就开始了我的第一次源码查找的经历。官网有如下一段话:
See src/include/storage/itemid.h and src/include/access/htup_details.h for explanations of the fields returned.看来这个就是关于行的详细信息了。因为知道冻结信息放在t_infomask中,所以,找到htup_details.sh后,先定位t_infomask的结构,有如下内容:/** information stored in t_infomask:*/
#define HEAP_HASNULL            0x0001    /* has null attribute(s) */
#define HEAP_HASVARWIDTH        0x0002    /* has variable-width attribute(s) */
#define HEAP_HASEXTERNAL        0x0004    /* has external stored attribute(s) */
#define HEAP_HASOID                0x0008    /* has an object-id field */
#define HEAP_XMAX_KEYSHR_LOCK    0x0010    /* xmax is a key-shared locker */
#define HEAP_COMBOCID            0x0020    /* t_cid is a combo cid */
#define HEAP_XMAX_EXCL_LOCK        0x0040    /* xmax is exclusive locker */
#define HEAP_XMAX_LOCK_ONLY        0x0080    /* xmax, if valid, is only a locker *//* xmax is a shared locker */
#define HEAP_XMAX_SHR_LOCK    (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)#define HEAP_LOCK_MASK    (HEAP_XMAX_SHR_LOCK | HEAP_XMAX_EXCL_LOCK | \HEAP_XMAX_KEYSHR_LOCK)
#define HEAP_XMIN_COMMITTED        0x0100    /* t_xmin committed */
#define HEAP_XMIN_INVALID        0x0200    /* t_xmin invalid/aborted */
#define HEAP_XMIN_FROZEN        (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
#define HEAP_XMAX_COMMITTED        0x0400    /* t_xmax committed */
#define HEAP_XMAX_INVALID        0x0800    /* t_xmax invalid/aborted */
#define HEAP_XMAX_IS_MULTI        0x1000    /* t_xmax is a MultiXactId */
#define HEAP_UPDATED            0x2000    /* this is UPDATEd version of row */
#define HEAP_MOVED_OFF            0x4000    /* moved to another place by pre-9.0* VACUUM FULL; kept for binary* upgrade support */
#define HEAP_MOVED_IN            0x8000    /* moved from another place by pre-9.0* VACUUM FULL; kept for binary* upgrade support */
#define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)#define HEAP_XACT_MASK            0xFFF0    /* visibility-related bits */其中关于冻结的信息就存放在HEAP_XMIN_FROZEN中了。而该部分信息时通过另外两个字段相与得出的:
HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID那么如果某个行被冻结后,那么该位的值应该是3. 接下来进行测试。新建一张表,并插入一条数据,同时查看通过age以及pageinspect的函数查看相关的信息:
test=# create table t (id int,vb text);
CREATE TABLE
test=# insert into t values (1,'test');
INSERT 0 1
test=# select ctid,age(xmin),xmin,xmax,* from t;ctid  | age | xmin | xmax | id |  vb
-------+-----+------+------+----+------(0,1) |   1 | 1864 |    0 |  1 | test
(1 row)test=# select * from heap_page_items(get_raw_page('t',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
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------1 |   8152 |        1 |     33 |   1864 |      0 |        0 | (0,1)  |           2 |       2306 |     24 |        |
(1 row)t_infomask对应的的2306,是t_infomask对应的值,该值是十进制,转换成十六进制则是0x0902,对应的位信息是:
HEAP_HASVARWIDTH
HEAP_XMIN_COMMITTED
HEAP_XMAX_INVALID插入第二条数据,让表里的数据行的年龄有些不同:
test=# insert into t values (2,'again test');
INSERT 0 1刚刚插入行的t_infomask值2050对应的十六进制为0x0802,之所以没有HEAP_XMIN_COMMITTED位信息的原因是,关于事务状态信息是通过hint bits来体现的,刚刚插入的行并不会在事务结束时立刻更新hint bits,而是会在下一次查询或者更新等操作时才会设置,所以这才出现了没有HEAP_XMIN_COMMITTED信息的t_infomask,具体的文章介绍,可以查看另一片翻译文章:
https://yq.aliyun.com/articles/55682test=# select * from heap_page_items(get_raw_page('t',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
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------1 |   8152 |        1 |     33 |   1864 |      0 |        0 | (0,1)  |           2 |       2306 |     24 |        |      2 |   8112 |        1 |     39 |   1865 |      0 |        0 | (0,2)  |           2 |       2050 |     24 |        |
(2 rows)test=# select ctid,age(xmin),xmin,xmax,* from t;ctid  | age | xmin | xmax | id |     vb
-------+-----+------+------+----+------------(0,1) |   2 | 1864 |    0 |  1 | test(0,2) |   1 | 1865 |    0 |  2 | again test
(2 rows)当通过查询语句select ctid,age(xmin),xmin,xmax,* from t查看表中数据后,hint bits得到更新,此时的t_infomask变成了2306,即0x0902
test=# select * from heap_page_items(get_raw_page('t',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
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------1 |   8152 |        1 |     33 |   1864 |      0 |        0 | (0,1)  |           2 |       2306 |     24 |        |      2 |   8112 |        1 |     39 |   1865 |      0 |        0 | (0,2)  |           2 |       2306 |     24 |        |
(2 rows)查看当前pg_class中relfrozenxid字段的值,随后该值会因为vacuum的触发而改变。
test=# select relfrozenxid from pg_class where relname= 't';relfrozenxid
--------------1863
(1 row)将vacuum_freeze_min_age设置成更小的值,方便查看在经过很少的事务之后,就能使得表中的行可以被冻结。
test=# set vacuum_freeze_min_age=5;
SET
test=# select txid_current();txid_current
--------------1866
(1 row)test=# select txid_current();txid_current
--------------1867
(1 row)test=# select txid_current();txid_current
--------------1868
(1 row)test=# select relfrozenxid from pg_class where relname= 't';relfrozenxid
--------------1863
(1 row)test=# select ctid,age(xmin),xmin,xmax,* from t;ctid  | age | xmin | xmax | id |     vb
-------+-----+------+------+----+------------(0,1) |   5 | 1864 |    0 |  1 | test(0,2) |   4 | 1865 |    0 |  2 | again test
(2 rows)test=# vacuum t;
VACUUM
test=# select ctid,age(xmin),xmin,xmax,* from t;ctid  | age | xmin | xmax | id |     vb
-------+-----+------+------+----+------------(0,1) |   5 | 1864 |    0 |  1 | test(0,2) |   4 | 1865 |    0 |  2 | again test
(2 rows)test=# select * from heap_page_items(get_raw_page('t',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
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------1 |   8152 |        1 |     33 |   1864 |      0 |        0 | (0,1)  |           2 |       2306 |     24 |        |      2 |   8112 |        1 |     39 |   1865 |      0 |        0 | (0,2)  |           2 |       2306 |     24 |        |
(2 rows)以上信息没有发生变化,还需要再次执行一次txid_current函数。test=# select relfrozenxid from pg_class where relname= 't';relfrozenxid
--------------1864
(1 row)test=# select txid_current();txid_current
--------------1869
(1 row)test=# vacuum t;
VACUUM
test=# select * from heap_page_items(get_raw_page('t',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
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------1 |   8152 |        1 |     33 |   1864 |      0 |        0 | (0,1)  |           2 |       2818 |     24 |        |      2 |   8112 |        1 |     39 |   1865 |      0 |        0 | (0,2)  |           2 |       2306 |     24 |        |
(2 rows)
此时可以发现,age为6的ctid为(0,1)的行的t_infomask值发生了改变,2818转换后是0x0b02,对应的位信息为:
HEAP_XMIN_FROZEN
HEAP_XMAX_INVALID
HEAP_HASVARWIDTH
这个时候就可以判断,t中的行被冻结了。此时,relfrozenxid也发生了变化,该字段实际值,根据官方文档的描述:All transaction IDs before this one have been replaced with a permanent ("frozen") transaction ID in this table. This is used to track whether the table needs to be vacuumed in order to prevent transaction ID wraparound or to allow pg_clog to be shrunk.
根据自己的理解,该字段存放的是上一次全表vacuum的冻结截止XID,可能会有些偏差~~。
test=# select relfrozenxid from pg_class where relname= 't';relfrozenxid
--------------1865
(1 row)test=# select ctid,age(xmin),xmin,xmax,* from t;ctid  | age | xmin | xmax | id |     vb
-------+-----+------+------+----+------------(0,1) |   6 | 1864 |    0 |  1 | test(0,2) |   5 | 1865 |    0 |  2 | again test
(2 rows)尽管冻结了行, 但是并没有体现在xmin中,也就印证了冻结的信息不再通过xmin来体现,源码中也有类似的介绍:/** HeapTupleHeaderGetRawXmin returns the "raw" xmin field, which is the xid* originally used to insert the tuple.  However, the tuple might actually* be frozen (via HeapTupleHeaderSetXminFrozen) in which case the tuple's xmin* is visible to every snapshot.  Prior to PostgreSQL 9.4, we actually changed* the xmin to FrozenTransactionId, and that value may still be encountered* on disk.*/

PG 9.4 行冻结信息的测试相关推荐

  1. Python [9] optparse模块生成命令行帮助信息

    起初,最先接触python命令行传参是sys模块的argv方法,此方法功能简单,稍微增加一些需求,就不难满足需要了 那么今天就和大家聊聊optparse模块来替换sys模块的argv方法 一.optp ...

  2. SAP中MD04中交货计划行例外信息30和再计划日期的分析

    笔者之前写过一篇<SAP中MD04中交货计划行例外信息07的分析>的文章.解读了07提示信息表示没有按预定的交货计划及时足量交货.其实在MD04中相关的提示信息还有很多种,笔者也在实际应用 ...

  3. 文件时间信息在测试中的应用

    1 简介 文件时间信息在测试中也有妙用- 通过记录模块运行前后的文件时间信息来识别运行前后发生变化的文件,从而识别模块运行前后的新增文件.删除的文件和内容发生变化的文件. 利用识别出来的发生变化的文件 ...

  4. Python读取文件夹下的所有文件,并获得文件中的2-10行的信息

    参考博客链接: python 获取当前文件夹下所有文件名 - StrongYaYa - 博客园 https://www.cnblogs.com/strongYaYa/p/7200357.html im ...

  5. 《安全测试指南》——信息收集测试【学习笔记】

    [信息收集测试] 1.搜索引擎信息收集(OTG-INFO-001) 通过搜索引擎收集以下: · 网络拓扑图和配置 · 管理员和其他员工的归档文章和邮件 · 登录过程和用户名的格式 · 用户名和密码 · ...

  6. boost::graph模块实现分布式压缩稀疏行图类型的测试

    boost::graph模块实现分布式压缩稀疏行图类型的测试 实现功能 C++实现代码 实现功能 boost::graph模块实现分布式压缩稀疏行图类型的测试 C++实现代码 #include < ...

  7. #PRBS# PRBS7高速串行总线的常用测试码型

    PRBS的定义: PRBS: Pseudo-Random Binary Sequence 伪随机二进制序列 PRBS 码具有"随机"特性,是因为在 PRBS 码流中,二进制数&qu ...

  8. Saiku设置展示table数据不隐藏空的行数据信息(二十六)

    Saiku设置展示table数据不隐藏空的行数据信息 saiku有个 非空的字段 按钮,点击这个后,会自动的把空的行数据信息给隐藏掉,这里我们来设置一下让其行数据不隐藏,为空的就为空. 主要更改两个文 ...

  9. linux文件 第八行,求助:如何grep一个文件中含有关键词“OTU_”之后第八行的信息...

    本帖最后由 ottchen 于 2014-12-13 17:23 编辑 大家好!我刚解除Linux,花了一个下午的时间才明白Grep命令的强大,但是还有很多不懂.如下: Query= OTU_527 ...

最新文章

  1. C/C++包管理工具Conan简介
  2. 操作系统 实验三 进程调度模拟程序
  3. 详解SOA五种基本架构模式
  4. js将数组元素随机排序的方法
  5. jps、jstack、jmap、jhat、jstat、hprof使用详解
  6. SaaS 不懂留存!别玩
  7. Google Maps API 调用实例
  8. 训练和测试数据的观察
  9. C与C++中const差别
  10. PartitionStateMachine分析
  11. python学习[第二篇] 基础二
  12. 各种版本操作系统的虚拟机镜像文件
  13. MATLAB 2018b 安装与简介
  14. 用python写恶搞病毒
  15. 街头篮球服务器维护,《街头篮球》4月23日新版活动抢先看
  16. kindle 越狱降级
  17. sqlserver 查询单引号
  18. 【arduino】LCD1602屏幕动画
  19. 使用Kong和Konga管理微服务和API
  20. bulid.prop优化代码(好像很强?)

热门文章

  1. .net学习之母版页执行顺序、jsonp跨域请求原理、IsPostBack原理、服务器端控件按钮Button点击时的过程、缓存、IHttpModule 过滤器...
  2. Android中的防缓冲区溢出技术
  3. 充分理解HP Flex-10和VMware的端口映射关系
  4. 解除IE8的内容审核程序
  5. 如何写出一个confirm组件
  6. 新版直播其他问题QA
  7. 2015 年最受 Linux 爱好者欢迎的软硬件大盘点
  8. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
  9. .NET中属性和特性
  10. 导致甲骨文裁员的原因有哪些?