09/05: MySQL > SELECT ... FOR UPDATE および SELECT ... LOCK IN SHARE MODE
Category: Web dev
Posted by: hajime osako
MySQL AB :: MySQL 4.1 リファレンスマニュアル :: 7.5.9.3 ロックを取得する読み取り
SELECT LOCK IN SHARE MODE and FOR UPDATE
テーブル型毎のロックの挙動
InnoDB型のREADロックとWRITEロックの取得は、MyISAM型のそれとは大きく異なります。MySQLのトランザクション処理はMVCC(Multi Version Concurrency Control: 多版型同時実行制御)を基に行われるので、WRITEロックとREADロックは競合しません。
データ操作(INSERT, UPDATE, DELETE)はデータ検索(SELECT)の実行をブロックしませんし、逆もまた然りです(補足 1)。特に、SELECT文の実行は一切ブロックされません。
次に、WRITEロック間の関係ですが、一意性(UNIQUE)制約もしくは主キー(PRIMARY KEY)制約を持つテーブルの場合は行レベルロック、それ以外のテーブルではテーブルロックが取得されます。
これはMySQLの実装方式に起因するもので、MySQL特有の挙動です。
SELECT FOR UPDATE文で排他的ロックを、SELECT LOCK IN SHARE MODE文で共有ロックを設定することができます。これらはトランザクションブロック内でのみ実行されます。
IN SHARE MODE と FOR UPDATE 読み取りによって設定されたロックは、トランザクションがコミットされたりロールバックされたりした時にリリースされます。
MySQL SELECT文
SELECT * FROM table_a USE INDEX (use_index_name);
SELECT * FROM table_a IGNORE INDEX (ignore_index_name);
SELECT col1, col2, col3 FROM table_a ORDER BY 1, 2;
SELECT STRAIGHT_JOIN * FROM T1,T2,T3;
SELECT HIGH_PRIORITY * FROM table_a;
SELECT SQL_BIG_RESULT * FROM table_a GROUP BY col1;
SELECT SQL_BUFFER_RESULT * FROM table_a;
SELECT SQL_SMALL_RESULT * FROM table_a GROUP BY col1;
SELECT SQL_CALC_FOUND_ROWS * FROM table_a LIMIT 100;
SELECT FOUND_ROWS();
SELECT * FROM table_a FOR UPDATE;
SELECT LOCK IN SHARE MODE and FOR UPDATE
テーブル型毎のロックの挙動
InnoDB型のREADロックとWRITEロックの取得は、MyISAM型のそれとは大きく異なります。MySQLのトランザクション処理はMVCC(Multi Version Concurrency Control: 多版型同時実行制御)を基に行われるので、WRITEロックとREADロックは競合しません。
データ操作(INSERT, UPDATE, DELETE)はデータ検索(SELECT)の実行をブロックしませんし、逆もまた然りです(補足 1)。特に、SELECT文の実行は一切ブロックされません。
次に、WRITEロック間の関係ですが、一意性(UNIQUE)制約もしくは主キー(PRIMARY KEY)制約を持つテーブルの場合は行レベルロック、それ以外のテーブルではテーブルロックが取得されます。
これはMySQLの実装方式に起因するもので、MySQL特有の挙動です。
SELECT FOR UPDATE文で排他的ロックを、SELECT LOCK IN SHARE MODE文で共有ロックを設定することができます。これらはトランザクションブロック内でのみ実行されます。
IN SHARE MODE と FOR UPDATE 読み取りによって設定されたロックは、トランザクションがコミットされたりロールバックされたりした時にリリースされます。
MySQL SELECT文
SELECT * FROM table_a USE INDEX (use_index_name);
SELECT * FROM table_a IGNORE INDEX (ignore_index_name);
SELECT col1, col2, col3 FROM table_a ORDER BY 1, 2;
SELECT STRAIGHT_JOIN * FROM T1,T2,T3;
SELECT HIGH_PRIORITY * FROM table_a;
SELECT SQL_BIG_RESULT * FROM table_a GROUP BY col1;
SELECT SQL_BUFFER_RESULT * FROM table_a;
SELECT SQL_SMALL_RESULT * FROM table_a GROUP BY col1;
SELECT SQL_CALC_FOUND_ROWS * FROM table_a LIMIT 100;
SELECT FOUND_ROWS();
SELECT * FROM table_a FOR UPDATE;