MySQL 数据导入方案推荐
MySQL 如何导入大批量的数据?
作者:陈伟,爱可生数据库工程师,负责 MySQL 日常维护及故障处理。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 2400 字,预计阅读需要 8 分钟。
需求背景
应用侧的同学需要对数据进行导出和导入,于是跑来找 DBA 咨询问题:MySQL 如何导入大批量的数据?
应用侧目前的方式:
- mysqldump 工具
- select outfile 语句
- 图形化管理工具(MySQL Workbench、Navicat 、DBeaver)
DBA 听了觉得挺好的呀!
DBA 想了,我的数据库我做主。通知应用侧,目前先使用之前熟悉的方式进行对比,测试之后给建议。
Tips:为了防止导入时出现大事务,造成主从延迟。
方案准备
待测方案: mysqldump、mydumper、select outfile 语句、Util.dumpTables 、Util.exportTable。
环境配置信息
配置项 | 说明 |
---|---|
MySQL 版本 | 5.7.39 |
磁盘随机读写 | 100 MiB/sec |
测试表名 | test.t_order_info |
行数 | 1000W |
字段数 | 6 |
建表语句
CREATE TABLE `t_order_info` ( `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', `order_no` varchar(64) NOT NULL DEFAULT '0000' COMMENT '订单编号', `order_status` varchar(2) NOT NULL DEFAULT '01' COMMENT '订单状态: 00-异常、01-待处理、02-进行中、03-已完成', `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标识: 1-正常、0-逻辑删除', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`ID`), UNIQUE KEY `IDX_ORDER_NO` (`order_no`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='订单表'
导出文件
- 包含数据结构和数据的 备份文件 (mysqldump、mydumper、Util.dumpTables)
- 只包含数据的 数据文件 (select outfile、Util.exportTable)
导出导入命令
导出 | 导入 |
---|---|
mysqldump | source 或 mysql< |
mydumper | myloader |
select outfile | load data |
Util.dumpTables | Util.loadDump |
Util.exportTable | Util.importTable |
方案测试
测试首先考虑的是 提升导入效率,并新增了 MySQL Shell 的使用。
mysqldump
单表导出(备份文件)
mysqldump --default-character-set=utf8mb4 --master-data=2 --single-transaction --set-gtid-purged=off --hex-blob --tables test t_order_info
--master-data=2
参数会在备份期间对所有表加锁FLUSH TABLES WITH READ LOCK
,并执行SHOW MASTER STATUS
语句以获取二进制日志信息。因此,在备份期间可能会影响数据库的并发性能。如果您不需要进行主从复制,则可以考虑不使用--master-data=2
参数。--single-transaction
参数用于在备份期间“使用事务来确保数据一致性”,从而避免在备份期间锁定表。[必须有]
备份文件
文件内容。
-- Table stricture for table `t_order_info` -- DROP TABLE IF EXISTS `t_order_info`; /*!40101 SET @saved_cs_client= @@character_set_client */; /*!49101 SET character_set_client = utf8 */; CREATE TABLE `t_order_info` ( `ID` bigint(2) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', `order_no` varchar(64) NOT NULL DEFAULT `0000` COMMENT '订单编号', `order_status` varchar(2) NOT NULL DEFAULT '01' COMMENT '订单状态: 80-异常、81-待处理、2-进行中、03-已完成', `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标识: 1-正常、0-逻辑删除', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`ID`), UNIOUE KEY `IDX_ORDER_NO` (`order no`) ) ENGINE=InnODB AUTO_INCREMENT=10129913 DEFAULT CHARSET=utf8m COMMENT='订单表'; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `t_order_info` -- LOCK TABLES `t_order_info` WRITE; /*!40000 ALTER TABLE `t_order_info` DISABLE KEYS */;
文件内容解释:
- 没有建库语句,因为是单表备份。
- 有删除表,建立表的语句,小心导入目标库时,删除表的语句,造成数据误删。
- INSERT 语句没有字段名称,导入时表结构要一致。
- 导入过程中有
lock table write
操作,导入过程中相关表不可写。 ALTER TABLE t_order_info DISABLE KEYS
此语句将禁用该表的所有非唯一索引,这可以提高插入大量数据时的性能。 对应的文件末尾有ALTER TABLE
t_order_infoENABLE KEYS
;
用途,可以将备份文件中的数据导入自定义库,“文件内容解释”部分遇到的问题可以使用下面参数解决。
--no-create-info
不包含建表语句(可以手动创建create table tablename like dbname.tablename;
)--skip-add-drop-database
不包含删库语句--skip-add-drop-table
不包含删表语句--skip-add-locks
INSERT 语句前不包含LOCK TABLES t_order_info WRITE;
--complete-insert
INSERT 语句中包含 列名称(新表的列有增加的时候)。
单表导出备份数据(只导出数据)。
mysqldump --default-character-set=utf8mb4 --master-data=2 --single-transaction --set-gtid-purged=off --hex-blob --no-create-info --skip-add-drop-table --skip-add-locks --tables dbname tablename // 部分数据导出追加参数 --where="create_time>'2023-01-02'"
导出单库中的某表为 CSV。
// 可选不导出表结构, --no-create-info --skip-add-drop-database --skip-add-drop-table /data/mysql/3306/base/bin/mysqldump -uadmin -p123456 -P3306 -h127.0.0.1 --default-character-set=utf8mb4 --single-transaction --set-gtid-purged=OFF --triggers --routines --events --hex-blob --fields-terminated-by=',' --fields-enclosed-by='"' --lines-terminated-by='\n' -T /data/mysql/3306/tmp test //其中 test 后面也可以指定表名,不指定就是全库。 test t_order_info t_order_info01 其中 --single-transaction --set-gtid-purged=OFF --triggers --routines --events --hex-blob 为了防止提示,可选
小结
1G 的备份文件,测试结果如下:
- 使用
mysql< 备份文件
导入,耗时 5 分钟。 - 使用用
source 备份文件
导入, 耗时 10 分钟。
推荐第一种,都是单线程。
mydumper
- 版本 0.14.4
多线程导出
mydumper -u admin -p 123456 -P 3306 -h 127.0.0.1 -t 8 --trx-consistency-only -G -E -R --skip-tz-utc --verbose=3 --compress --no-schemas --rows=1000000 -T test.t_order_info -o /backup // 导出时支持部分导出追加参数 --where="create_time>'2023-01-02'" // 文件输出 test01.t_order_info.00000.dat # 包含 CSV 数据 test01.t_order_info.00000.sql # 包含 LOAD DATA 语句 // 导入命令 LOAD DATA LOCAL INFILE '/data/mysql/3306/tmp/test01.t_order_info.00005.dat' REPLACE INTO TABLE `t_order_info` CHARACTER SET binary FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '\\' LINES STARTING BY '' TERMINATED BY '\n' (`ID`,`order_no`,`order_status`,`flag`,`create_time`,`modify_time`);
- 多线程导入
myloader -u admin -p 123456 -P 3306 -h 127.0.0.1 --enable-binlog -t 8 --verbose=3 -B test -d /backup // 导入主库时需要添加 --enable-binlog // 库名可以自定义 -B test
小结
耗时 2 分钟,建议如下:
- 在数据量大于 50G 的场景中,更推荐 mydumper。
- 补充场景,支持导出 CSV,也支持
--where
过滤。
mydumper -u admin -p 123456 -P 3306 -h 127.0.0.1 -t 8 --trx-consistency-only -G -E -R --skip-tz-utc --verbose=3 --where="create_time>'2023-01-02'" --no-schemas --rows=1000000 --load-data --fields-terminated-by ',' --fields-enclosed-by '"' --lines-terminated-by '\n' -T test.t_order_info -o /backup
导入命令同上,且可以按需手动进行 LOAD DATA
。
SELECT OUTFILE 语句
Tips:适合于单表数据的导出,不支持多表。
导出命令,耗时 15 秒。
SELECT * from test01.t_order_info INTO OUTFILE "/data/mysql/3306/tmp/t_order_info0630_full.csv" CHARACTER SET utf8mb4 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\'' LINES TERMINATED BY '\n'; // 带列名导出,导入时需添加 IGNORE 1 LINES; SELECT * INTO OUTFILE "/data/mysql/3306/tmp/t_order_info0630_full.csv" CHARACTER SET utf8mb4 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\'' LINES TERMINATED BY '\n' from (select 'id','order_no','order_status','flag','create_time','modify_time' union all select * from test01.t_order_info) b;
导入命令,耗时 3 分钟。
mysql -uadmin -P3306 -h127.0.0.1 -p123456 --local-infile load data local infile '/data/mysql/3306/tmp/t_order_info0630_full.csv' into table test.t_order_info CHARACTER SET utf8mb4 fields terminated by ',' OPTIONALLY ENCLOSED BY '\'' lines terminated by '\n';
小结
- 支持跨表导入。A 表的数据可以导入 B 表,因为备份文件中只有数据。
- 可自定义导出部分列,导出导入速度较快,最常用。
MySQL_Shell > dumpTables
单表导出,耗时 4 秒。
util.dumpTables("test", ["t_order_info"], "/backup")
部分导出。
util.dumpTables("test", ["t_order_info"], "/backup", {"where" : {"test.t_order_info": "create_time>'2023-01-02'"}})
导入,耗时 3 分钟。
util.loadDump("/backup")
注意:不支持部分导入,不支持跨数据库版本。
因为导入时最大支持 2 个参数,可以将导出的部分数据全部导入到新的库中。
导入命令:util.loadDump("/backup",{schema: "test_new"})
小结
- 支持跨库导入,A 库的数据可以导入 B 库。表名需要一致。不支持增量到已有数据的表中。
- 导出时和
SELECT OUTFILE
同效,导入时,比LOAD DATA
快(默认 4 线程)。
注意:
- 部分导出功能需要较新的 MySQL Shell 版本,如 8.0.33。
LOAD DATA
单线程导入 耗时 1h20min。
MySQL_Shell > exportTable
单表导出,耗时 10 秒。
util.exportTable("test.t_order_info", "/backup/t_order_info.csv", {defaultCharacterSet: "utf8mb4", fieldsOptionallyEnclosed: true, fieldsTerminatedBy: ",", linesTerminatedBy: "\n", fieldsEnclosedBy: '"', defaultCharacterSet: "utf8mb4", showProgress: true, dialect: "csv"})
部分导出。
util.exportTable("test.t_order_info", "/backup/t_order_info.csv", { dialect: "csv", defaultCharacterSet: "utf8mb4", fieldsOptionallyEnclosed: true, fieldsTerminatedBy: ",", linesTerminatedBy: "\n", fieldsEnclosedBy: '"', showProgress: true, where: "create_time>'2023-01-02'" } )
导入,耗时 10 分钟。
util.importTable("/backup/t_order_info.csv", { "characterSet": "utf8mb4", "dialect": "csv", "fieldsEnclosedBy": "\"", "fieldsOptionallyEnclosed": true, "fieldsTerminatedBy": ",", "linesTerminatedBy": "\n", "schema": "test", "table": "t_order_info" })
部分导入(不推荐使用)。
util.importTable("/backup/t_order_info.csv", { "characterSet": "utf8mb4", "dialect": "csv", "fieldsEnclosedBy": "\"", "fieldsOptionallyEnclosed": true, "fieldsTerminatedBy": ",", "linesTerminatedBy": "\n", "schema": "test100", "table": "t_order_info" })util.importTable("/backup/t_order_info0630.csv", { "characterSet": "utf8mb4", "dialect": "csv", "fieldsEnclosedBy": "\"", "fieldsOptionallyEnclosed": true, "fieldsTerminatedBy": ",", "linesTerminatedBy": "\n", "schema": "test", "table": "t_order_info" })
有报错 MySQL Error 1205 (HY000): Lock wait timeout exceeded; try restarting transaction @ file bytes range [450000493, 500000518)
需要重复执行一次,才能保证数据完整。
根据报错提示可以使用以下命令导入:
LOAD DATA LOCAL INFILE '/backup/t_order_info0630.csv' INTO TABLE `test`.`t_order_info` CHARACTER SET 'utf8mb4' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\\' LINES STARTING BY '' TERMINATED BY '\n';
MySQL 5.7 也推荐直接使用 LOAD DATA
。
小结
- 支持跨库导入,A 库的数据可以导入 B 库,表名需要一致。
- 导出时和
SELECT OUTFILE
同效。导入时,比LOAD DATA
快(默认 8 线程)。
总结
可以通过数据大小进行选用:
导出 | 导入 | 优点 | 推荐度(效率) |
---|---|---|---|
mysqldump | source 或 MySQL< | 原生,可远程 | ⭐⭐⭐ <br/>(数据量<10G) |
mydumper | myloader | 多线程 | ⭐⭐⭐<br/>(数据量>50G) |
SELECT OUTFILE | LOAD DATA | 最灵活 | ⭐⭐<br/>(数据量<20G) |
Util.dumpTables | Util.loadDump | 原生,多线程 | ⭐⭐⭐<br/>(数据量<50G) |
Util.exportTable | Util.importTable | 原生,单线程 | ⭐<br/>(数据量<20G) |
MySQL<
导入时,需要避免数据丢失。- 前 3 种都支持
WHERE
过滤,mydumper 是最快的。SELECT OUTFILE
最常用(因为支持自定义导出部分列)。 - 前 2 种因为是备份工具,所以有 FTWRL 锁。
Util.dumpTables
不支持增量到已有数据的表中,因为包含了库表的元数据信息,像 mydumper。Util.exportTable
备份是单线程,导入是多线程,不推荐的原因是导入容易出错(多次导入可解决)。- 使用建议:按照数据量选择,全表备份最快用
Util.dumpTables
,部分备份用SELECT OUTFILE
。 - 测试之后再使用,导出和导入均需要进行数据验证。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
爱可生开源社区的 SQLE 是一款面向数据库使用者和管理者,支持多场景审核,支持标准化上线流程,原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。
SQLE 获取

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
基于 ACK Fluid 的混合云优化数据访问(四):将第三方存储目录挂载到 Kubernetes,提升效率和标准化
作者:车漾 前文回顾: 本系列将介绍如何基于 ACK Fluid 支持和优化混合云的数据访问场景,相关文章请参考: -基于 ACK Fluid 的混合云优化数据访问(一):场景与架构 -基于 ACK Fluid 的混合云优化数据访问(二):搭建弹性计算实例与第三方存储的桥梁 -基于 ACK Fluid 的混合云优化数据访问(三):加速第三方存储的读访问,降本增效并行 在前一篇文章《加速第三方存储的读访问,降本增效并行》中,介绍如何加速第三方存储访问,实现更好的性能,更低的成本同时降低对专线稳定性的依赖。 还有一些客户的场景下,出于历史原因和容器存储接口开发维护的成本,并没有选择使用标准的 CSI 接口,而是使用非容器化的手段,比如自动化脚本。但是一旦拥抱云,就需要考虑如何和基于标准接口的云服务对接的问题。 而本文将重点介绍如何通过 ACK Fluid 实现第三方存储主机目录挂载 Kubernetes 化,更加标准并加速提效。 概述 有许多企业由于历史原因和技术云下存储选择没有支持 CSI 协议,只支持以主机目录的方式通过 ansible 等运维工具挂载,一方面存在与 Kubernete...
- 下一篇
什么是多云? 为什么我们需要多云可观测性 (Observability)?
Observe 是一家提供可观察性云解决方案的公司,以帮助企业加速应用故障排查和问题解决的效率。公司成立于2017年9月,总部位于美国加利福尼亚州圣马特奥。到目前为止,Observe 已经在5轮融资中总共筹集了1.62亿美元。他们最近的一轮融资是在2023年10月5日,通过可转换票据融资筹集了5000万美元,并推出了新一代人工智能功能。 本篇内容是根据Observe官网的技术文章翻译整理,以下3点是NineData的数据库工程师对多云的思考: 多云是今天的现实,也是未来的趋势 (公共云基础设施用户中有86%正在实施多云策略); 多云环境下的数据管理成为新的需求,包括文章中提到的Observability; 云环境越来越复杂,既是困难,也是机遇。 什么是多云可观察性?它是一种令人兴奋的新的科技趋势,还是只是最新一轮的被技术观测和监控厂商的营销部门夸大的流行词?你可能已经猜到了,答案介于两者之间。就像科技中许多流行的流行词一样,它起源于组织所感受到的实际需求,但在不同的上下文中,它的含义也会有所不同。因此,如果使用了多个云,是否需要多云可观察性?如何实现多云可观察性?它与“常规”可观察性有...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19