MySQL数据库迁移快速导出导入大量数据(外发)

2023-11-17

数据库迁移是我们经常可遇到的问题,对于少量的数据,迁移基本上不会有什么问题。生产环境中,有以下情况需要做迁移工作:

磁盘空间不够。比如一些老项目,选用的机型并不一定适用于数据库。随着时间的推移,硬盘很有可能出现短缺;
业务出现瓶颈。比如项目中采用单机承担所有的读写业务,业务压力增大,不堪重负。如果 IO 压力在可接受的范围,会采用读写分离方案;
机器出现瓶颈。机器出现瓶颈主要在磁盘 IO 能力、内存、CPU,此时除了针对瓶颈做一些优化以外,选择迁移是不错的方案;
项目改造。某些项目的数据库存在跨机房的情况,可能会在不同机房中增加节点,或者把机器从一个机房迁移到另一个机房。再比如,不同业务共用同一台服务器,为了缓解服务器压力以及方便维护,也会做迁移。

MySQL迁移通常使用的有三种方法:

1、数据库直接导出,拷贝文件到新服务器,在新服务器上导入。
2、使用第三方迁移工具。
3、数据文件和库表结构文件直接拷贝到新服务器,挂载到同样配置的MySQL服务下。

第一种方案的优点:会重建数据文件,减少数据文件的占用空间,兼容性最好,导出导入很少发生问题,需求灵活。缺点:使用传统导出导入时间占用长。
第二种方案的优点:设置完成后传输无人值守,自动完成。缺点:不够灵活,设置繁琐,传输时间长,异常后很难从异常的位置继续传输。
第三种方案的优点:时间占用短,文件可断点传输,操作步骤少。缺点:新旧服务器中MySQL版本及配置必须相同,可能引起未知问题。

假如数据库迁移是因为业务瓶颈或项目改造等需要变动数据表结构的(比如分区分表),我们便只能使用第一种方法了。

使用MySQL的SELECT INTO OUTFILE 、LOAD DATA INFILE快速导出导入数据

LOAD DATA INFILE语句从一个文本文件中以很高的速度读入一个表中。MySQL官方文档也说明了,该方法比一次性插入一条数据性能快20倍。

当用户一前一后地使用SELECT ... INTO OUTFILE 和LOAD DATA INFILE 将数据从一个数据库写到一个文件中,然后再从文件中将它读入数据库中时,两个命令的字段和行处理选项必须匹配。否则,LOAD DATA INFILE 将不能正确地解释文件内容。

下面是具体的操作过程:
环境:Centos 6.10
MySQL:8.0.22

首先在MySQL中执行指令:
在要导入的MySQL上,执行如下命令,确认可写(有些在集群中的机是不可写的):
select @@read_only;
set global read_only=0;
COMMIT;

在要导入的机上:
show variables like 'require_secure%';
show variables like '%secure%';
set GLOBAL require_secure_transport=ON;  (注意:执行此语句会造成数据库不可使用工具和其它程序连接,只能使用本机命令行连接,OFF其它程序可以连接,ON不可以连接)
COMMIT;

使用:
show variables like '%secure%'; 
应该可以看到:
require_secure_transport    OFF
secure_file_priv    /var/lib/mysql-files/
注意这个路径,后面会使用到,现在需要确定几件事情:
1、你是否真计划把你的导出文件放到这个目录下,如果确定,那一定要确定你导出的文件大小,由于这个目录一般情况下较小,导出的数据过多会撑满根目录。
2、如果确认修改或使用这个目录,后面的语句中必须与这个一致

修改secure_file_priv的方法(这个值不可以通过命令行修改):
mkdir /u01/mysql-files
chown -R mysql:mysql /u01/mysql-files
vim /etc/my.cnf
在其中添加:
secure_file_priv=/u01/mysql-files

这里修改后必须重启MySQL:
service mysqld restart

重启完成后,再使用“show variables like '%secure%' ”查看,即可确认这个目录已切换至指定的目录。

再次强调,这个目录是后面导入导出使用的目录。

