2017年5月26日金曜日

MySQLのSELECT .. FOR UPDATEはREPEATABLE-READでも直近にコミットされたレコードを返す

TL;DR


ドキュメント探してみたけどほんのちょっとだけしか書いてないような気がする。
SELECT … LOCK IN SHARE MODE は、 これらの行のいずれかがコミットされていない別のトランザクションによって変更された場合、クエリーはそのトランザクションが終了するまで待機してから、最新の値を使用します。
しゃらっと 最新の値を使用します と書いてあるけど、最新の値が意味するのは「最後にコミットされた時の値」であって、REPEATABLE-READのはずの分離レベル内でREAD-COMMITTEDっぽい動作が見える。
どういうことかというと
mysql57 4> START TRANSACTION;
mysql57 5> START TRANSACTION;

mysql57 4> SELECT * FROM t1;
+-----+--------+
| num | val    |
+-----+--------+
|   1 | before |
+-----+--------+
1 row in set (0.00 sec)

mysql57 5> SELECT * FROM t1;
+-----+--------+
| num | val    |
+-----+--------+
|   1 | before |
+-----+--------+
1 row in set (0.00 sec)

mysql57 4> UPDATE t1 SET val = 'after' WHERE num = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql57 4> COMMIT AND CHAIN;
Query OK, 0 rows affected (0.00 sec)

mysql57 4> SELECT * FROM t1;
+-----+-------+
| num | val   |
+-----+-------+
|   1 | after |
+-----+-------+
1 row in set (0.00 sec)
ほぼ同時に開始したトランザクション45がいて、4はある行の値をアップデートしてコミットした。 この時に”after”が見えるのがREAD-COMMITTED、”before”が見えるのがREPEATABLE-READのはずで確かにそうなるんだけど、ブロッキングリード(SELECT .. FOR UPDATE, SELECT .. LOCK IN SHARE MODE)の場合は
mysql57 5> SELECT * FROM t1 FOR UPDATE;
+-----+-------+
| num | val   |
+-----+-------+
|   1 | after |
+-----+-------+
1 row in set (0.00 sec)
コミット済みの値が見える。 同じトランザクションの中で非ブロッキングリードとブロッキングリードをすると
mysql57 5> SELECT * FROM t1;
+-----+--------+
| num | val    |
+-----+--------+
|   1 | before |
+-----+--------+
1 row in set (0.00 sec)

mysql57 5> SELECT * FROM t1 FOR UPDATE;
+-----+-------+
| num | val   |
+-----+-------+
|   1 | after |
+-----+-------+
1 row in set (0.00 sec)

mysql57 5> SELECT * FROM t1;
+-----+--------+
| num | val    |
+-----+--------+
|   1 | before |
+-----+--------+
1 row in set (0.00 sec)
返ってくる値が変わる。
この話自体は有名な気がしていたんだけれど、ドキュメントには小さくしか見つけられなかったのでひょっとしたら有名じゃないのかなって。 (これ実演してみせたら爆笑されたw)

2017年5月22日月曜日

MySQLユーザ会会 in 長野 2017に参加してきましたよ

MySQLユーザ会会 in 長野 2017に逝ってきました!
開催の経緯とかはとみたさんのブログ MySQLユーザ会会 in 長野 を開催しました - @tmtms のメモ 、当日のふいんき(何故か変換できない)はTogetter MySQLユーザ会会 in 長野 2017 - Togetterまとめ がまとまってます。
セッションの内容は坂井さんMySQLとはみたいなことやると聞いていたし、かじやまさんは「MySQL 8.0」だって聞いてたし、bizstationさんTransactd PHP ORMと聞いていたので(というか、それが聞きたいと頼んだのはわたしだ)
( ´-`).oO(この豪勢なメンツに対抗して自分の色が出せそうなセッション…? 運用ネタ…?
とか考えたんですが、結局
いつもどおり「MySQLを楽しんでいるおじさんっぷり」を話すことにしました。






背景の舞奈たんがさかさまになっているのが謎。手元のPDFファイル(や、SlideshareからダウンロードしたPDF)では天地正しいんですけれども。
最近のお気に入りのGTID、本当はmysqlslavetrxの話も入れたかったし8.0のSET @@GLOBAL.GTID_PURGED = '+gtid_set'も入れたかったなあと思い出してみたり、PMMのデモ(というか本番だけど)を見せられたのは良かったなあと思ったりしました。
yoku0825は絶賛楽しそうなことを探していますので、他に楽しそうなものがあったら教えてください :)

(交通費は自腹でしたが)登壇枠くれたとみたさん、会場提供のケイケンシステムさんありがとうございました!