AUTO_INCREMENT の上限まであとどれくらいかを調べる SQL
Posted on
MySQL の AUTO_INCREMENT
属性を使っている場合、整数型の上限に達しないか注意する必要があります。たとえば INT 型だと約 21 億 4700 万、unsigned が指定されていると倍の約 42 億 9400 万が上限です。
上限に達する前により大きな型にマイグレーションしなければなりませんが、そのためには上限まであとどれくらいかを調べる必要があります。各テーブルで LAST_INSERT_ID()
を叩けば最後に生成された AUTO_INCREMENT
の値を取得できますが、すべてのテーブルを網羅的に調べる必要があるので information_schema
から SQL で割り出してみました。
たとえば INT 型のカラムを対象に何パーセント使用しているかを調査する SQL です。 unsigned が指定されていると上限が倍になるので column_type
を見て分母を変えています。
SELECT
c.table_name,
c.column_type,
t.auto_increment,
IF(
LOCATE('unsigned', c.column_type) = 0,
(t.auto_increment / 2147483647) * 100,
(t.auto_increment / 4294967295) * 100
) as use_rate
FROM
information_schema.tables AS t
INNER JOIN
information_schema.columns AS c
ON
t.table_name = c.table_name
WHERE
t.auto_increment IS NOT NULL
AND
c.extra = 'auto_increment'
AND
c.data_type = 'int'
ORDER BY
use_rate DESC
;
実際に使うときは閾値を超えたテーブルだけ知りたいので HAVING
句で絞って Slack に通知しています。
参考までに information_schema
のテーブルはこんなスキーマになっています。
mysql> DESC information_schema.tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512) | NO | | | |
| TABLE_SCHEMA | varchar(64) | NO | | | |
| TABLE_NAME | varchar(64) | NO | | | |
| TABLE_TYPE | varchar(64) | NO | | | |
| ENGINE | varchar(64) | YES | | NULL | |
| VERSION | bigint(21) unsigned | YES | | NULL | |
| ROW_FORMAT | varchar(10) | YES | | NULL | |
| TABLE_ROWS | bigint(21) unsigned | YES | | NULL | |
| AVG_ROW_LENGTH | bigint(21) unsigned | YES | | NULL | |
| DATA_LENGTH | bigint(21) unsigned | YES | | NULL | |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES | | NULL | |
| INDEX_LENGTH | bigint(21) unsigned | YES | | NULL | |
| DATA_FREE | bigint(21) unsigned | YES | | NULL | |
| AUTO_INCREMENT | bigint(21) unsigned | YES | | NULL | |
| CREATE_TIME | datetime | YES | | NULL | |
| UPDATE_TIME | datetime | YES | | NULL | |
| CHECK_TIME | datetime | YES | | NULL | |
| TABLE_COLLATION | varchar(32) | YES | | NULL | |
| CHECKSUM | bigint(21) unsigned | YES | | NULL | |
| CREATE_OPTIONS | varchar(255) | YES | | NULL | |
| TABLE_COMMENT | varchar(2048) | NO | | | |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)
mysql> DESC information_schema.columns;
+--------------------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512) | NO | | | |
| TABLE_SCHEMA | varchar(64) | NO | | | |
| TABLE_NAME | varchar(64) | NO | | | |
| COLUMN_NAME | varchar(64) | NO | | | |
| ORDINAL_POSITION | bigint(21) unsigned | NO | | 0 | |
| COLUMN_DEFAULT | longtext | YES | | NULL | |
| IS_NULLABLE | varchar(3) | NO | | | |
| DATA_TYPE | varchar(64) | NO | | | |
| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES | | NULL | |
| CHARACTER_OCTET_LENGTH | bigint(21) unsigned | YES | | NULL | |
| NUMERIC_PRECISION | bigint(21) unsigned | YES | | NULL | |
| NUMERIC_SCALE | bigint(21) unsigned | YES | | NULL | |
| DATETIME_PRECISION | bigint(21) unsigned | YES | | NULL | |
| CHARACTER_SET_NAME | varchar(32) | YES | | NULL | |
| COLLATION_NAME | varchar(32) | YES | | NULL | |
| COLUMN_TYPE | longtext | NO | | NULL | |
| COLUMN_KEY | varchar(3) | NO | | | |
| EXTRA | varchar(30) | NO | | | |
| PRIVILEGES | varchar(80) | NO | | | |
| COLUMN_COMMENT | varchar(1024) | NO | | | |
+--------------------------+---------------------+------+-----+---------+-------+
20 rows in set (0.01 sec)
まとめ
サービスが急成長していると INT 型の上限は射程に入ってきます。上限に達して障害を起こさないようにちゃんと監視する必要がありますね。