=============== SET TRANSACTION =============== .. container:: refentry :name: SQL-SET-TRANSACTION .. container:: titlepage .. container:: refnamediv .. rubric:: SET TRANSACTION :name: set-transaction SET TRANSACTION — 设置当前事务的特性 .. container:: refsynopsisdiv .. rubric:: 大纲 :name: 大纲 .. code:: 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 .. container:: refsect1 :name: id-1.9.3.177.8 .. rubric:: 描述 :name: 描述 ``SET TRANSACTION``\ 命令设置当前 会话的特性。\ ``SET SESSION CHARACTERISTICS``\ 设置一个会话后续事务的默认 事务特性。在个体事务中可以用 ``SET TRANSACTION``\ 覆盖这些默认值。 可用的事务特性是事务隔离级别、事务访问模式(读/写或只读)以及 可延迟模式。此外,可以选择一个快照,不过只能用于当前事务而不能 作为会话默认值。 一个事务的隔离级别决定当其他事务并行运行时该事务能看见什么数据: .. container:: variablelist ``READ COMMITTED`` 一个语句只能看到在它开始前提交的行。这是默认值。 ``REPEATABLE READ`` 当前事务的所有语句只能看到这个事务中执行的第一个查询或者 数据修改语句之前提交的行。 ``SERIALIZABLE`` 当前事务的所有语句只能看到这个事务中执行的第一个查询或者 数据修改语句之前提交的行。如果并发的可序列化事务间的读写 模式可能导致一种那些事务串行(一次一个)执行时不可能出现 的情况,其中之一将会被回滚并且得到一个 ``serialization_failure``\ 错误。 SQL 标准定义了一种额外的级别:\ ``READ UNCOMMITTED``\ 。在 PostgreSQL中\ ``READ UNCOMMITTED``\ 被视作 ``READ COMMITTED``\ 。 一个事务执行了第一个查询或者数据修改语句( ``SELECT``\ 、 ``INSERT``\ 、\ ``DELETE``\ 、 ``UPDATE``\ 、\ ``FETCH``\ 或 ``COPY``\ )之后就无法更改事务隔离级别。 更多有关事务隔离级别和并发控制的信息可见\ `多版本控制 `__\ 。 事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。 当一个事务为只读时,如果 SQL 命令 ``INSERT``\ 、\ ``UPDATE``\ 、 ``DELETE``\ 和\ ``COPY FROM`` 要写的表不是一个临时表,则它们不被允许。不允许 ``CREATE``\ 、\ ``ALTER``\ 以及 ``DROP``\ 命令。不允许\ ``COMMENT``\ 、 ``GRANT``\ 、\ ``REVOKE``\ 、 ``TRUNCATE``\ 。如果\ ``EXPLAIN ANALYZE`` 和\ ``EXECUTE``\ 要执行的命令是上述命令之一, 则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对 磁盘的写入。 只有事务也是\ ``SERIALIZABLE``\ 以及 ``READ ONLY``\ 时,\ ``DEFERRABLE`` 事务属性才会有效。当一个事务的所有这三个属性都被选择时,该事务在 第一次获取其快照时可能会阻塞,在那之后它运行时就不会有 ``SERIALIZABLE``\ 事务的开销并且不会有任何牺牲或者 被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者 备份。 ``SET TRANSACTION SNAPSHOT``\ 命令允许新的事务 使用与一个现有事务相同的\ *快照*\ 运行。已经存在的事务 必须已经把它的快照用\ ``pg_export_snapshot``\ 函数( 见\ `第 9.26.5 节 `__\ )导出。 该函数会返回一个快照标识符,\ ``SET TRANSACTION SNAPSHOT``\ 需要被给定一个快照标识符来指定要导入的快照。 在这个命令中该标识符必须被写成一个字符串,例如 ``'000003A1-1'``\ 。 ``SET TRANSACTION SNAPSHOT``\ 只能在一个事务的 开始执行,并且要在该事务的第一个查询或者数据修改语句( ``SELECT``\ 、 ``INSERT``\ 、\ ``DELETE``\ 、 ``UPDATE``\ 、\ ``FETCH``\ 或 ``COPY``\ )之前执行。此外,该事务必须已经被设置 为\ ``SERIALIZABLE``\ 或者 ``REPEATABLE READ``\ 隔离级别(否则,该快照将被立刻抛弃, 因为\ ``READ COMMITTED``\ 模式会为每一个命令取一个新快照)。 如果导入事务使用了\ ``SERIALIZABLE``\ 隔离级别,那么导入快照 的事务必须也使用该隔离级别。还有,一个非只读可序列化事务不能导入来自只读 事务的快照。 .. container:: refsect1 :name: id-1.9.3.177.9 .. rubric:: 注解 :name: 注解 如果执行\ ``SET TRANSACTION``\ 之前没有 ``START TRANSACTION``\ 或者 ``BEGIN``\ ,它会发出一个警告并且不会有任何效果。 可以通过在\ ``BEGIN``\ 或者 ``START TRANSACTION``\ 中指定想要的\ *``transaction_modes``*\ 来省掉 ``SET TRANSACTION``\ 。但是在 ``SET TRANSACTION SNAPSHOT``\ 中该选项不可用。 会话默认的事务模式也可以通过设置配置参数 `default_transaction_isolation `__\ 、 `default_transaction_read_only `__\ 和 `default_transaction_deferrable `__\ 来设置(实际上 ``SET SESSION CHARACTERISTICS``\ 只是用 ``SET``\ 设置这些变量的等效体)。这意味着可以通过配置文件、 ``ALTER DATABASE``\ 等方式设置默认值。 .. container:: refsect1 :name: id-1.9.3.177.10 .. rubric:: 示例 :name: 示例 要用一个已经存在的事务的同一快照开始一个新事务,首先要从该现有 事务导出快照。这将会返回快照标识符,例如: .. code:: programlisting BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT pg_export_snapshot(); pg_export_snapshot --------------------- 00000003-0000001B-1 (1 row) 然后在一个新开始的事务的开头把该快照标识符用在一个 ``SET TRANSACTION SNAPSHOT``\ 命令中: .. code:: programlisting BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '00000003-0000001B-1'; .. container:: refsect1 :name: R1-SQL-SET-TRANSACTION-3 .. rubric:: 兼容性 :name: 兼容性 SQL标准中定义了这些命令,不过 ``DEFERRABLE``\ 事务模式和 ``SET TRANSACTION SNAPSHOT``\ 形式除外,这两者是 PostgreSQL扩展。 ``SERIALIZABLE``\ 是标准中默认的事务隔离级别。在 PostgreSQL中默认值是普通的 ``READ COMMITTED``\ ,但是你可以按上述的方式更改。 在 SQL 标准中,可以用这些命令设置一个其他的事务特性:诊断区域 的尺寸。这个概念与嵌入式 SQL 有关,并且因此没有在 PostgreSQL服务器中实现。 SQL 标准要求连续的\ *``transaction_modes``*\ 之间有逗号, 但是出于历史原因 PostgreSQL允许省略逗号。