自增字段写入数据表现不一致的情况

t6 是聚簇索引表,
t7 是非聚簇索引表,且未指定主键。
在非聚簇索引表中,“若创建表时没有指定主键时,TiDB 会使用 _tidb_rowid 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器。

这是应该算是 TiDB 和 MySQL 的差异。
避免这种差异最好的办法是: 表需要有主键或者唯一索引

貌似这样看会清晰一些:

drop table t6,t7;

create table t6 (
id int(1) not null auto_increment,
name varchar(64),
primary key(id)
) engine=innodb;

create table t7 (
id int(1) not null auto_increment,
name varchar(64),
key idx_id(id)
) engine=innodb;

insert into t6 values(1,‘chen’),(2147483646,‘wu’);
insert into t7 values(1,‘chen’),(2147483646,‘wu’);

mysql> select _tidb_rowid,id,name from t7;
±------------±-----------±-----+
| _tidb_rowid | id | name |
±------------±-----------±-----+
| 2147483647 | 1 | chen |
| 2147483648 | 2147483646 | wu |
±------------±-----------±-----+
2 rows in set (0.00 sec)

mysql> SELECT AUTO_INCREMENT,TIDB_ROW_ID_SHARDING_INFO FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME =‘t7’;
±---------------±--------------------------+
| AUTO_INCREMENT | TIDB_ROW_ID_SHARDING_INFO |
±---------------±--------------------------+
| 2147483649 | NOT_SHARDED |
±---------------±--------------------------+
1 row in set (0.02 sec)

mysql> insert into t7 (name) values(‘a47’);
ERROR 1690 (22003): constant 2147483649 overflows int

t7 如果是显示插入 ,是OK的,试试看 t8 :

drop table if exists t8;
create table t8 (
id int(1) not null auto_increment,
name varchar(64),
key idx_id(id)
) engine=innodb;

insert into t8 values(1,‘chen’),(2,‘wu’);
insert into t8 values(3,‘li’),(4,‘wang’);
insert into t8 values(2147483645,‘zhang’),(2147483646,‘zhao’);
insert into t8 values(2147483647,‘a47’);
insert into t8 values(2147483647,‘a47’);

mysql> select _tidb_rowid,id,name from t8;
±------------±-----------±------+
| _tidb_rowid | id | name |
±------------±-----------±------+
| 3 | 1 | chen |
| 4 | 2 | wu |
| 5 | 3 | li |
| 6 | 4 | wang |
| 2147483647 | 2147483645 | zhang |
| 2147483648 | 2147483646 | zhao |
| 2147483649 | 2147483647 | a47 |
| 2147483650 | 2147483647 | a47 |
±------------±-----------±------+
8 rows in set (0.01 sec)

隐式的插入会报错:
mysql> insert into t8 values(2147483648,‘a48’);
ERROR 1264 (22003): Out of range value for column ‘id’ at row 1
mysql> insert into t8(name) values(‘a47’);
ERROR 1690 (22003): constant 2147483652 overflows int

1 个赞

请问有官方文档依据么?

这里
https://docs.pingcap.com/zh/tidb/stable/mysql-compatibility

又学到了

若创建表时没有指定主键时,TiDB 会使用 _tidb_rowid 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器。如果指定了自增列为主键,则 TiDB 会用该列来标识行。

这个可以理解。

另外,您的 t8 和我上面那个不一样哈,少了主键。
官档中好像没有明确指出如果自增列和主键同时存在且不是同一字段时,如何分配 AUTO_INCREMENT

tidb 中 AUTO_INCREMENT 为什么会停在 2147513647, 而不是 2147513648

表里是不允许存在两个自增列的,如果自增列不是主键,但有别的列做主键,那只分配自增列就可以了,key是主键这个不用管;

学到了

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。