做好以下工作后,即可使用以下脚本进行导出:
export.sh :
----------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
rm -fr ./tables
chown -R mysql:mysql ../
mysql mysql -h localhost -P3306 -uroot -p123456 <<!  #连接数据库
    USE ${1};   #设置数据库名参数
    SELECT t.TABLE_NAME into outfile '/u01/mysql-files/tables' FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\n'  FROM INFORMATION_SCHEMA.TABLES t WHERE t.TABLE_SCHEMA = '${1}'  AND t.TABLE_NAME NOT LIKE 'V_%';
!

while read line
do
   #mysql -uroot -p123456 ${1} -e "LOAD DATA INFILE '/u01/mysql-files/$line' INTO TABLE $line  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'";
   echo "开始导出 $line 表,目标文件:/u01/mysql-files/$line"
   mysql -h localhost -P3306 -uroot -p123456 ${1} -e "select * into outfile '/u01/mysql-files/$line' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' from $line";

done < tables

exit;
----------------------------------------------------------------------------------------------------------------------------

授权:
chmod 777 export.sh

执行:
./export.sh 数据库名

导入脚本:
import.sh
----------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
 
while read line
do
   echo "开始导入 /u01/mysql-files/$line 至 TABLE $line"
   mysql -h localhost -P3306 -uroot -p123456 ${1} -e "LOAD DATA INFILE '/u01/mysql-files/$line' INTO TABLE $line  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"
   echo "完成导入 /u01/mysql-files/$line 至 TABLE $line"
done < tables

----------------------------------------------------------------------------------------------------------------------------
授权:
chmod 777 import.sh

执行:
./import.sh 数据库名


往往导出的文件可能会较大,所以需要对文件进行分割。
使用如下工具进行分隔:
linux split 命令
  功能说明:切割文件。
  语  法:split [–help][–version][-<行数>][-a <长度>][-b <字节>][-d][-d <字节>][-l <行数>][要切割的文件][输出文件名]
    示    例:split -a 2 -d -l 1000000 T_CHECK_RECORD.txt T_CHECK_RECORD_SPLIT
  补充说明:split可将文件切成较小的文件,预设每1000行会切成一个小文件。

  参  数:
  -<行数>或-l<行数>  指定每多少行就要切成一个小文件。
  -a<长度>  指定后缀长度,即自动生成的编号长度
  -b<字节>  指定每多少字就要切成一个小文件。支持单位:m,k
  -C<字节>  与-b参数类似,但切割时尽量维持每行的完整性。
  -d  使用数字后缀而不是字母。
  –help  显示帮助。
  –version  显示版本信息。
  [输出文件名]  设置切割后文件的前置文件名,split会自动在前置文件名后再加上编号。

使用例子:
split -b 100m 1111.log (按照字节分隔)
split -l 1000000 1111.log(按照行数分隔)

split -a 6 -d -l 100000 T_ALARM_LAST_1.txt T_ALARM_LAST_SPLIT

分隔文件脚本:
splitfile.sh
----------------------------------------------------------------------------------------------------------------------------
#!/bin/bash

while read line
do   
   echo "开始分割 /u01/mysql-files/$line"
   split -a 6 -d -l 100000 /u01/mysql-files/$line /u01/mysql-files/${line}_SPLIT
   mkdir /u01/mysql-files.bak
   echo "分割完毕 /u01/mysql-files/$line ,将期移入/u01/mysql-files.bak目录下"
   mv /u01/mysql-files/$line /u01/mysql-files.bak/
   echo "移动 /u01/mysql-files/$line 完毕"
done < tables
----------------------------------------------------------------------------------------------------------------------------
授权:
chmod 777 splitfile.sh

执行:
./splitfile.sh

导入脚本(注意其中的路径及连接信息,如果是空表导入的话,可以直接用INTO,而不用IGNORE INTO):
slipt_import.sh
----------------------------------------------------------------------------------------------------------------------------
#!/bin/bash

db_host='localhost'
db_user='root'
db_pass='123456'
db_port='3306'

