目录
一、TXID简介
1、定义
txid=事务id:当一个事务开始时,pg的事务管理系统会为该事务分配一个唯一标识符:事务id,即txid
pg中的txid被定义为一个32位的无符号整数,约能记录42亿个事务;
通常来说,txid对管理者是透明的,但我们可以利用pg的内部函数txid_current(),来获取当前事务的txid:
事务ID用来标识一个事务的先后顺序,该顺序决定了锁申请的优先权,以及访问一张表时对行的可见性规则判断。
注:begin命令并不会分配txid,而是在begin之后执行的第一个DML命令,在执行时,事务管理器会分配一个txid,然后事务才算开始。
2、txid的结构
PG有一个行可见性规则的概念,由于多版本并发控制的存在,不同事务对相同表的查询结果未必是相同的(这块在十九章中详细描述);
在此规则中,visible(过去的)事务,是可见的;invisible(未来的)事务,是不可见的;
3、TXID环绕
TXID环绕问题产生过程:
-->假设元组tuple_1的txid为100,即tuple_1的t_xmin为100,且服务器运行了很久之后,tuple_1依然没有被修改;
-->当前的txid是21亿+100,执行select命令;
-->此时,tuple_1根据可见性规则,被判断为可见,因为txid 100是过去的;
-->紧接着,又执行相同的select命令,此时,当前的txid变为21亿+101,根据可见性规则判断,tuple_1为不可见,因为txid=100被判定为未来的;
-->在tuple_1没有被新事务修改的情况下,前后两次对其的查询结果发生了变化,这就是TXID环绕
二、冻结与解冻
PG中,解决事务环绕问题的方法:冻结&解冻;
其做法是把21亿以前的事务修改的行做一个标记位(即冻结),跳过行可见性规则,凡是被标识为冻结行的,在判断时不依赖t_xmin,直接判定为可见数据。
若TXID使用过一轮之后,被冻结的行被新事务修改,则原来的标记位被消除(即解冻),此时,此行是否可见,依然根据可见性规则,依赖t_xmin决定。
三、如何冻结TXID
1、冻结处理的两种模式
(1)lazy mode :惰性模式
冻结极限txid的定义如下:
freezeLimit_txid=(OldestXmin-vacuum_freeze_min_age)
Autovacuum操作会进行冻结操作,每分钟执行一次,被选中的表都会进行Vacuum操作,包含冻结txid内容。
(2)eager mode :急切模式
当满足以下条件时,执行急切模式:
pg_database.datfrozenxid < (OldestXmin-vacuum_freeze_table_age)
在急切模式下,可能会突然冻结很多行,属于I/O密集型操作
(3)对比
2、查询信息
(1)显示被冻结的对象信息
vacuum test2;
SELECT n.nspname as "Schema",c.relname as "Name",c.relfrozenxid
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace
WHERE c.relkind IN('r','')
AND n. nspname <> 'information_schema'
AND n. nspname !~ '^pg_ toast'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY c.relfrozenxid::text::bigint DESC;
(2)显示被冻结的数据库信息
SELECT datname,datfrozenxid FROM pg_database WHERE datname='wqdb';
3、使用_VM提高效率
在可见性地图中,将惰性冻结操作过的页,记录为1;
在进行急性冻结时,会跳过这样的页,这样可以大大提高急切冻结的效率。