美文网首页databases
当自增遇到零

当自增遇到零

作者: 沐一同学 | 来源:发表于2020-05-25 10:21 被阅读0次

今天排查一个问题,迁移工具(公司内部同步工具),迁移的数据少一条,好奇怪,由于迁移表依据primary key切分任务
大概率会是收尾处数据丢失。

假设有表tb1,其定义如下:
CREATE TABLE tb1 (
id int(11) NOT NULL AUTO_INCREMENT,
c1 int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

源:
mysql> select min(id),max(id) from tbl;
+---------+---------+
| min(id) | max(id) |
+---------+---------+
| 0 | 157087 |
+---------+---------+
1 row in set

目标:
mysql> select min(id),max(id) from t_hash;
+---------+---------+
| min(id) | max(id) |
+---------+---------+
| 1 | 157083 |
+---------+---------+
1 row in set

通过添加日志,调试迁移工具;

  1. 任务切分没有问题,包含id为0行记录;
  2. pull数据的操作没有问题,拉取数据包含id为0行记录;
  3. push数据的操作,也没有问题,操作中也是包含id为0行的记录;

突然想起来前几天,关于自增列的问题,如果insert的自增列值为0,会变成1;

验证:
肯定是没问题的:
insert into tb1 VALUES(1,1);
insert into tb1(id,c1)VALUES(2,2);

负值的自增值也没有问题:
INSERT INTO tb1(id,c1)VALUES(-1,-1);

那插入0呢?

INSERT INTO tb1(id,c1)VALUES(0,0);
虽然显示插入自增值为0,但是自增值变成了1,这是啥意思呢?

查看了下MySQL帮助文档,发现该问题和一个变量有关:NO_AUTO_VALUE_ON_ZERO,一般情况下,在插入记录时,如果自增列对于的数据为NULL或0时,系统会获取一个新的自增值来作为本次插入的自增值使用,如果希望将0作为自增值来使用,那些需要设置SQL MODE 为NO_AUTO_VALUE_ON_ZERO,如:

SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO';

官方文档如下:

NO_AUTO_VALUE_ON_ZERO affects handling of AUTO_INCREMENT columns. Normally, you generate the next sequence number for the column by inserting either NULL or 0 into it. NO_AUTO_VALUE_ON_ZERO suppresses this behavior for 0 so that only NULL generates the next sequence number.
This mode can be useful if 0 has been stored in a table's AUTO_INCREMENT column. (Storing 0 is not a recommended practice, by the way.) For example, if you dump the table with mysqldump and then reload it, MySQL normally generates new sequence numbers when
it encounters the 0 values, resulting in a table with contents different from the one that was dumped. Enabling NO_AUTO_VALUE_ON_ZERO before reloading the dump file solves this problem. mysqldump now automatically includes in its output a statement that enables NO_AUTO_VALUE_ON_ZERO, to avoid this problem.

=======================================================================

尽管可以通过NO_AUTO_VALUE_ON_ZERO来将自增值设置为0,但不建议将自增值设置为0,以避免在数据迁移或同步时因环境设置不同而导致数据差异,如从库未设置NO_AUTO_VALUE_ON_ZERO的情况下通过mysqldump导入初始化数据,便会导致数据不一直或初始化失败。

=======================================================================

相关文章

  • 当自增遇到零

    今天排查一个问题,迁移工具(公司内部同步工具),迁移的数据少一条,好奇怪,由于迁移表依据primary key切分...

  • SQLite使用合集

    清空SQLite表后,如何使表的自增ID值也归零问题描述:sqlite3在清空table后,如果table中有自增...

  • 字符串最高字段加一

    当使用char作为主键,无法实现自增的时候

  • 2019-02-24

    算术运算符 主要介绍一下 %(取模)、自增(++)、自减(--) 自增 (++) 自增分为自增前(++a) 和自增...

  • JavaScript中的自增与自减

    自增: 通过自增运算符可以使变量在自身的基础上加一; 自增符号:++ 自增分为: 前自增(++a); 后自增(a+...

  • java数组的自增

    数组的自增 数组的增长是元素个数的增长,元数据不能破坏 自增是当数组添加元素的时候自动调用

  • MySQL的自增主键用完了会发生什么?

    首先MySQL的自增主键ID是有限制的,它的最大值是231-1=4294967295。 当自增主键达到最大,再次插...

  • 自增主键与UUID的优缺点

    自增主键 自增ID是在设计表时将id字段的值设置为自增的形式,这样当插入一行数据时无需指定id会自动根据前一字段的...

  • 前自增运算符和后自增运算符

    前自增运算符和后自增运算符 前自增运算符:先自增再做其他操作; 后自增运算符:先做其他操作再自增。 例如:

  • java(4-运算符)

    自增自减运算符 前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算。后缀自增自减法(a+...

网友评论

    本文标题:当自增遇到零

    本文链接:https://www.haomeiwen.com/subject/vrktahtx.html