问题现象
写入报错 4016。
问题示例如下。
创建表 t1 ,column 设有自增属性(设置auto_increment)。
obclient [test]> create table t1 (col1 int not null auto_increment); Query OK, 0 rows affected (0.114 sec)执行
Alter Table,将 column 自增属性去掉,并且此时 column 的值定义是NOT NULL。obclient [test]> alter table t1 modify column col1 int not null; Query OK, 0 rows affected (0.088 sec)执行 Truncate Table。
obclient [test]> truncate table t1; Query OK, 0 rows affected (0.061 sec)执行
Alter Table,给 2 中同一个 column 加自增属性。obclient [test]> alter table t1 modify column col1 int auto_increment; Query OK, 0 rows affected (0.141 sec)在执行
insert into table或show create table时会报错 4016。obclient [test]> insert into t1 values("666"); ERROR 4016 (HY000): Internal error
OBServer 日志中有 inner_autoinc_version can not less than autoinc_version 信息。

执行如下命令检查发现 __all_virtual_auto_increment 表和 __all_virtual_table 中同一个 table 的 truncate version 不一致的 SQL 的 count 不为 0 时则会命中该问题。

问题诊断
触发条件
Alter Table 反复添加和删除自增列属性,并且自增列默认值为 NOT NULL,并且 Alter Table 之后有执行 Truncate Table。
事前巡检
该 SQL 查询结果不为 0,则是有 truncate_version 不一致的问题。
obclient> select count(*) from (select * from __all_virtual_table) as a join (select * from __all_virtual_auto_increment) as b where a.tenant_id = b.tenant_id and a.table_id = b.sequence_key and a.autoinc_column_id = b.column_id and a.truncate_version != b.truncate_version;
事后诊断
- observer 日志中有
inner_autoinc_version can not less than autoinc_version。 - 填写 tenant_id、table_id,查询对应租户下的 table 信息,如果个数不为 0,则是有 truncate_version 不一致的问题。
obclient> select count(*) from (select * from __all_virtual_table where table_id = $table_id and tenant_id = $tenant_id) as a join (select * from __all_virtual_auto_increment) as b where a.tenant_id = b.tenant_id and a.table_id = b.sequence_key and a.autoinc_column_id = b.column_id and a.truncate_version != b.truncate_version;
问题原因
因为 Alter Table 重新添加自增列属性的时候,由于一个内核的缺陷,并没有 reset __all_auto_increment 表,导致此表的值被复用。Insert 数据的时候会校验 table schema 的 truncate version 和自增列的 truncate version。如果 table schema 的 truncate_version 比自增列 __all_auto_increment 表的 truncate_version 大的时候,则会报错 -4016。
问题的风险及影响
MySQL 租户下,有 NOT NULL 的自增列情况下,进行 Alter Table、Truncate Table 的场景下会导致 insert table 写入报错和 show create table 展示报错。
影响版本
- OceanBase 数据库 V4.1.0 BP3(oceanbase-4.1.0.2-103000072023081111)(含) 到 V4.1.0 BP4 Hotfix2(oceanbase-4.1.0.2-104020012023110316)(含)之间的所有版本。
- OceanBase 数据库 V4.2.0 所有版本。
- OceanBase 数据库 V4.2.1 和 V4.2.1 BP1(oceanbase-4.2.1.1-101000062023103122) 版本。
解决方法及规避方式
解决方法
方法一:通过更改 table 对应租户的
__all_auto_increment表,让其 truncate version 和__all_virtual_table表中table_id对应租户的 truncate version 值一致。警告
操作内部表存在一定的风险,请联系 OceanBase 技术支持协助处理。
方法二:DROP TABLE 之后,重建 TABLE。
方法三:升级到修复版本。目前已修复的版本包含 OceanBase 数据库 V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119) 及之后版本。
规避方式
避免对一个表的同一个列做如下操作:
- 对于表中列定义为
NOT NULL的,执行Alter Table去掉该列自增属性。 - 执行
Truncate Table。 - 执行
Alter Table对表中列添加自增属性。