ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# SET TRANSACTION ## Name SET TRANSACTION -- 设置当前事务的特性 ## Synopsis ``` SET TRANSACTION _transaction_mode_ [, ...] SET TRANSACTION SNAPSHOT _snapshot_id_ SET SESSION CHARACTERISTICS AS TRANSACTION _transaction_mode_ [, ...] 这里的 `_transaction_mode_`是下列之一: 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`, `FETCH`, 或 `COPY`)执行之后就不能再次设置。 参阅[Chapter 13](#calibre_link-444) 获取有关事务隔离级别和并发性控制的更多信息。 事务访问模式决定事务是读/写还是只读。读/写是缺省。如果一个事务是只读, 而且写入的表不是临时表,那么下面的 SQL 命令是不允许的:`INSERT`, `UPDATE`, `DELETE`, `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.26.5](#calibre_link-510))输出了它的快照。 这个函数返回一个快照标识符,这个标识符必须给`SET TRANSACTION SNAPSHOT` 以指出要输出哪个快照。该标识符在这个命令中必须写作字符串,例如`'000003A1-1'`。 `SET TRANSACTION SNAPSHOT`只能在该事务第一次查询或数据修改语句执行之前设置, (`SELECT`, `INSERT`, `DELETE`, `UPDATE`, `FETCH`, `COPY`)。另外,事务必须已经设置为`SERIALIZABLE` 或`REPEATABLE READ`隔离级别(否则,快照会被立即丢弃,因为 `READ COMMITTED`模式为每个命令接受一个新的快照)。如果导入事务使用 `SERIALIZABLE`隔离级别,那么输出快照的事务必须也使用该隔离级别。 还有,非只读的序列化事务不能从一个只读的事务中导入一个快照。 ## 注意 如果执行`SET TRANSACTION`之前没有执行`START TRANSACTION` 或`BEGIN`,那么它会显得没有效果一样,因为事务将立即结束。 可以用在`BEGIN`或`START TRANSACTION` 里面声明所需要的`_transaction_modes_` 的方法来避免使用`SET TRANSACTION`。但是这个选项不适用于 `SET TRANSACTION SNAPSHOT`。 会话的缺省事务模式也可以通过设置配置参数 [default_transaction_isolation](#calibre_link-511), [default_transaction_read_only](#calibre_link-512), 和 [default_transaction_deferrable](#calibre_link-513)的方法来设置。 (实际上`SET SESSION CHARACTERISTICS`只是一个用`SET` 来设置这些参数的另一种等效的方法)。这就意味着缺省值可以通过`ALTER DATABASE` 或在配置文件里等方法设置。参考[Chapter 18](#calibre_link-500)获取更多信息。 ## 例子 开启一个与已经存在的事务具有相同快照的新事务,首先从现存事务中输出快照。 这将返回快照的标识符,例如: ``` BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT pg_export_snapshot(); pg_export_snapshot -------------------- 000003A1-1 (1 row) ``` 然后在新打开的事务的开始的`SET TRANSACTION SNAPSHOT`命令中给出快照标识符: ``` BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '000003A1-1'; ``` ## 兼容性 这些命令在SQL标准中定义了,除了`DEFERRABLE` 事务模式和`SET TRANSACTION SNAPSHOT`格式是PostgreSQL 的扩展。 标准里的缺省事务隔离级别是`SERIALIZABLE`; 但在PostgreSQL里,缺省隔离级别是 `READ COMMITTED`, 但是你可以用上面描述的方法修改它。 在 SQL 标准里还有另外一种事务特性可以用这些命令设置:诊断范围的大小。 这个概念只用于嵌入式 SQL ,因此没有在PostgreSQL服务器里实现。 SQL 标准要求在相连的`_transaction_modes_` 之间使用逗号,但是因为历史原因,PostgreSQL允许省略这个逗号。