ちなみにMySQLのバージョンは5.1.73
どんな現象にハマったのか
トランザクション内でinsertしたレコードは、ありえない条件でselect出来ちゃうケースがある。
insertした直後に「auto_incrementカラム is null」という条件で一度だけselect出来てしまう
。。。。
すみません。うまく説明出来ないので実際の現象を紹介します。
たとえばこんなテーブルがあるとします。
mysql> desc users;
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| created | datetime | NO | | NULL | |
+-----------------+---------------------+------+-----+---------+----------------+
プライマリキーだしauto_incrementだしNullも許可されていないので、以下のようなselect文を実行しても何も取れません。取れるわけないっす。
mysql> select * from users where id is null;
Empty set (0.00 sec)
しかしトランザクション内でinsertした直後だとどうでしょう。
(すみません。トランザクション内じゃなくても発生しました。)
mysql> begin; #トランザクション開始(しなくても発生しました)
mysql> insert into users (`name`, `created`) values ('Kei Sasakure', now()); #レコード追加
mysql> select * from users where id is null;
+--------+--------------+---------------------+
| id | name | created |
+--------+--------------+------+-----+--------+
| 3390 | Kei Sasakure | 2016-02-25 16:18:03 |
+--------+--------------+------+-----+--------+
1 row in set (0.00 sec)
mysql> select * from users where id is null; #2度目は取れない
Empty set (0.00 sec)
むむむ! これはキモい! いくら commit していないとはいえ id あるのに、、
なぜ一度だけ取得出来てしまうのか
僕には理解が及びませんでした。
(コメント頂いた情報によると、どうやら仕様でした)
気付いた背景
Model系クラスのユニットテストで、トランザクション使って実行中だけテストデータ作るみたいな事すると思うんですけど
その中で「引数(id)がnullならデータ返さない事」という期待値のテストケースを書いたら、何故か取得出来ちゃうもんで気付きました。
解決方法
MySQLのバージョンをとりあえず5.5系に上げたら発生しなくなったっす。
@ngyuki さんのコメントを参照してください。バージョン上げる必要ありませんでした。