SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
このステートメントは、現在のセッションまたは次のトランザクションに対して、トランザクション遮断レベルをグローバルに設定します。
GLOBAL
キーワードが指定された場合、このステートメントは、以降のすべてのセッションに対するデフォルトトランザクションレベルをグローバルに設定します。既存のセッションには影響はありません。
SESSION
キーワードが指定された場合、このステートメントは、現在のセッション内で実行される以降のすべてのトランザクションに対するデフォルトトランザクションレベルを設定します。
SESSION
または
GLOBAL
キーワードが指定されない場合、このステートメントは、現在のセッション内で実行される次の
(開始されていない)
トランザクションの遮断レベルを設定します。
グローバルなデフォルト遮断レベルを変更するには、SUPER
権限が必要です。どのセッションも、そのセッションの遮断レベル
(トランザクションの途中であっても)、または次のトランザクションの遮断レベルを自由に変更できます。
サーバーの起動時にグローバルなデフォルト遮断レベルを設定するには、コマンドラインまたはオプションファイルで
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;
InnoDB
は、ここで説明する各トランザクション遮断レベルを、異なるロック方式を使用してサポートします。デフォルトレベルは
REPEATABLE
READ
です。InnoDB
のレコードレベルのロックや、それらのロックを使用してさまざまな型のステートメントを実行する方法の詳細については、項9.8.4. 「InnoDB
レコード、ギャップ、およびネクストキーロック」
および 項9.8.6. 「InnoDB
内で各種 SQL
ステートメントによって設定されるロック」
を参照してください。
次のリストは、MySQL による各種のトランザクションレベルのサポート方法を示しています。
SELECT
ステートメントは非ロックの方法で実行されますが、以前のバージョンの行が使用される可能性もあります。従って、この遮断レベルを利用したこのような読み込みは一貫性がありません。また、これは「ダーティー読み取り」とも呼ばれます。そうでない場合、この遮断レベルは
READ
COMMITTED
のように機能します。
一貫性のある (非ロック) 読み取りに関して、ある程度 Oracle に似た遮断レベル。一貫性のある読み取りはそれぞれ (同じトランザクション内であっても)、独自のフレッシュスナップショットを設定したり、読み取ったりします。項9.8.2. 「一貫性非ロック読み取り」 を参照してください。
ロック読み取り (FOR
UPDATE
または LOCK IN
SHARE MODE
を指定した
SELECT
)
の場合、InnoDB
はインデックスレコードのみをロックし、各インデックスレコードの前にあるギャップはロックしないため、ロックされたレコードの横に新しいレコードを自由に挿入できます。UPDATE
および
DELETE
ステートメントの場合、ロックはステートメントが、一意の検索条件
(たとえば、WHERE id =
100
) または範囲タイプの検索条件
(たとえば、WHERE id >
100
)
のどちらを含む一意のインデックスを使用しているかによって異なります。一意の検索条件を含む一意のインデックスの場合、InnoDB
は検索されたインデックスレコードのみをロックし、その前にあるギャップはロックしません。範囲タイプの検索の場合、InnoDB
は、範囲に含まれているギャップへのほかのセッションによる挿入をブロックするためのギャップロックまたはネクストキー
(ギャップ + インデックスレコード)
ロックを使用して、スキャンされたインデックス範囲をロックします。これは、「phantom
rows」 が MySQL
レプリケーションと復旧が機能するためにブロックされなければいけないため必要になります。
MySQL 5.1
では、READ
COMMITTED
遮断レベルが使用されているか、または
innodb_locks_unsafe_for_binlog
システム変数が有効になっている場合、外部キー制約の確認と重複キーの確認を除き、InnoDB
のギャップロックは存在しません。また、一致しない行に対するレコードロックも、MySQL
が WHERE
条件を評価したあとに解放されます。
MySQL 5.1
の時点では、READ
COMMITTED
を使用するか、または
innodb_locks_unsafe_for_binlog
を有効にする場合は、行ベースのバイナリログを使用する必要があります。
これが InnoDB
のデフォルト遮断レベルです。一貫性のある読み取りの場合、READ
COMMITTED
遮断レベルとは重要な違いがあります。同じトランザクション内の一貫性のある読み取りはすべて、最初の読み取りで確立されたスナップショットを読み取ります。この規則は、同じトランザクション内で複数のプレーン
(非ロック)
SELECT
ステートメントを発行した場合、これらの
SELECT
ステートメントは互いに関しても一貫性があることを示します。項9.8.2. 「一貫性非ロック読み取り」
を参照してください。
ロック読み取り (FOR
UPDATE
または LOCK IN
SHARE MODE
を指定した
SELECT
)、UPDATE
、および
DELETE
ステートメントの場合、ロックはステートメントが、一意の検索条件または範囲タイプの検索条件のどちらを含む一意のインデックスを使用しているかによって異なります。一意の検索条件を含む一意のインデックスの場合、InnoDB
は検索されたインデックスレコードのみをロックし、その前にあるギャップはロックしません。その他の検索条件の場合、InnoDB
は、範囲に含まれているギャップへのほかのセッションによる挿入をブロックするためのギャップロックまたはネクストキー
(ギャップ + インデックスレコード)
ロックを使用して、スキャンされたインデックス範囲をロックします。
このレベルは
REPEATABLE
READ
に似ていますが、自動コミットが無効になっている場合、InnoDB
はすべてのプレーン
SELECT
ステートメントを
SELECT
... LOCK IN SHARE MODE
に暗黙的に変換します。自動コミットが有効になっている場合、SELECT
は独自のトランザクションです。したがって、読み取り専用であることがわかっているため、一貫性のある
(非ロック)
読み取りとして実行された場合は直列化することができ、ほかのトランザクションのためのブロックは必要ありません。(つまり、選択された行がほかのトランザクションによって変更された場合にプレーン
SELECT
で強制的にブロックするには、自動コミットを無効にする必要があります。)