MySQLにおけるトランザクション分離レベルの設定は、データベースの整合性と同時実行性能のバランスを調整するうえで重要な管理作業です。
MySQLのInnoDBストレージエンジンはREPEATABLE READをデフォルトの分離レベルとして採用しており、MVCCとネクストキーロックによってファントムリードも防止するという特徴的な実装を持っています。
本記事では、トランザクション分離レベルのMySQLでの設定方法、確認と変更手順、isolation level・SET TRANSACTION・phantom read・dirty read・InnoDB・同時実行制御などについてわかりやすく解説していきます。
MySQLの管理・運用・チューニングを担当している方や、データベースの設定を詳しく理解したい開発者の方に役立つ実践的な内容をお届けします。
MySQLの分離レベルはSET TRANSACTIONコマンドとシステム変数で設定する
それではまず、MySQLでのトランザクション分離レベルの確認方法と設定方法について解説していきます。
MySQLの分離レベル設定には「現在のセッションの分離レベルを変更する方法」「グローバル(サーバー全体)の分離レベルを変更する方法」「次のトランザクションのみの分離レベルを変更する方法」という3つのスコープがあります。
現在の分離レベルの確認方法
現在設定されているトランザクション分離レベルを確認するコマンドは以下の通りです。
MySQL 8.0以降での確認:
SELECT @@transaction_isolation;
— または
SELECT @@global.transaction_isolation; — グローバル設定の確認
SELECT @@session.transaction_isolation; — セッション設定の確認
MySQL 5.7以前での確認:
SELECT @@tx_isolation;
SHOW VARIABLES LIKE ‘transaction_isolation’;
出力結果は「REPEATABLE-READ」「READ-COMMITTED」「READ-UNCOMMITTED」「SERIALIZABLE」のいずれかが表示されます。
セッションレベルでの変更
現在の接続(セッション)に対してのみ分離レベルを変更する方法です。
他のセッションには影響を与えず、セッションが終了すると設定はリセットされます。
セッションレベルの変更:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
— または省略形
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
次のトランザクションのみに適用(現在のトランザクション外で実行):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN; — この次のトランザクションのみSERIALIZABLEで実行される
グローバルレベルでの変更
サーバー全体のデフォルト分離レベルを変更する方法です。
既存の接続には影響せず、新しく接続するセッションから適用されます。
SUPER権限またはSYSTEM_VARIABLES_ADMIN権限が必要です。
グローバルレベルの変更(要SUPER権限):
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
— または
SET @@global.transaction_isolation = ‘READ-COMMITTED’;
my.cnfでの永続的な設定変更
サーバー再起動後も設定を維持するにはmy.cnf(またはmy.ini)設定ファイルを編集します。
/etc/mysql/my.cnf(またはmy.iniファイル)の[mysqld]セクションに追記:
[mysqld]
transaction-isolation = READ-COMMITTED
設定後、MySQLサービスを再起動して反映させます:
sudo systemctl restart mysql
本番環境でグローバルの分離レベルを変更する際は、既存のアプリケーションの動作に影響がないか事前に十分に検証することが必須です。特にREPEATABLE READからREAD COMMITTEDへの変更は、ファントムリードへの耐性が失われる可能性があります。
MySQLのInnoDBにおける各分離レベルの動作特性
続いては、MySQLのInnoDBエンジンにおける各分離レベルの具体的な動作と実装の詳細を確認していきます。
InnoDBはMVCCとネクストキーロックを組み合わせた独自の実装によって、標準SQL仕様を超えたレベルの分離性を提供しています。
InnoDBのREPEATABLE READの特徴
MySQLのデフォルト分離レベルであるREPEATABLE READは、InnoDBの実装においてSQL標準の仕様を超えた特性を持っています。
通常のSELECT文(スナップショットリード)はトランザクション開始時のMVCCスナップショットを使うため、他のトランザクションのINSERT/DELETE後もカウントが変わらない(ファントムリードが防止される)という特性があります。
一方、FOR UPDATE・LOCK IN SHARE MODEを付けたロックリード(カレントリード)はMVCCを使わず現在の最新データを読むため、別のロックリードと組み合わせるとファントムリードが発生する場合があります。
InnoDBのネクストキーロック
ネクストキーロック(Next-Key Lock)はInnoDBがREPEATABLE READでSERIALIZABLEと同等のファントムリード防止を実現するための仕組みです。
レコードロック(行ロック)とギャップロック(インデックスの間の範囲に対するロック)を組み合わせたもので、検索条件に一致する既存レコードだけでなく、そのレコードの前後の「ギャップ(間隔)」もロックすることで、新規行の挿入を防ぎます。
ただしネクストキーロックはデッドロックの原因にもなりやすいため、READ COMMITTEDに変更してギャップロックを無効化することでデッドロックを回避するチューニングが行われることもあります。
分離レベルとバイナリログ形式の関係
MySQLでレプリケーションを使用している場合、分離レベルとバイナリログ形式の組み合わせに注意が必要です。
READ COMMITTEDをステートメントベース(STATEMENT)バイナリログと組み合わせると、レプリケーション先でのデータ不整合が発生する可能性があります。
そのためREAD COMMITTEDを使用する場合は、バイナリログ形式をROW(行ベース)またはMIXED(混在)に設定することが推奨されます。
バイナリログ形式の確認と変更:
SHOW VARIABLES LIKE ‘binlog_format’;
SET GLOBAL binlog_format = ‘ROW’;
分離レベル変更による性能改善のユースケース
続いては、MySQLの分離レベルを変更することで性能改善が期待できる具体的なユースケースを確認していきます。
READ COMMITTEDへの変更でデッドロックを低減
REPEATABLE READでネクストキーロックによるデッドロックが頻発している場合、READ COMMITTEDに変更することでギャップロックが無効化されデッドロックが大幅に減少することがあります。
これはECサイトの在庫更新処理や高頻度のINSERT/UPDATEが発生するシステムで特に効果的なチューニングです。
ただしREAD COMMITTEDに変更する場合は、アプリケーションがノンリピータブルリードやファントムリードを許容できる設計になっているかを事前に確認する必要があります。
特定の処理だけ分離レベルを変更するパターン
グローバル設定を変えずに、特定の重要な処理だけSERIALIZABLEで実行するパターンも有効です。
特定トランザクションのみSERIALIZABLEで実行:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
— 絶対的な整合性が必要な決済処理など
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance – 10000 WHERE id = 1;
COMMIT;
「全体はREAD COMMITTEDで高性能を維持しながら、重要な決済処理だけSERIALIZABLEで確実な整合性を保証する」という使い分けは、パフォーマンスと安全性を両立する実践的な設計パターンです。
まとめ
本記事では、トランザクション分離レベルのMySQLでの設定方法、確認と変更手順、isolation level・SET TRANSACTION・phantom read・dirty read・InnoDB・同時実行制御などについて解説しました。
MySQLではSET SESSION/GLOBAL TRANSACTION ISOLATION LEVELコマンドで分離レベルをリアルタイムに変更でき、my.cnfで永続設定も可能です。
InnoDBのREPEATABLE READはMVCCとネクストキーロックによってファントムリードも防止する強力な実装ですが、デッドロックへの注意が必要です。
レプリケーション環境ではバイナリログ形式との整合性確認も含め、分離レベルの変更は十分な検証と影響評価のもとで行うことが重要でしょう。