SET TRANSACTION — 現在のトランザクションの特性を設定する
SET TRANSACTIONtransaction_mode
[, ...] SET TRANSACTION SNAPSHOTsnapshot_id
SET SESSION CHARACTERISTICS AS TRANSACTIONtransaction_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
1つひとつの文から見ることができるのは、その文が開始される前にコミットされた行のみです。 これがデフォルトです。
REPEATABLE READ
現在のトランザクションにおける全ての文は、トランザクションで最初の問い合わせ文またはデータを変更する文が実行される前にコミットされた行だけを見ることができます。
SERIALIZABLE
現在のトランザクションにおける全ての文は、トランザクションで最初の問い合わせ文またはデータを変更する文が実行される前にコミットされた行だけを見ることができます。
同時実行のシリアライザブルトランザクションの中で読み取りと書き込みのパターンによって、これらのトランザクションの実行を直列に(同時に一度)行うことができない状況になる場合、その内1つのトランザクションはserialization_failure
というエラーでロールバックされます。
標準SQLでは、READ UNCOMMITTED
というもう1つのレベルを定義しています。
PostgreSQLではREAD UNCOMMITTED
はREAD COMMITTED
として扱われます。
トランザクション隔離レベルは、そのトランザクションにおける最初の問い合わせ文やデータ更新文(SELECT
、INSERT
、DELETE
、UPDATE
、FETCH
、COPY
)が実行された後では変更することができません。
トランザクションの隔離や同時実行制御についての詳細情報は13章同時実行制御を参照してください。
トランザクションのアクセスモードは、そのトランザクションが読み書き可能か読み取りのみかを決定します。
デフォルトは読み書き可能です。
読み取りのみのトランザクションでは、以下のSQLコマンドの実行が制限されます。
書き込み対象のテーブルが一時テーブルでない場合、INSERT
、UPDATE
、DELETE
、COPY FROM
などのSQLコマンドを実行できません。
すべてのCREATE
、ALTER
、DROP
系のSQLコマンド、COMMENT
、GRANT
、REVOKE
、TRUNCATE
は、実行できません。
さらに、上述のコマンドが含まれるEXPLAIN ANALYZE
とEXECUTE
コマンドも実行できません。
この方法ではディスクへの書き込みをすべて防ぐわけではないので、読み取り専用の高レベルの概念です。
DEFERRABLE
トランザクション属性は、トランザクションがSERIALIZABLE
かつREAD ONLY
である場合のみ効果があります。
あるトランザクションでこれら3つの属性がすべて選択されている場合、最初にスナップショットを獲得する時にブロックされる可能性があります。
その後、そのトランザクションを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
隔離レベルを使用している場合、スナップショットを公開したトランザクションもこの隔離レベルを使用しなければなりません。
また、読み取り専用ではないシリアライザブルトランザクションは、読み取り専用トランザクションから公開されたスナップショットを取り込むことができません。
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
などで設定可能です。
詳細は19章サーバの設定を参照してください。
既存のトランザクションと同じスナップショットを持つトランザクションを新しく開始するためには、まず既存のトランザクションからスナップショットを公開します。 以下の例に示すように、これはスナップショット識別子を返します。
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の拡張です。
標準SQLではデフォルトのトランザクションはSERIALIZABLE
です。
PostgreSQLでは、通常、READ COMMITTED
がデフォルトですが、これは上述の通り変更可能です。
標準SQLでは、もう1つ、診断領域の大きさというトランザクション特性があり、このコマンドで設定可能です。 この概念は組み込みSQL固有のものなので、PostgreSQLサーバには実装されていません。
標準SQLでは、連続するtransaction_modes
の間にはカンマが必要です。
歴史的な理由よりPostgreSQLではカンマを省略することができます。