在查看此内容前,需要先了解一些PG数据库相关基础概念:
1、事务ID:TXID,详见本专栏:PostgreSQL(十八)TXID与冻结
2、PG中的元组结构、DML操作原理,详见本专栏:PostgreSQL(十五)行结构与DML操作
3、PG记录事务状态的方式、事务快照概述,详见本专栏:PostgreSQL(十九)PG事务概述
一、事务快照在可见性规则中的作用
核心思想:过去已发生的为 可见,将来未发生的为 不可见
二、可见性判断的重要因素&常见规则
可见性判断有四个重要因素:t_xmin、t_xmax、clog、获取的事务快照
1、T_Xmin,T_xmax
T_Xmin有3种状态:Abort、In_Progress、Commited
(1)T_Xmin=Aborted 不可见
表示插入此元组的事务已被终止,则判断此行为始终不可见;
此规则显示表示为以下逻辑表达式:
/*t_xmin status=ABORTED*/
Rule1:
IF t_xmin status is 'ABORTED' THEN
RETURN 'Invisible'
End IF
2)T_Xmin= In_Progress 当前事务可见
此规则显示表示为以下逻辑表达式:
/*t_xmin stat=IN_PROGRESS*/
IF t_xmin status is 'IN_PROGRESS' THEN
IF t_xmin=current_txid THEN
RULE2: IF t_xmax = INVALID THEN
RETURN 'Visible'
RULE3: ELSE /*this tuple has been deleted or updated by the current transaction itself.*/
RETURN 'Invisible'
END IF
RULE4: ELSE /* t xmin ≠ current_txid*/
RETURN 'Invisible'
END IF
END IF
(3)T_Xmin= Commited 需要判断
此时的状态判断需要考虑t_xmax的值,如果t_xmax=0,则此行可见;
如果t_xmax≠0,则还得判断t_xmax的状态是否为当前事务,判断规则较为复杂;
此规则显示表示为以下逻辑表达式:
/*t_xmin status=COMMITTED*/
IF t_xmin status is COMMITTED THEN
RULE5: IF t_xmin is active in the obtained transaction snapshot THEN
RETURN 'Invisible'
RULE6: ELSE IF t_xmax =INVALID OR status of t_xmax is 'ABORTED' THEN
RETURN 'Visible'
ELSE IF t_xmax status is 'IN_PROGRESS' THEN
RULE7: IF t_xmax= current_txid THEN
RETURN 'Invisible'
RULE8: ELSE /*t_xmax ≠ current_txid*/
RETURN 'Visible'
END IF
ELSE IF t_xmax status is 'COMMITTED' THEN
RULE9: IF t_xmax is active in the obtained transaction snapshot THEN
RETURN 'Visible'
RULE10: ELSE
RETURN 'Invisible'
END IF
END IF
END IF
2、可见性判断示例
T3:依据RULE6判断:Status(t_xmin:199)=committed^t_xmax=invalid --> visible
T5:对于事务id=200来说,
第一行数据可见性参见Rule7:
Status(t_xmin:199)=committed ^ Status(t_xmax:200)=IN_PROGRESS ^ t_xmax:200=current_txid:200 --> Invisible
第二行数据可见性参见Rule2:
Status(t_xmin:200)=IN_PROGRESS ^ t_xmin:200=current_txid:200 ^ t_xmax=INVALID --> Visible
对于事务id=201来说,
第一行数据可见性参见RULE8:
Status(t_xmin:199)=committed ^ Status(t_xmax:200)=IN_PROGRESS ^ t_xmax:200≠current_txid:200 --> visible
第二行数据可见性参见RULE4:
Status(t_xmin:200)=IN_PROGRESS ^ t_xmin:200≠current_txid:200 --> Invisible
T7:此时刻,需根据事务隔离级别来判断可见性;
对于读提交(read committed)来说,依据RULE10、RULE6来判断:
第一行数据可见性参见RULE8:
Status(t_xmin:199)=committed ^ Status(t_xmax:200)= committed ^Snapshot( t_xmax:200)≠active --> Invisible
第二行数据可见性参见RULE4:
Status(t_xmin:200)= committed ^ t_xmax=Invalid --> visible
对于可重复读(repeatable read)来说,依据RULE9、RULE5来判断:
第一行数据可见性参见RULE9:
Status(t_xmin:199)=committed ^ Status(t_xmax:200)= committed ^Snapshot( t_xmax:200)=active --> visible
第二行数据可见性参见RULE5:
Status(t_xmin:200)= committed ^ Snapshot( t_xmax:200)=active --> Invisible
3、提高判断效率
(1)Hint Bits
由于进行行可见性判断时,都需要查看存储在clog中T_Xmin和T_Xmax的状态,为了 解决对clog频繁访问的问题,PG使用了提示位,在行头提示事务的提交状态,如:
三、实现闪回功能
PG目前的官方版本并没有闪回功能,但从理论上来说,PG数据的更新时,新旧数据都保留在数据块中,可以实现像Oracle一样的闪回查询功能,只要在判断时先判断该查询是否是闪回査询,然后再根据一个针对闪回査询的可见性规则判断就可以实现。
如果要实现闪回查询,会涉及到 Vacuum操作时需要考虑更多的因素,需要有个参数来设置块中被删除的行保留的时间长度。
此功能实现依赖到专业的PG开发,期待将来能深入学习至此,再开专篇与大家共享。