上一篇中描述了存储页面的格式和回滚机制,也了解了删除数据并不会马上释放空间,但是你可能还是有疑问,有没有办法‘看到’事务修改过程呢,下面我们一起来‘看看’数据更新时元数据的变化。
在开始演示之前,我们先引入pg_attribute表(The catalog pg_attribute stores information about table columns. There will be exactly one pg_attribute row for every column in every table in the database.)
从官方文档看出,attname对应列名,attnum和attname对应,代表该列在postgresql表中列序号,其中系统列的序号是负数。
看一个实际的例子,还是用t_mvcc表举例:
postgres=> select attrelid,attname,attnum from pg_attribute where attrelid='public.t_mvcc'::regclass;
接下来看一个实际更新的例子:
T | A Session | B Session |
---|---|---|
T1 | begin;--查看XID select txid_current(); txid_current-------------- 12548select cmax,xmax,cmin,xmin,ctid,id,val from t_mvcc where id=20000003; | --查看XID select txid_current(); txid_current-------------- 12549--select txid_current_snapshot(); |
T2 | --更新数据 update t_mvcc set val='11923:12548:11923,11928,11932,11939-update' where id=20000003; | --查询ID=20000003的数据select cmax,xmax,cmin,xmin,ctid,id,val from t_mvcc where id=20000003; |
T3 | --提交事务 commit; | --查询ID=20000003的数据select cmax,xmax,cmin,xmin,ctid,id,val from t_mvcc where id=20000003; --select txid_current_snapshot(); |
- T1时刻A Session XID=12548,B Session XID=12549,由于A先开启事务且未提交/回滚,所以A Session对B Session来说是活跃事务。
- T2时刻A Session执行update SQL,它把对应版本XMIN标记为自己XID=12548,而自己‘看到’的内容是更新后的内容。此时B Session查询数据ID=20000003的记录时,看出xmax=12548是A Session XID且未提交,所以查出来的记录是更新前的值。
- T3时刻A Session提交事务,B Session再次执行查询数据ID=20000003的记录,通过查询活跃事务列表看出,A Session XID已经不再事务快照中,所以B Session能够看到A Session更新的记录。