原作者:陆凯
适用范围
mtk异构迁移mysql到mogdb
mtk:2.8.3
mogdb:3.0.0
问题概述
在生产中使用mtk工具进行异构迁移(mysql to mogdb)带子分区的表t时,报错MySQL-2008: MySQL Not Support SubPart Type KEY.
mysql表结构(拥有子分区):
CREATE TABLE t (
TRANSIDO varchar(30) NOT NULL,
MOBILE varchar(11) NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL,
UNIQUE T_UQ_IDX (TRANSIDO,APP,INSERTTIME,MOBILE) USING BTREE,
KEY T_MOBILE_IDX (MOBILE) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (TO_DAYS(INSERTTIME))
SUBPARTITION BY KEY (MOBILE)
SUBPARTITIONS 9
(PARTITION p20230623 VALUES LESS THAN (739059) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) ;
问题原因
在mysql中,分区有四种类型分别是by range、by list、by hash、by key,且仅range和list分区支持子分区,子分区类型只能是hash(需要整型字段)或者key,mtk不支持mysql的子分区by key划分。
问题测试
1.删除掉字段上的key,重新迁移
CREATE TABLE t(
TRANSIDO varchar(30) NOT NULL,
MOBILE varchar(11) NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (TO_DAYS(INSERTTIME))
SUBPARTITION BY KEY (MOBILE)
SUBPARTITIONS 9
(PARTITION p20230623 VALUES LESS THAN (739059) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
相同报错,排除字段上设置的unique以及key导致产生的这种异常
2.修改子分区类型(mysql子分区只支持hash或者key,修改字段类型为int,采用by hash子分区),重新迁移
CREATE TABLE t(
TRANSIDO varchar(30) NOT NULL,
MOBILE int NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL,
UNIQUE T_UQ_IDX (TRANSIDO,APP,INSERTTIME,MOBILE) USING BTREE,
KEY T_MOBILE_IDX (MOBILE) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (TO_DAYS(INSERTTIME))
SUBPARTITION BY HASH (MOBILE)
SUBPARTITIONS 9
(PARTITION p20230623 VALUES LESS THAN (739059) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
成功迁移,锚定错误问题产生于mysql的by key子分区无法迁移,但是支持by hash子分区
3.删除掉表的子分区,测试分区by key
CREATE TABLE t(
TRANSIDO varchar(30) NOT NULL,
MOBILE varchar(11) NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL,
UNIQUE T_UQ_IDX (TRANSIDO,APP,INSERTTIME,MOBILE) USING BTREE,
KEY T_MOBILE_IDX (MOBILE) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY KEY (MOBILE)
PARTITIONS 9;
成功迁移,说明by key仅仅在子分区中时mtk不支持
解决方案
方法1:开启mtk的noSupportPartTabToNormalTab参数,该参数作用是将带分区的表当作一般的表处理(注释了表分区部分),不创建分区结构,但是迁移仍然失败,参数无效:
CREATE TABLE t (
TRANSIDO varchar(30) NOT NULL,
MOBILE varchar(11) NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL,
UNIQUE T_UQ_IDX (TRANSIDO,APP,INSERTTIME,MOBILE) USING BTREE,
KEY T_MOBILE_IDX (MOBILE) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!50100 PARTITION BY RANGE (TO_DAYS(INSERTTIME))
SUBPARTITION BY KEY (MOBILE)
SUBPARTITIONS 9
(PARTITION p20230623 VALUES LESS THAN (739059) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
方法2:在目标端mogdb中根据mysql的语法释意手动创建表结构,建立表分区信息,建立好表结构后只迁移源端对应表的数据,迁移成功(后续需要在mogdb端手工创建分区索引)。
改写需要注意的问题:
1.varchar长度变为原长3倍(mysql的varchar是字符长度,而mogdb的varchar是字节长度,utf8的汉字是三个字节)
2.datetime变为timestamp
3.int变为integer
4.unique与primary key的语法转换
5.分区语法转换(在mysql中by key分区策略对应mogdb的by hash分区策略)
CREATE TABLE t (
TRANSIDO varchar(30) NOT NULL,
MOBILE varchar(11) NOT NULL,
INSERTTIME datetime NOT NULL,
APP varchar(100) DEFAULT NULL,
UNIQUE (TRANSIDO,APP,INSERTTIME,MOBILE),
PRIMARY KEY (MOBILE)
) PARTITION BY RANGE (INSERTTIME) SUBPARTITION BY HASH (MOBILE) (
PARTITION p20230623 VALUES LESS THAN ('2023-06-23 00:00:00')
(
SUBPARTITION p1_1,
SUBPARTITION p1_2,
SUBPARTITION p1_3,
SUBPARTITION p1_4,
SUBPARTITION p1_5,
SUBPARTITION p1_6,
SUBPARTITION p1_7,
SUBPARTITION p1_8,
SUBPARTITION p1_9
),
PARTITION pmax VALUES LESS THAN (MAXVALUE)
(
SUBPARTITION p2_1,
SUBPARTITION p2_2,
SUBPARTITION p2_3,
SUBPARTITION p2_4,
SUBPARTITION p2_5,
SUBPARTITION p2_6,
SUBPARTITION p2_7,
SUBPARTITION p2_8,
SUBPARTITION p2_9
)
);