子事务在事务内启动,允许将大型事务分解为更小的单元。子事务可以提交或中止,而不会影响其父事务,从而允许父事务继续。这使得更容易处理错误,这是常见的应用程序开发模式。子事务一词通常缩写为 子事务。
可以使用 SAVEPOINT
命令显式启动子事务,但也可以通过其他方式启动,例如 PL/pgSQL 的 EXCEPTION
子句。PL/Python 和 PL/Tcl 也支持显式子事务。子事务也可以从其他子事务启动。顶级事务及其子子事务形成一个层次结构或树,这就是我们称主事务为顶级事务的原因。
如果为子事务分配了非虚拟事务 ID,则其事务 ID 称为 “子事务 ID”。只读子事务不会被分配子事务 ID,但一旦它们尝试写入,就会被分配一个子事务 ID。这也导致子事务 ID 的所有父事务(包括顶级事务在内)都被分配非虚拟事务 ID。我们确保父事务 ID 始终低于其任何子子事务 ID。
每个子事务 ID 的直接父事务 ID 记录在 pg_subtrans
目录中。没有为顶级事务 ID 创建条目,因为它们没有父事务,也没有为只读子事务创建条目。
当子事务提交时,其所有已提交的具有子事务 ID 的子子事务也将被视为在该事务中已提交。当子事务中止时,其所有子子事务也将被视为已中止。
当具有 xid 的顶级事务提交时,其所有已提交的子事务也会持久记录为已提交,记录在 pg_xact
子目录中。如果顶级事务中止,其所有子事务也会中止,即使它们已提交。
每个事务保持打开(未回滚或释放)的子事务越多,事务管理开销就越大。每个后端在共享内存中最多缓存 64 个打开的子 xid;之后,由于在 pg_subtrans
中查找子 xid 条目,存储 I/O 开销会显著增加。