db_db='fmmp'
mysql_files='/var/lib/mysql-files'
#mysql_files='/u01/mysql-files'
cd $mysql_files
p="/u01/mysql-files"
for f in `ls $p`
do
echo $f
eval "mv '$p/$f' $mysql_files"
eval "chown -R mysql:mysql '$mysql_files/$f'"
import_cmd="mysql -h $db_host -u$db_user -p$db_pass -P$db_port $db_db <<!
 LOAD DATA INFILE '$mysql_files/$f' IGNORE INTO TABLE ${f%_*} FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n';
!"
echo "$import_cmd"

#eval $import_cmd
mysql -h $db_host -u$db_user -p$db_pass -P$db_port $db_db <<!
 LOAD DATA INFILE '$mysql_files/$f' IGNORE INTO TABLE ${f%_*} FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n';
!

eval "mv '$mysql_files/$f' /u01/mysqlfile/"

done

echo 'finished!'

exit

----------------------------------------------------------------------------------------------------------------------------
授权:
chmod 777 slipt_import.sh

执行:
./slipt_import.sh 数据库名

关于单个表的导入请参考:
----------------------------------------------------------------------------------------------------------------------------
mysql -h localhost -uroot -p123456 -P3306 fmmp <<!
 USE fmmp;
 DELETE FROM T_CHECK_RECORD_01;
 LOAD DATA INFILE '/var/lib/mysql-files/T_CHECK_RECORD_04.txt' IGNORE INTO TABLE T_CHECK_RECORD_01 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
!
----------------------------------------------------------------------------------------------------------------------------

关于单个表的导出请参考:
----------------------------------------------------------------------------------------------------------------------------
mysql mysql -h localhost -P3306 -uroot -p123456 <<!  #连接数据库
    USE fmmp;   #设置数据库名参数
    select * into outfile '/var/lib/mysql-files/T_CHECK_RECORD_03.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' from T_CHECK_RECORD WHERE CHECK_RECORD_ID IN (32341776,32341777,32341778);
!
----------------------------------------------------------------------------------------------------------------------------

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL数据库迁移快速导出导入大量数据(外发) 的相关文章

  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • MySQL正则表达式:如何将字符串中的数字与\d匹配?

    我有一个专栏release date它以字符串格式存储日期 不是 DATETIME 格式 因为它们有时可以是任何其他字符串文字 我想根据给定的月份和年份查找任意日期的所有记录 尝试遵循但对我不起作用 gt Post find all con
  • 将 PDF 转换为 600dpi 的 TIFF 和 jpg 96 dpi

    我想使用 ImageMagick 从 Python 脚本将 pdf 转换为 600 dpi 的 tiff 和 96 dpi 的 jpg 我使用 imagemagick 命令行完成了这项任务 但我想使用python中的Imagemagick将
  • Mysql带限制的删除语句

    我试图从表中删除行 但出现错误 DELETE FROM chat messages ORDER BY timestamp DESC LIMIT 20 50 我在 50 时收到此错误 您的 SQL 语法有错误 检查与您的 MySQL 服务器版
  • “修改列”与“更改列”

    我知道 我们不能使用重命名列MODIFY COLUMN语法 但我们可以使用CHANGE COLUMN syntax 我的问题是 主要用途是什么modify syntax 例如 ALATER TABLE tablename CHANGE co
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • 针对约 225 万行的单表选择查询的优化技术?

    我有一个在 InnoDB 引擎上运行的 MySQL 表 名为squares大约有 2 250 000 行 表结构如下 squares square id int 7 unsigned NOT NULL ref coord lat doubl
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • 使用 MYSQL 将 h:mm pm/am 时间格式插入数据库

    我正在尝试将以 h mm am pm 格式写入的时间插入到存储为标准 DATETIME 格式 hh mm ss 的数据库中 但我不知道如何将发布的时间转换为标准格式所以数据库会接受它 这是我到目前为止一直在尝试的 title POST in
  • rake db 问题:迁移 -

    我无法为 Ruby on Rails 设置 MySQL 数据库 设置数据库并确保 config database yml 文件匹配后 我遇到了以下错误消息 U Rails alpha gt rake db migrate trace in
  • 如何为 MySQL 中的字段或列添加别名?

    我正在尝试做这样的事情 但我收到未知的列错误 SELECT SUM field1 field2 AS col1 col1 field3 AS col3 from core 基本上 我只想使用别名 这样我就不需要执行之前执行的操作 这在mys
  • docker容器大小远大于实际大小

    我正在尝试从中构建图像debian latest 构建后 报告的图像虚拟大小来自docker images命令为 1 917 GB 我登录查看尺寸 du sh 大小为 573 MB 我很确定这么大的尺寸通常是不可能的 这里发生了什么 如何获
  • 多处理:仅使用物理核心?

    我有一个函数foo它消耗大量内存 我想并行运行多个实例 假设我有一个有 4 个物理核心的 CPU 每个核心有两个逻辑核心 我的系统有足够的内存来容纳 4 个实例foo并行但不是 8 个 此外 由于这 8 个核心中的 4 个是逻辑核心 我也不
  • MySQL:@@ 是什么意思?

    我正在阅读本页上的 MySQL 文档 http dev mysql com doc refman 5 1 en set statement html http dev mysql com doc refman 5 1 en set stat
  • 如何从 MySQL 数据查询创建 XML 文件?

    我想知道一种仅使用 MySQL 查询创建 XML 文件的方法 根本不使用任何脚本语言 有关于这个主题的书籍 教程吗 UPDATE 我想澄清一下 我想使用 sql 查询将 XML 数据转发到 php 脚本 Here s 关于从 MySQL S
  • 从表中选择行,其中另一个表中具有相同 id 的行在另一列中具有特定值

    在 MySQL 中 如果我们有两个表 comments key value 1 foo 2 bar 3 foobar 4 barfoo and meta comment key value 1 1 2 1 3 2 4 1 我想得到来自以下人
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 如何通过ssh检查ubuntu服务器上是否存在php和apache

    如何通过ssh检查Ubuntu服务器上apache是 否安装了php和mysql 另外如果安装的话在哪个目录 如果安装了其他软件包 例如 lighttpd 那么它在哪里 确定程序是否已安装的另一种方法是使用which命令 它将显示您正在搜索
  • 使用函数的 SQL 查询 - 如何获取列表的最大计数

    如何查询 MAXIMUM COUNT 交易次数 我的代码如下 SELECT customer id COUNT customer id FROM rental GROUP BY customer id HAVING MAX COUNT cu

