PostgreSQL 支持两阶段提交事务(two-phase commit),简称 2PC。单机版本的 PG 很少会用到 2PC 事务,而基于 PG 的分布式数据库,其事务管理器大多数都是基于 PG 的 2PC 事务或者在其基础上进行修改实现。
一、2PC 事务相关命令
PG 提供了一组命令用于 2PC 事务,如下:
- prepare transaction 'xxx'
- commit prepared 'xxx'
- rollback prepared 'xxx'
其中 'xxx' 为事务 ID,它是一个小于 200 字符的字符串,且不能与 prepared 的事务 ID 相同。
prepare transaction 'xxx' 预备好当前事务,为 2PC 的提交做准备,这个命令执行完成后,当前事务不再与当前会话关联,事务状态会存储到磁盘上,并且很大可能性这个事务在后面会提交成功,即使在提交前,数据库发生崩溃也不会影响该事务的状态。此时我们称这个事务的状态为 prepared ,prepared 的事务数据不是可见的。如果在 prepared 的过程中失败了,事务将被回滚。
一旦事务变成 prepared 状态,它在后续将会被提交或者回滚。执行 commit prepared 'xxx' 进行提交,执行 rollback prepared 'xxx' 进行回滚。这两个命令可以在任一会话中执行,并不需要在事务原始会话中执行。
2PC 事务不用于一般的应用程序或者交互式会话,它的目的是允许外部事务管理器进行跨多个数据节点的全局事务原子化,除非你需要写一个事务管理器,否则通常不会用到 2PC 事务。
prepare transaction 命令必须被包含在事务块中,即 begin 开始的事务块中。commit prepared 和 rollback prepared 命令不能在事务块中执行。
2PC 事务执行过程中不允许使用临时表、会话的临时命名空间,这些对象与会话关系高度紧密,而 2PC 事务是与会话无关的,因此不能在 2PC 事务中使用这些临时对象。
二、2PC 事务相关视图
所有 prepared 的事务,可通过视图 pg_prepared_xacts 进行查询,如下:select * from pg_prepared_xacts;
三、2PC 事务相关参数
max_prepared_transactions 表示最大的 prepared 事务的数量,设置为 0 则表示关闭 2PC 事务。
四、2PC 事务注意事项
不要让 prepared 的事务长时间存在,它会干扰 vacuum 回收,在极端情况下为了防止事务 ID 回卷,可能导致数据库关闭。
五、2PC 事务使用示例
session1:
begin;
insert into t values (1,'a');
prepare transaction 'T100';
session2:
commit prepared 'T100';
或者
rollback prepared 'T100';