匿名用户例如:
update t1 set info = 'abcd' where id = 2;
想判断是否是hot更新,一种方式是通过
t_infomask2 来判断的
请问,背后对应的原理是啥?
t_infomask标识位用于加快元组的可见性判断,其实现原理为:当查询一条数据时,需要判断所涉及元组的可见性,也就需要知道该元组的提交状态( 查看CLOG) ,如果同一条数据经常被查询或被访问,就需要多次去查看CLOG文件,会涉及较高代价的I/O操作。而将可见性标识位t_infomask直接写入把事务状态直接记录在元组头中(HeapTupleHeaderData),避免频繁访问CLOG影响从而加快可见性判断。
2.3 t_infomask的计算
postgres=# insert into test values(1);
postgres=# insert into test values(2);
postgres=# select *, t_xmin,t_xmax, t_infomask,t_infomask2 from heap_page_items(get_raw_page('test',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 | t_xmin | t_xmax | t_infomask | t_infomask2
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+------------+--------+--------+------------+-------------
1 | 16352 | 1 | 28 | 824 | 0 | 0 | (0,1) | 1 | 2048 | 24 | | | \x01000000 | 824 | 0 | 2048 | 1
2 | 16320 | 1 | 28 | 825 | 0 | 0 | (0,2) | 1 | 2048 | 24 | | | \x02000000 | 825 | 0 | 2048 | 1
(2 rows)
可以看出插入 1 的事务id 为824, 插入 2 的事务id 为825。两者的标志位 t_infomask = 2048, 换算成16进制为0x0800;根据上述t_infomask的宏定义可知 t_xmax invalid/aborted,这是因为插入数据t_xmax不发生变化,为0;并不知道t_xmin是否提交,也就是说下次查询的时候并不能直接判断该元组的可见性,需要从CLOG读取事务的提交状态。
问题来了,那怎么才能避免后续重读读取CLOG文件,加快元组可见性判断和数据的读取呢?见下:
postgres=# select * from test;
id
----
1
2
(2 rows)
postgres=# select *, t_xmin,t_xmax, t_infomask,t_infomask2 from heap_page_items(get_raw_page('test',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 | t_xmin | t_xmax | t_infomask | t_infomask2
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+------------+--------+--------+------------+-------------
1 | 16352 | 1 | 28 | 824 | 0 | 0 | (0,1) | 1 | 2304 | 24 | | | \x01000000 | 824 | 0 | 2304 | 1
2 | 16320 | 1 | 28 | 825 | 0 | 0 | (0,2) | 1 | 2304 | 24 | | | \x02000000 | 825 | 0 | 2304 | 1
(2 rows)
从上述例子看出,执行select 语句后发现t_infomask从2048转变成2304,换算成16进制为0x0900;即
0x0800 | 0x0100 = 0x0900,表明设置了HEAP_XMIN_COMMITTED(0x0100)这个标志位,该元组插入成功并已提交,对后续事务均可见。
等到第一次访问(可能是VACUUM,DML或SELECT)该元组并进行可见性判断时:
如果Hint Bits已设置,直接读取Hint Bits的值。
如果Hint Bits未设置,则调用函数从CLOG中读取事务状态。如果事务状态为COMMITTED或ABORTED,则将Hint Bits设置到元组的t_informask字段。如果事务状态为INPROCESS,由于其状态还未到达终态,无需设置Hint Bits。
https://www.pudn.com/news/62444b37852c2d5b7e8042ef.html
评论
有用 0
墨值悬赏

