多事物
多事务是因为行级锁出现的,当有多个session对同一行记录添加行级锁时,就会出现多事务。下面我们使用一个例子来演示一下多事务的出现。
添加测试数据:

session1:

执行for share后上图t_xmax更新为495,没问题。
session2:

执行for share后,上图t_xmax变成了1,为什么会是1呢?
我们看下控制文件

控制文件中有一行NextMultiXactId: 1,这个就是多事物ID,表示有多个事务锁定了这一行,也就是在session2中看到的t_xmax的值,这次多事物结束后NextMultiXactId会加1。
多事物状态信息存在pg_multixact目录下

2PC事务
两阶段提交(2PC)事务它的目的是允许一个外部事务管理器在多个数据库或者其他事务性来源之间执行原子的全局事务。除非你在编写一个事务管理器,否则你可能不会用到PREPARE TRANSACTION。
要演示2PC事务,首先要修改max_prepared_transactions参数大于0,官方手册建议与max_connections一样。

开始演示:

当执行prepare transaction 'test_2pc'也就是一阶段提交后我们已经退出了事务块,但是事务没有完全提交所以我们无法查询到事务块内插入的数据,commit prepared 'test_2pc'也就是二阶段提交后,2PC事务已完成,所以又重新获取到了数据。
pg_prepared_xacts系统事物记录了2PC事务完成一段提交,未完成二段提交的事务信息。

pg_twophase目录存储事物数据,提交状态与普通事务一样存储在pg_xcat目录下:

在什么时候pg_twophase目录不为空呢?我们接着演示:
当我们执行完一段提交后,pg_twophase目录仍为空
退出当前session,pg_twophase目录仍为空

关闭数据库,pg_twophase目录下有文件了,

如上000001F9文件就是2PC事务505创建的存储文件。 
执行第二段提交后,pg_twophase目录为空。

让一个事务处于准备好状态太久是不明智的。这将会干扰 VACUUM回收存储的能力,并且在极限情况下可能导致 数据库关闭以阻止事务 ID 回卷(见第 24.1.5 节 )。还要记住,该事务会继续持有它已经持有的锁。该特性的设计用法是,只要一个外部事务管理器已经验证其他数据库也准备好了要提交,一个准备好的事务将被正常地提交或者回滚。
如果没有建立一个外部事务管理器来跟踪准备好的事务并且确保它们被迅速地结束,最好禁用准备好事务特性(设置 max_prepared_transactions为零)。这将防止意外地创建准备好事务,不然该事务有可能被忘记并且最终导致问题。




