Hatena::ブログ(Diary)

SH2の日記 RSSフィード

2014-09-14 MySQLのロックについて このエントリーを含むブックマーク

JPOUG> SET EVENTS 20140907 | Japan Oracle User Group (JPOUG)に参加して発表をしてきました。IIJさまのセミナルームは窓からの眺めがすばらしいですね。JPOUGの運営メンバのみなさま、会場を提供してくださったIIJのみなさま、当日お越しいただいたみなさま、どうもありがとうございました。

私のセッションでは「MySQLのロックについて」と題してネクストキーロックなどの説明をしました。プレゼンテーション資料と、調査のために作成したツールを公開します。

プレゼンテーション資料からリンクしているウェブサイトの一覧です。

過去記事の訂正

@kamipoさんから言及がありましたが、私は2009年の記事でネクストキーロックという用語を誤って使用していました。

ところで、ネクストキーロックというとsh2さんのMySQL InnoDBのネクストキーロック おさらい - SH2の日記の記事が有名ですよね。この、ひとつ先のインデックスレコードまでロックするのもネクストキーロックと呼ぶし、レコードロックとその直前のギャップロックの組み合わせもネクストキーロックと書いてるし、議論するときにはどちらの意味で使ってるのか文脈読み取れる社会性が必要そうです(今回はレコードロックとその直前のギャップロックの組み合わせの意味で使います)。

  • 誤:一つ先のレコードまでロックを取得すること。
  • 正:レコードとその手前のギャップに対するロックのこと。

ご指摘ありがとうございました。

訂正前

1つめのセッションではc1 < 30の行だけロックをすればいいのですが、実際にはc1 = 30の行もロックされてしまっています。これはInnoDBアーキテクチャからもたらされている制限事項で、このロックのことをネクストキーロックといいます。ある範囲をロックする際に、一つ先の行までロックをかけることで「範囲」というものを表現する仕組みです。

訂正後

1つめのセッションではc1 < 30の行だけロックをすればいいのですが、実際にはc1 = 30の行もロックされてしまっています。これはInnoDBアーキテクチャからもたらされている制限事項です。InnoDBインデックス上で走査した行に対してロックをかけるアーキテクチャとなっており、このケースではc1 = 30の行まで走査しています。また、走査したそれぞれの行に対してネクストキーロックと呼ばれる特殊なロックをかけています。ネクストキーロックとは行とその手前のギャップに対するロックのことで、現時点で存在しない行に対してロックをかける現実的な仕組みです。InnoDBはこのような仕組みで「範囲」というものを表現し、ファントムリードを防いでいるのです。

MySQL Casual Talks vol.6の復習

今回の資料は、MySQL Casual Talks vol.6での@karupaneruraさんの発表にインスパイアされて作成しました。

じっくり復習すると、P20はセカンダリインデックスでcol1 = 8の手前に対するギャップロックが取得されていること、P21以降で(gap)は最初と最後だけではなく途中にも存在していること、などが分かるかと思います。

Lock Inspector

今回の資料を作るにあたって、簡単なツールを作成しました。以下のようなスクリプトを準備すると、

1:RC
2:RC
1:Q:SELECT * FROM emp WHERE empno = 7788 FOR UPDATE
2:Q:SELECT * FROM emp WHERE empno = 7788 FOR UPDATE
S:10
1:C
2:C

複数のワーカがコマンドを逐次発行してくれます。

Lock Inspector
1:READ_COMMITTED
2:READ_COMMITTED
1:QUERY:SELECT * FROM emp WHERE empno = 7788 FOR UPDATE
(empno      ename      job        mgr        hiredate   sal        comm       deptno     )
(7788       scott      analyst    7566       1987-04-19 3000.00    null       20         )
(1:QUERY)
2:QUERY:SELECT * FROM emp WHERE empno = 7788 FOR UPDATE
SLEEP:10
(2:QUERY)
(2:com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request)
2:ABORT
(SLEEP)
1:COMMIT
1:EXIT

GitHub上は、sandboxというあまりやる気のないリポジトリに入れてあります。

トランザクション処理 概念と技法

参考書籍です。洋書は購入可能です。

和書は中古で手に入れるしかないと思います。こちらは上下巻に分かれています。

トランザクション処理 上

トランザクション処理 上

トランザクション処理 下

トランザクション処理 下