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により個々のトランザクションのデフォルト特性を上書きすることができます。
利用可能なトランザクション特性はトランザクションの隔離レベル、トランザクションのアクセスモード(読み書きモードもしくは読み取りのみモード)、遅延モードです。 さらに、セッションのデフォルトとしてではなく、現在のトランザクションのみに対してスナップショットを選択することができます。
トランザクションの隔離レベルは、並行して実行中の他のトランザクションが存在する場合、そのトランザクションが見ることができるデータを決定するものです。
1つひとつの文から見ることができるのは、その文が開始される前にコミットされた行のみです。 これがデフォルトです。
現在のトランザクションにおける全ての文は、トランザクションで最初の問い合わせ文またはデータを変更する文が実行される前にコミットされた行だけを見ることができます。
現在のトランザクションにおける全ての文は、トランザクションで最初の問い合わせ文またはデータを変更する文が実行される前にコミットされた行だけを見ることができます。 同時実行のシリアライザブルトランザクションの中で読み取りと書き込みのパターンによって、これらのトランザクションの実行を直列に(同時に一度)行うことができない状況になる場合、その内1つのトランザクションはserialization_failureというエラーでロールバックされます。
標準SQLでは、さらにREAD UNCOMMITTEDという1つのレベルを定義しています。 PostgreSQLではREAD UNCOMMITTEDはREAD COMMITTEDとして扱われます。
トランザクション隔離レベルは、そのトランザクションにおける最初の問い合わせ文やデータ更新文(SELECT、INSERT、DELETE、UPDATE、FETCH、COPY)が実行された後からは変更することができません。 トランザクションの隔離や同時実行制御についての詳細情報は第13章を参照してください。
トランザクションのアクセスモードは、そのトランザクションが読み書き可能か読み取りのみかを決定します。 デフォルトは読み書き可能です。 読み取りのみのトランザクションでは、書き込み対象のテーブルが一時テーブルでない限り、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'のようにリテラル文字列として記述しなければなりません。 トランザクションの開始時に、トランザクションの最初の問い合わせまたはデータ変更文(SELECT、INSERT、DELETE、UPDATE、FETCH、COPY)を行う前でのみ、SET TRANSACTION SNAPSHOTを実行することができます。 さらに、そのトランザクションを前もって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などで設定可能です。 詳細は第18章を参照してください。
既存のトランザクションと同じスナップショットを持つトランザクションを新しく開始するためには、まず既存のトランザクションからスナップショットを公開します。 以下の例に示すように、これはスナップショット識別子を返します。
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 is the default transaction isolation level in the standard. In PostgreSQL the default is ordinarily READ COMMITTED, but you can change it as mentioned above. --> 標準SQLではデフォルトのトランザクションはSERIALIZABLEです。 PostgreSQLでは、通常、READ COMMITTEDがデフォルトですが、これは上述の通り変更可能です。
標準SQLでは、もう1つ、診断領域の大きさというトランザクション特性があり、このコマンドで設定可能です。 この概念は組み込みSQL固有のものなので、PostgreSQLサーバには実装されていません。
標準SQLでは、連続するtransaction_modesの間にはカンマが必要です。 歴史的な理由よりPostgreSQLではカンマを省略することができます。