SET [GLOBAL | SESSION] TRANSACTIONtransaction_characteristic[,transaction_characteristic] ...transaction_characteristic: ISOLATION LEVELlevel| READ WRITE | READ ONLYlevel: REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE
このステートメントは、トランザクションの特性を指定します。これは、カンマで区切られた 1 つ以上の特性値のリストを受け取ります。これらの特性は、トランザクションの分離レベルまたはアクセスモードを設定します。分離レベルは、InnoDB
テーブルに対する操作に使用されます。アクセスモードはMySQL 5.6.5の時点で指定することができ、トランザクションが読み取り/書き込みまたは読み取り専用のどちらのモードで動作するかを示します。
さらに、SET TRANSACTION
には、ステートメントのスコープを示すオプションのGLOBAL
またはSESSION
キーワードを含めることができます。
トランザクションの特性のスコープ
トランザクションの特性はグローバルに、現在のセッションに対して、または次のトランザクションに対して設定できます。
GLOBAL
キーワードを指定すると、このステートメントは、以降のすべてのセッションに対してグローバルに適用されます。既存のセッションは影響を受けません。SESSION
キーワードを指定すると、このステートメントは、現在のセッション内で実行される以降のすべてのトランザクションに適用されます。SESSION
またはGLOBAL
キーワードのどちらも指定しない場合、このステートメントは、現在のセッション内で実行される次の (開始されていない) トランザクションに適用されます。
トランザクションの特性をグローバルに変更するには、SUPER
権限が必要です。どのセッションも、そのセッションの特性 (トランザクションの途中であっても)、または次のトランザクションの特性を自由に変更できます。
アクティブなトランザクションが存在する間は、GLOBAL
またはSESSION
を指定しないSET TRANSACTION
は許可されません。
mysql> START TRANSACTION; Query OK, 0 rows affected (0.02 sec) mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; ERROR 1568 (25001): Transaction characteristics can't be changed while a transaction is in progress
サーバーの起動時にグローバルなデフォルトの分離レベルを設定するには、コマンド行またはオプションファイルでmysqldに対して--transaction-isolation=
オプションを使用します。このオプションのlevel
level
の値では、スペースではなくダッシュが使用されるため、許可される値はREAD-UNCOMMITTED
、READ-COMMITTED
、REPEATABLE-READ
、またはSERIALIZABLE
です。たとえば、デフォルトの分離レベルをREPEATABLE READ
に設定するには、オプションファイルの[mysqld]
セクションで次の行を使用します。
[mysqld] transaction-isolation = REPEATABLE-READ
グローバルなトランザクション分離レベルやセッションのトランザクション分離レベルは、tx_isolation
システム変数を使用して、実行時にチェックまたは設定できます。
SELECT @@GLOBAL.tx_isolation, @@tx_isolation; SET GLOBAL tx_isolation='REPEATABLE-READ'; SET SESSION tx_isolation='SERIALIZABLE';
同様に、サーバーの起動時または実行時にトランザクションアクセスモードを設定するには、--transaction-read-only
オプションまたはtx_read_only
システム変数を使用します。デフォルトでは、これらはOFF
(モードは読み取り/書き込み) ですが、ON
に設定して読み取り専用のデフォルトモードにすることができます。
tx_isolation
またはtx_read_only
のグローバルまたはセッション値を設定することは、SET GLOBAL TRANSACTION
またはSET SESSION TRANSACTION
で分離レベルまたはアクセスモードを設定することと同等です。
分離レベルの詳細および使用方法
InnoDB
は、ここで説明されている各トランザクション分離レベルを、異なるロックの方法を使用してサポートしています。ACID準拠が重要な要件である重要なデータに対する操作の場合は、デフォルトのREPEATABLE READ
レベルを使用して高度な一貫性を適用できます。あるいは、正確な一貫性や繰り返し可能な結果がロックのためのオーバーヘッドの量の最少化ほど重要でない一括レポートなどの状況では、READ COMMITTED
や場合によってはREAD UNCOMMITTED
を使用して一貫性のルールを緩和できます。SERIALIZABLE
はREPEATABLE READ
よりさらに厳密なルールを適用し、主にXAトランザクションのほか、並列性やデッドロックに関する問題のトラブルシューティングなどの特殊な状況で使用されます。
これらの分離レベルがInnoDB
トランザクションと連携する方法に関する完全な情報については、セクション14.2.2「InnoDB のトランザクションモデルおよびロック」を参照してください。特に、InnoDB
のレコードレベルのロック、およびそれを使用してさまざまな種類のステートメントが実行される方法の詳細は、セクション14.2.6「InnoDB のレコード、ギャップ、およびネクストキーロック」およびセクション14.2.8「InnoDB のさまざまな SQL ステートメントで設定されたロック」を参照してください。
次のリストは、MySQL が各種のトランザクションレベルをどのようにサポートするかについて説明しています。このリストは、もっとも一般的に使用されるレベルから使用頻度の低い順に並べられています。
これが
InnoDB
のデフォルトの分離レベルです。一貫性読み取りでは、READ COMMITTED
分離レベルとの重要な違いがあります。同じトランザクション内の一貫性読み取りはすべて、最初の読み取りによって確立されたスナップショットを読み取ります。この規則は、同じトランザクション内で複数のプレーン (非ロック)SELECT
ステートメントを発行した場合、これらのSELECT
ステートメントは互いに関しても一貫性があることを示します。セクション14.2.4「一貫性非ロック読み取り」を参照してください。ロック読み取り(
FOR UPDATE
またはLOCK IN SHARE MODE
を含むSELECT
)、UPDATE
、およびDELETE
ステートメントの場合、ロックは、そのステートメントが一意のインデックスを一意の検索条件または範囲タイプの検索条件のどちらで使用しているかによって異なります。一意の検索条件を使用した一意のインデックスの場合、InnoDB
は見つかったインデックスレコードのみをロックし、その前にあるギャップはロックしません。その他の検索条件の場合、InnoDB
は、ギャップロックまたはネクストキーロックを使用して、範囲に含まれるギャップへのほかのセッションによる挿入をブロックすることによって、スキャンされたインデックス範囲をロックします。一貫性 (非ロック) 読み取りに関して、いくぶん Oracle に似た分離レベルです。各一貫性読み取りが (同じトランザクション内であっても)、独自の新しいスナップショットを設定して読み取ります。セクション14.2.4「一貫性非ロック読み取り」を参照してください。
ロック読み取り(
FOR UPDATE
またはLOCK IN SHARE MODE
を含むSELECT
)、UPDATE
ステートメント、およびDELETE
ステートメントの場合、InnoDB
はインデックスレコードのみをロックし、その前にあるギャップはロックしないため,ロックされたレコードの横への新しいレコードの自由な挿入が許可されます。注記MySQL 5.6 では、
READ COMMITTED
分離レベルが使用されている場合、または非推奨のinnodb_locks_unsafe_for_binlog
システム変数が有効になっている場合、外部キー制約チェックと重複キーチェックを除き、InnoDB
のギャップロックは存在しません。また、一致しない行に対するレコードロックも、MySQL がWHERE
条件を評価したあとに解放されます。READ COMMITTED
を使用するか、またはinnodb_locks_unsafe_for_binlog
を有効にする場合は、行ベースのバイナリロギングを使用する必要があります。SELECT
ステートメントは非ロックの方法で実行されますが、以前のバージョンの行が使用される可能性もあります。そのため、この分離レベルを使用すると、このような読み取りには一貫性がありません。これは、ダーティー読み取りとも呼ばれます。そうでなければ、この分離レベルはREAD COMMITTED
のように機能します。このレベルは
REPEATABLE READ
に似ていますが、自動コミットが無効になっている場合、InnoDB
はすべてのプレーンSELECT
ステートメントをSELECT ... LOCK IN SHARE MODE
に暗黙的に変換します。自動コミットが有効になっている場合、SELECT
は独自のトランザクションです。したがって、読み取り専用であることがわかっているため、一貫性のある (非ロック) 読み取りとして実行された場合は直列化することができ、ほかのトランザクションのためのブロックは必要ありません。(選択された行がほかのトランザクションによって変更された場合、プレーンSELECT
で強制的にブロックするには、自動コミットを無効にします。)
トランザクションアクセスモード
MySQL 5.6.5 の時点では、トランザクションアクセスモードはSET TRANSACTION
で指定できます。デフォルトでは、トランザクションは読み取り/書き込みモードで実行され、そのトランザクションで使用されるテーブルに対して読み取りと書き込みの両方が許可されます。このモードは、READ WRITE
のアクセスモードを使用して明示的に指定できます。
トランザクションアクセスモードがREAD ONLY
に設定されている場合は、テーブルへの変更が禁止されます。これにより、書き込みが許可されていない場合に可能になる、ストレージエンジンのパフォーマンス向上が実現される可能性があります。
同じステートメント内でREAD WRITE
とREAD ONLY
の両方を指定することは許可されません。
読み取り専用モードでは、DML ステートメントを使用してTEMPORARY
キーワードで作成されたテーブルは引き続き変更できます。永続的なテーブルと同様に、DDL ステートメントによって行われる変更は許可されません。
READ WRITE
およびREAD ONLY
アクセスモードは、START TRANSACTION
ステートメントを使用して個々のトランザクションに対しても指定できます。