openGauss

开源数据库

openGauss社区官网

开源社区

使用MTK迁移Mysql源库后主键自增列导致数据无法插入问题

伊织鸟2022-09-01使用MTK迁移Mysql源库后主键自增列导致数据无法插入问题

使用 MTK 迁移 Mysql 源库后主键自增列导致数据无法插入问题

故障背景

用户使用 Mogdb 2.0.1 版本进行业务上线测试,发现在插入数据时,应用日志中提示 primary key 冲突,用户自查业务 SQL 没有问题,接到通知后,招手处理故障。 图片.png

故障描述及根源分析

通过对用户数据表的检查,发现在 id 列上有一个 primary key,并且制定了一个序列器作为自增主键的代替。初步怀疑是 id 中的值,已经超过了序列器的最大值,导致了故障的发生。 分别检查序列器和表.id 字段的最大值,发现果然 max(id)为 474,序列器最大值刚刚 44。

sql
file_manage=> \d file_table
                                    Table "file_manage.file_table"
    Column     |            Type             |                        Modifiers
---------------+-----------------------------+---------------------------------------------------------
 id            | bigint                      | not null default nextval('file_table_id_seq'::regclass)
 type_id       | bigint                      |
 column_name   | character varying(32)       | default NULL::character varying
 file_id       | character varying(64)       | default NULL::character varying
 file_name     | character varying(100)      | default NULL::character varying
 category_type | integer                     | default 0
 pieces_id     | bigint                      |
 flag          | smallint                    | default (0)::smallint
 del_flag      | smallint                    | default (0)::smallint
 create_time   | timestamp without time zone | default pg_systimestamp()
 update_time   | timestamp without time zone | default pg_systimestamp()

file_manage=> \d file_table_id_seq
   Sequence "file_manage.file_table_id_seq"
    Column     |  Type   |        Value
---------------+---------+---------------------
 sequence_name | name    | file_table_id_seq
 last_value    | bigint  | 44
 start_value   | bigint  | 1
 increment_by  | bigint  | 1
 max_value     | bigint  | 9223372036854775807
 min_value     | bigint  | 1
 cache_value   | bigint  | 1
 log_cnt       | bigint  | 32
 is_cycled     | boolean | f
 is_called     | boolean | t
 uuid          | bigint  | 0
Owned by: file_manage.file_table.id

图片.png

图片.png

同时查看报错的 id 对应值是否在 file_table 表中是否存在:

file_manage=> select count(*) from file_table where id=43;
 count
-------
     1
(1 row)

file_manage=> select count(*) from file_table where id=44;
 count
-------
     1
(1 row)

图片.png

由此,基本上可以确定故障原因在于表中主键列已经保存了一定数量的值,在操作过程中,序列器并没有进行累加,导致序列器 nextval 已经远远小于主节列值,从而引发主键冲突。咨询用户后,用户确实使用过 insert into 语句为数据表插入了部分测试数据库上的数据。

故障处理流程

使用语句重新为序列器重置 currval

file_manage=> select setval('file_table_id_seq',(select max(id) from file_table));
 setval
--------
    474
(1 row)

通知用户重新启动应用进行测试,故障现象消失。故障总结分析本次故障的成因是通过 MTK 进行数据数据迁移时,如果源库是 MySQL,MTK 会通过判断 MySQL 数据表是否存在自增主键,如果存在泽辉建立一个序列器模拟 MySQL 自增主键效果。 但是如果在此类表上进行手动 gs_dump 或者 insert into 操作时,由于在操作过程中指定了主键列的值,并不会推搞序列器的 currval,最会导致在正常的数据增删改之后,出现类似主键冲突的问题。 对应的处理办法是需要在数据插入后,手动进行序列器的 currval 的重置,指向当前主键最大值。