随机推荐

  • 对数和指数

    参考 https www zhihu com question 21453993 这就相当于先发明减法符号 再发明加法符号 1614年 纳皮尔发明了对数和对数表 1637年 法国数学家笛卡儿发明了指数 比对数晚了20多年 1770年 欧拉才
  • 判断设备联网状态(Python)

    判断设备联网状态 Python 在Python中利用socket来判断设备是否联网 通过ping命令来验证设备的网络状态 完整代码如下 import socket def isNetOK testserver s socket socket
  • zed双目摄像头 +yolo进行双目测距

    zed双目摄像头 yolo进行双目测距 首先根据你电脑或者jetson系列中的cuda版本下载对应的zed sdk 去安装zed api 安装过程可能会出现import pyzed sl as sl ImportError DLL load
  • b站黑马的Vue快速入门案例代码——计数器

    目录 目标效果 重点原理 1 创建Vue实例的时候 2 v on 为元素绑定事件 3 v text 解析文本用 设置标签的文本值 v text 简写 为 实现步骤 代码部分 1 计数器模板 html 全是重点 2 index css 辅助作
  • ubuntu下安装jdk

    ubuntu下的jdk 氛围open jdk和oracle jdk两种 前者是开源的 其实也行 不过大部分人使用的还是oracle jdk 有些博客推荐用ppa的方式安装 但这个安装的链接被墙了 所以经常会安装失败 现在介绍另一种 手动解压
  • 解决vscode远程安装插件不了、安装太慢问题

    一 问题描述 一直显示正在安装 几个小时也没动静 特别是那个c c 插件的安装 二 解决方法 1 采用手动安装插件的方式 步骤 先去这个网站找你要安装的插件 然后下载到本地电脑 All categories Extensions Visua
  • React 入门教程系列(三)——JSX 和 虚拟 DOM

    文章目录 1 JSX 2 虚拟 DOM 3 实例1 4 实例2 5 源码 1 JSX JSX的全称是 JacaScript XML 是 React 定义的第一种类似于 XML 的 JS 拓展语法 JSX 的语法大致遵循下面几条 标签名任意
  • C++中拷贝构造函数的四种调用方式

    代码 define CRT SECURE NO WARNINGS include
  • 分享一个iec104协议的资源,一个模拟iec104协议主站端的小工具

    最近编写的iec104协议的软件也基本稳定了 现在上传到资源上去留作备份 可实现功能 V1 005 2019 331 1 增加启动调用可执行文件目录下104 ini 调用遥信点表功能 增加显示SOE功能 2 增加显示SOE功能 根据读取的点
  • 数据库批量插入,存在则更新,不存在则插入

    INSERT ON DUPLICATE KEY UPDATE 语句 在并发量比较高的时候 可能两个线程都查询某个记录不存在 所以会执行两次插入 然后其中一条必然会因为主键 这里说的主键不是递增主键 冲突而失败 数据库层MySQL中INSER
  • Python中利用compileall将py项目打包成pyc项目

    在进行python项目开发的时候一定会涉及到项目打包这个环节 有时因为一些依赖的原因没法打包成一个大的可执行文件 但为了代码的安全性我们最起码需要打包成pyc的预编译格式 这样运行者 一般是测试和线上部署 在无法看到程序源码的同时也能顺利执
  • numpy.c_和numpy.r_的用法

    numpy c 将切片对象沿第二个轴 按列 连接 np c np array 1 2 3 np array 4 5 6 array 1 4 2 5 3 6 np c np array 1 2 3 0 0 np array 4 5 6 arr
  • UML类图几种关系的总结

    在UML类图中 常见的有以下几种关系 泛化 Generalization 实现 Realization 关联 Association 聚合 Aggregation 组合 Composition 依赖 Dependency 1 泛化 Gene
  • 子类加@Data后,IDEA调试时“出现”父类属性无值

    项目场景 自测一个功能的时候 IDEA调试同过对象的VIEW查看对象内容 发现加了 Data的返回子类型中父类的属性没有出现 问题描述 父类Response中的返回VO对象 Data public class PVO private Sti
  • 链式存储之:链表的引出及其简介

    上篇博客 笔者讲解了一下顺序表ArrayList 对于ArrayList有想法的各位老铁可以看一下 值得思索的 ArrayList和线性表 你确定错过这次机会 念君思宁的博客 CSDN博客值得思索的 ArrayList和线性表 你确定错过这
  • python格式化

    python格式化是python语法中很基础也是很重要的知识 本文介绍了python格式化的几种方法仅供参考 一 格式化方法1 格式为 输出内容 对应的变量1 对应的变量2 其中 d表示整数类型 s表示字符串类型 f表示浮点类型 例子 设以
  • 半实物仿真测试方法、装置及系统与流程

    机器人控制器的测试主要包括控制器核心软件的测试和外部接口的测试 同时为了保证机器人控制器在真实工况下进行测试 需要对其实际运行的各项功能和性能指标进行测试 半实物仿真测试平台是连接控制器和被控对象进行测试的测试平台 在基于半实物仿真的实验中
  • 数据清洗:让数据更纯净,Python实战 机器学习&深度学习

    目录 步骤1 导入必要的库 步骤2 加载数据 步骤3 处理缺失值 3 1 删除含有缺失值的行
  • 给应届生开出20K月薪,看到招聘要求后,我傻眼了......

    一到秋招季 就有 灵异 事件发生 应届生痛斥找不到工作 精心准备的简历投了几十家过不了网申 而企业控诉招不到人才 今年明明扩招了 应届生be like 这些岗位都挺适合我的 简直一个量身打造 用人单位be like 岗位要求门槛写得也不高
  • MySQL数据库迁移快速导出导入大量数据(外发)

    数据库迁移是我们经常可遇到的问题 对于少量的数据 迁移基本上不会有什么问题 生产环境中 有以下情况需要做迁移工作 磁盘空间不够 比如一些老项目 选用的机型并不一定适用于数据库 随着时间的推移 硬盘很有可能出现短缺 业务出现瓶颈 比如项目中采