MySQL AUTO_INCREMENT
runs out of value
某天我们系统的一张表无法INSERT了,但是某些存在的数据一直在更新。我用tcpdump的确看到INSERT请求不断的发往MySQL,程序日志也没有记录INSERT错误。我当时就懵了,MySQL怕不是糊涂了吧!
1 SQL的失败情况
(webhook_alert_id, instance)
组成UNIQUE KEY。
INSERT...ON DUPLICATE KEY UPDATE
成功了,但是SELECT刚才写入的值,不存在INSERT
失败,程序没用这个语句,所以没发现错误
mysql> INSERT INTO alertItemList(webhook_alert_id, instance, status) VALUES (10098161, "10.135.48.67:789", "resolved") ON DUPLICATE KEY UPDATE status = values(status); Query OK, 2 rows affected (0.00 sec) mysql> SELECT * FROM alertItemList WHERE webhook_alert_id = 10098161; Empty set (0.00 sec) mysql> INSERT INTO alertItemList(webhook_alert_id, instance, status) VALUES (10098161, "10.135.48.67:789", "resolved"); ERROR 1062 (23000): Duplicate entry '4294967295' for key 'PRIMARY'
2 失败原因
4294967295
看到这个数字,失败原因就知道七七八八了, 肯定是整数溢出了。查看表结构, `id` int(10) unsigned NOT NULL AUTO_INCREMENT
果然如此。
2.1 为什么INSERT报错是 Duplicate entry
翻看 MySQL文档 有这么一句:
When an
AUTO_INCREMENT
integer column runs out of values, a subsequent INSERT operation returns a duplicate-key error. This is general MySQL behavior.
把错误类型归结为1062,让 INSERT...ON DUPLICATE KEY UPDATE
变得危险起来
2.2 AUTO_INCREMENT
变的危险起来
如上, INSERT...ON DUPLICATE KEY UPDATE
成功了,因为 PRIMARY KEY
duplicate了,所以不是INSERT了,而是总是在UPDATE最后一行,这解释了为啥SELECT不出来。 使用 INSERT...ON DUPLICATE KEY UPDATE
的本意是unique key duplicate时更新,绝对不是 AUTO_INCREMENT
out of values导致duplicate时更新。
就这样,真正的INSERT丢失了,而最后一行的数据一直被意外的更新。
3 如何避免
- 如果不确定,
AUTO_INCREMENT
使用 BIGINT - 监控
AUTO_INCREMENT
的位置,SELECT id FROM t ORDER BY id DESC LIMIT 1