暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TDSQL迁移myloader:39626报错

原创 冯睿 2021-09-13
1556

背景介绍:

TDSQL平台下,某系统由于业务需求,要将其中三个数据库迁移至其他实例。TDSQL拥有DCN同步以及多源同步等迁移功能,但是由于前期部署规划问题并没有安装相关组件,因此综合考虑后,决定使用mydumper进行数据冷迁移。

正文:

导出源数据:

cd /data/home/tdsql/tdsqlinstall/mysqlagent/bin
./mydumper -u数据库用户名 -p 密码 -h 源实例网关地址 -P 网关端口 -B 数据库名 --threads=线程数 --outputdir=导出目录 --events --routines --triggers --less-locking

Mydumper参数说明

–events 备份事件
–routines 备份存储过程和函数
–triggers 备份触发器
–less-locking 减少对 InnoDB 表的锁施加时间
–ignore-sysdb 忽略 sysdb 库和 mysql 库
–chunk-filesize 将表按大小分块时,指定的块大小,单位是 MB
–complete-insert 使用完整的 insert 语句(包含列名称)。
–outputdir 导出的目录
–complete-insert, -c 使用完整的 insert 语句(包含列名称)。
–single-transaction 该选项在导出数据之前提交一个 BEGIN SQL 语句, BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。
–add-drop-database 每个数据库创建之前添加 drop 数据库语句。
–add-drop-table 每个数据表创建之前添加 drop 数据表语句。 (默认为打开状态,使用–skip-add-drop-table 取消选项)
–add-locks 在每个表导出之前增加 LOCK TABLES 并且之后 UNLOCK TABLE。 (默认为打开状态,使用–skip-add-locks 取消选项)
–set-gtid-purged=OFF 这个选项可以取消 GTID 信息写入 dump 文件。

导入数据到新实例:

./myloader -u-u数据库用户名 -p 密码 -h 新实例网关地址 -P 新网关端口 -v 1 --threads=线程数 --outputdir=导出目录 --enable-binlog

Myloader参数说明

–enable-binlog 启用还原数据的二进制日志
–overwrite-tables 如果要恢复的表存在,则先 drop 掉该表,使用该参数,需要备份时候要备份表结构

导出导入的操作比较简单,需要注意的是threads配置数不宜过大,否则会过多占用DB机器的资源,最终影响业务系统的性能;另外需要先预估导出数据文件的大小,导出路径应该留有充足的空间(不建议导出到根目录)

在导入完成后,有几个表出现如下报错

** (myloader:39626): CRITICAL **: Error restoring cgdb.eval_rec_status from file cgdb.eval_rec_status.sql: Duplicate entry '0' for key 'PRIMARY'
** (myloader:39626): CRITICAL **: Error restoring cgdb.databasechangelog from file cgdb.databasechangelog.sql: Duplicate entry '0' for key 'PRIMARY'

与源环境进行了数据比对,发现以上报错的两个表在新环境下,创建成功但是无数据导入。

原环境表.png

新环境表.png

根据报错相关信息,发现这几张表并无主键,导出表语句(db.table-schema.sql)如下

/*!40101 SET NAMES binary*/;
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;

CREATE TABLE `databasechangelog` (
  `ID` varchar(255) NOT NULL,
  `AUTHOR` varchar(255) NOT NULL,
  `FILENAME` varchar(255) NOT NULL,
  `DATEEXECUTED` datetime DEFAULT NULL,
  `ORDEREXECUTED` int(11) NOT NULL,
  `EXECTYPE` varchar(10) NOT NULL,
  `MD5SUM` varchar(35) DEFAULT NULL,
  `DESCRIPTION` varchar(255) DEFAULT NULL,
  `COMMENTS` varchar(255) DEFAULT NULL,
  `TAG` varchar(255) DEFAULT NULL,
  `LIQUIBASE` varchar(20) DEFAULT NULL,
  `CONTEXTS` varchar(255) DEFAULT NULL,
  `LABELS` varchar(255) DEFAULT NULL,
  `DEPLOYMENT_ID` varchar(10) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=10108 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;


插入数据的语句(db.table.sql)如下:

/*!40101 SET NAMES binary*/;
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
/*!40103 SET TIME_ZONE='+00:00' */;
INSERT INTO `databasechangelog` VALUES(‘xxx’,’xxx’,’xxx’...省略若干数据);


从以上信息可以得知这张表并无主键,但是为何会出现主键相关报错,决定去排查源环境下的表结构。
未使用主键表.png

源环境下该表有一个名为tdsql_pk_auto_implicit的主键。当一个表创建时没有指定主键,那么TDSQL会自动创建一个主键,另外值得一提的是,该主键只能通过jmysql(super权限)的方式才可见,业务用户是无法查到该主键的。同理,在新环境下没有主键的表也会自动创建名为tdsql_pk_auto_implicit的主键,这样就可以理解为什么会有 (myloader:39626): Duplicate entry ‘0’ for key 'PRIMARY’这条报错了,因为插入数据的语句格式为INSERT INTO databasechangelog VALUES(‘xxx’,’xxx’,’xxx’…省略若干数据); 并没有指定列名。
想要指定列名,在mydumper工具中可以使用参数 --complete-insert,(使用包含列名称的insert 语句)导出,结果如下

/*!40101 SET NAMES binary*/;
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
/*!40103 SET TIME_ZONE='+00:00' */;
INSERT INTO `databasechangelog` (`ID`,`AUTHOR`,`FILENAME`,`DATEEXECUTED`,`ORDEREXECUTED`,`EXECTYPE`,`MD5SUM`,`DESCRIPTION`,`COMMENTS`,`TAG`,`LIQUIBASE`,`CONTEXTS`,`LABELS`,`DEPLOYMENT_ID`) VALUES(‘xxx’,’xxx’,’xxx’...省略若干数据);

再次使用myloader导入,成功无报错,至此,问题解决。

总结:

TDSQL中,无主键的表会自动创建一个名为tdsql_pk_auto_implicit的主键,该主键只能通过jmysql(super权限)的方式才可见,业务用户无法查到该主键。这类表在使用myloader导入时,需要使用–complete-insert 参数,生成的导入语句需要指定列名,否则会导入失败。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论