読者です 読者をやめる 読者になる 読者になる

LAST_INSERT_IDの限界

こんにちは。

突然ですが32bit/64bitの差を調べていて気づいたのでメモ。
32bitだともちろん32bitを超える数値をそのままでは扱えないわけですが、MySQL的にはどうなのよってことで特に値が大きくなりがちなid発番を見てみました。

弊社ではid発番をauto_incrementではなく、MyISAMなテーブルに対する以下クエリで発番しています。

CREATE TABLE `hoge` (
  `id` bigint(20) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=sjis
update hoge set id=LAST_INSERT_ID(id+1)

で、unsignedなんだから「18446744073709551615」までイケるだろ!
と思ったら

mysql> select * from hoge;
+---------------------+
| id                  |
+---------------------+
| 9223372036854775807 |
+---------------------+
1 row in set (0.00 sec)

mysql> update hoge set id=LAST_INSERT_ID(id+1);
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

mysql> select LAST_INSERT_ID();
+----------------------+
| LAST_INSERT_ID()     |
+----------------------+
| -9223372036854775808 |
+----------------------+
1 row in set (0.00 sec)

mysql> select * from hoge;
+----+
| id |
+----+
|  0 |
+----+
1 row in set (0.00 sec)

工エエェェ(´д`)ェェエエ工

反転した。

ん、Warning出とる。

Rows matched: 1  Changed: 1  Warnings: 1
mysql> show warnings;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'id' at row 1 |
+---------+------+---------------------------------------------+
1 row in set (0.00 sec)

あら。。。
これはなんとまぁ、仕様なんですね。

MySQL Bugs: #20964: last_insert(id) does not support bigint unsigned

900京を超えるようなidを発番する機会なんてそうそうないでしょうが、そうなった時はロジックを変えないといけないのかな。

decimalにしてもダメでした。
これがLAST_INSERT_IDの限界か!

ちなみにLAST_INSERT_IDについてこちらの記事が大変わかりやすかったです!

LAST_INSERT_IDを使って採番テーブルを扱う - (゚∀゚)o彡 sasata299's blog