SET TRANSACTION — 设置当前事务的特性
SET TRANSACTIONtransaction_mode[, ...] SET TRANSACTION SNAPSHOTsnapshot_idSET SESSION CHARACTERISTICS AS TRANSACTIONtransaction_mode[, ...] wheretransaction_modeis one of: ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } READ WRITE | READ ONLY [ NOT ] DEFERRABLE
SET TRANSACTION 命令设置当前事务的特性。它对后续的任何事务都没有影响。SET SESSION CHARACTERISTICS 为一个会话的后续事务设置默认的事务特性。对于单个事务,这些默认值可以通过 SET TRANSACTION 加以覆盖。
可用的事务特性包括事务隔离级别、事务访问模式(读/写或只读)以及可延迟模式。此外,还可以选择一个快照,但只能针对当前事务,不能作为会话的默认值。
一个事务的隔离级别决定了该事务在其他事务并发运行时能看到哪些数据:
READ COMMITTED一个语句只能看到在它开始之前已提交的行。这是默认值。
REPEATABLE READ当前事务的所有语句只能看到在该事务中执行第一条查询或数据修改语句之前已提交的行。
SERIALIZABLE 当前事务的所有语句只能看到在该事务中执行第一条查询或数据修改语句之前已提交的行。如果并发可串行化事务之间的读写模式会造成一种在这些事务的任何串行(一次一个)执行中都不可能出现的情形,那么其中一个事务将被回滚并产生 serialization_failure 错误。
SQL 标准还定义了一个额外的级别 READ UNCOMMITTED。在 PostgreSQL 中,READ UNCOMMITTED 被视为 READ COMMITTED。
在事务的第一条查询或数据修改语句(SELECT、INSERT、DELETE、UPDATE、MERGE、FETCH 或 COPY)执行之后,事务隔离级别就不能再更改了。有关事务隔离和并发控制的更多信息,请参见 Chapter 13。
事务访问模式决定事务是读/写的还是只读的。默认为读/写。当事务为只读时,以下 SQL 命令是不允许的:如果这些命令要写入的表不是临时表,则不允许 INSERT、UPDATE、DELETE、MERGE 和 COPY FROM;所有 CREATE、ALTER 和 DROP 命令;COMMENT、GRANT、REVOKE、TRUNCATE;以及 EXPLAIN ANALYZE 和 EXECUTE(如果它们要执行的命令属于上面列出的命令)。这是一种高层次的只读概念,并不会阻止所有对磁盘的写入。
DEFERRABLE 事务属性只有在事务同时也是 SERIALIZABLE 和 READ ONLY 时才会起作用。当一个事务同时选择了这三种属性时,该事务在首次获取快照时可能会阻塞,此后它就可以在没有 SERIALIZABLE 事务通常开销的情况下运行,并且不会有任何导致序列化失败或者被序列化失败取消的风险。这种模式非常适合长时间运行的报表或备份。
SET TRANSACTION SNAPSHOT 命令允许一个新事务使用与某个现有事务相同的 快照 来运行。已有的事务必须已经使用 pg_export_snapshot 函数导出过它的快照(参见 Section 9.28.5)。该函数会返回一个快照标识符,必须把它提供给 SET TRANSACTION SNAPSHOT,以指定要导入哪个快照。在这个命令中,该标识符必须写成一个字符串字面值,例如 '00000003-0000001B-1'。SET TRANSACTION SNAPSHOT 只能在事务开始时执行,也就是在该事务的第一条查询或数据修改语句(SELECT、INSERT、DELETE、UPDATE、MERGE、FETCH 或 COPY)之前。此外,该事务必须已经被设置为 SERIALIZABLE 或 REPEATABLE READ 隔离级别(否则快照会被立即丢弃,因为 READ COMMITTED 模式会为每条命令获取一个新快照)。如果导入快照的事务使用 SERIALIZABLE 隔离级别,那么导出快照的事务也必须使用该隔离级别。另外,非只读的可串行化事务不能从只读事务导入快照。
如果在没有先执行 START TRANSACTION 或 BEGIN 的情况下执行 SET TRANSACTION,它会发出一个警告,除此之外没有任何效果。
也可以不用 SET TRANSACTION,而是直接指定所需的 transaction_modes,即在 BEGIN 或 START TRANSACTION 中给出它们。但这个选项不适用于 SET TRANSACTION SNAPSHOT。
会话的默认事务模式也可以通过配置参数 default_transaction_isolation、default_transaction_read_only 和 default_transaction_deferrable 来设置或查看。(实际上,SET SESSION CHARACTERISTICS 只不过是用 SET 设置这些变量的一种冗长等价形式。)这意味着这些默认值可以在配置文件中设置,也可以通过 ALTER DATABASE 等方式设置。更多信息请查阅 Chapter 19。
当前事务的模式同样可以通过配置参数 transaction_isolation、transaction_read_only 和 transaction_deferrable 来设置或查看。设置这些参数中的任何一个,其效果与相应的 SET TRANSACTION 选项相同,并且在何时可以进行设置方面也有同样的限制。不过,这些参数不能在配置文件中设置,也不能从实际 SQL 之外的任何来源设置。
要以与某个现有事务相同的快照开始一个新事务,请先从该现有事务导出快照。这将返回快照标识符,例如:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT pg_export_snapshot(); pg_export_snapshot --------------------- 00000003-0000001B-1 (1 row)
然后在新打开的事务开始处,在一条 SET TRANSACTION SNAPSHOT 命令中给出该快照标识符:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '00000003-0000001B-1';
这些命令在 SQL 标准中都有定义,但 DEFERRABLE 事务模式和 SET TRANSACTION SNAPSHOT 形式除外,它们是 PostgreSQL 的扩展。
在标准中,SERIALIZABLE 是默认的事务隔离级别。在 PostgreSQL 中,默认值通常是 READ COMMITTED,但可以如上所述对其进行更改。
在 SQL 标准中,还有一种事务特性可以用这些命令来设置:诊断区的大小。这个概念是嵌入式 SQL 特有的,因此在 PostgreSQL 服务器中没有实现。
SQL 标准要求连续的 transaction_modes 之间用逗号分隔,但由于历史原因,PostgreSQL 允许省略这些逗号。