原因是:在使用on duplicate key update时,int unsigned 自增主键增长飞快,很快就达到了最大值。此时再执行sql时无法更新、插入。但sql执行是成功的,只是影响行数为0.
先复现问题:
create table at_test (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`vid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'vid',
`tag` text COMMENT 'tag',PRIMARY KEY (`id`),UNIQUE KEY `uniq_vid` (`vid`)
) ENGINE=InnoDB AUTO_INCREMENT=4294967295 DEFAULT CHARSET=utf8mb4 COMMENT='vid info表';
先创建一张表,自增int unsigned类型的id,自增设置为最大值4294967295。
此时执行SQL:
mysql> insert into at_test(vid,tag)values(1,'1111') on duplicate key update tag = values(tag);
Query OK, 1 row affected (0.00 sec)
此sql能正常被执行,但看increment不会自动增长了,因为已经增长到最大了。
mysql> show create table at_test\G
*************************** 1. row ***************************
Table: at_test
Create Table: CREATE TABLE `at_test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`vid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'vid',
`tag` text COMMENT 'tag',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_vid` (`vid`)
) ENGINE=InnoDB AUTO_INCREMENT=4294967295 DEFAULT CHARSET=utf8mb4 COMMENT='vid info表'
1 row in set (0.00 sec)
mysql> select * from at_test;
+------------+-----+------+
| id | vid | tag |
+------------+-----+------+
| 4294967295 | 1 | 1111 |
+------------+-----+------+
1 row in set (0.00 sec)
mysql> insert into at_test(vid,tag)values(1,'2222') on duplicate key update tag = values(tag);
Query OK, 2 rows affected (0.00 sec)
mysql> select * from at_test;
+------------+-----+------+
| id | vid | tag |
+------------+-----+------+
| 4294967295 | 1 | 2222 |
+------------+-----+------+
1 row in set (0.00 sec)
再插入一条新数据,SQL是执行成功的,能正常返回,但影响行数为0,表示数据是没有被写入的
mysql> insert into at_test(vid,tag)values(2,'2222') on duplicate key update tag = values(tag);
Query OK, 0 rows affected (0.00 sec)
mysql> select * from at_test;
+------------+-----+------+
| id | vid | tag |
+------------+-----+------+
| 4294967295 | 1 | 2222 |
+------------+-----+------+
1 row in set (0.00 sec)
如果不用on uplicate key update ,直接insert 是直接报主键冲突的。
mysql> insert into at_test(vid,tag)values(2,'2222');
ERROR 1062 (23000): Duplicate entry '4294967295' for key 'PRIMARY'
在使用on duplicate key update时需要注意如下有几个问题:
1、on duplicate key update会导致自增主键增长特别快,很容易达到最大限制(原因:update时也会导致自增增加)可参考:[AUTO_INCREMENT Handling in InnoDB](https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html)
2、on duplicate key update会导致不连续自增
3、on uplicate key update 在自增超了的情况下竟然没有报错,这是非常难受的,直接报失败不挺好?(https://bugs.mysql.com/bug.php?id=92813,提了个bug)。
4、on duplicate key update语句能够正确执行,依赖于对应的表结构上的唯一索引不发生变动。开发需要确保后续随着业务变更,不能影响到其依赖的唯一索引。
文章最后更新时间:
2018年10月17日 12:22:37