本文正在参加「技术专题19期 漫谈数据库技术」活动
前言
我们在使用MySQL时,有时会有复制表数据的需求。你都知道哪些方法呢?我们一起往下看。
insert ... select语句
首先来了解一下insert select语句。它可以快速复制一个表的数据到另一个表。
语法示例:
insert into t2(c,d) select c,d from t
要注意的是,执行的时候会将t表的行和间隙都加锁。 因为如果不加锁, 执行的时候还有插入到t的数据,binlog主备执行会出现主备不一致的问题。
复制数据的方法
复制数据有多种方法,这里总结3种:
一、mysqldump复制一张表
- 复制到本地文件命令:
mysqldump -h$host -P$port -u$user --add-locks=0 --no-create-info --single-transaction --set-gtid-purged=OFF db1 t --where="a>100" --result-file=/data/t.sql
备注:
–single-transaction的作用是,在导出数据的时候不需要对表 db1.t 加表锁;–add-locks设置为 0,表示在输出的文件结果里,不增加" LOCK TABLES t WRITE;"–no-create-info的意思是,不需要导出表结构;–set-gtid-purged=off表示的是,不输出跟 GTID 相关的信息;–result-file指定了输出文件的路径
- 再插入到db2
mysql -h127.0.0.1 -P13000 -uroot db2 -e "source /data/t.sql"
二、导出csv文件
查询结果导出到mysql服务端本地目录:
select * from db1.t where a>100 into outfile '/data/t.csv'
再load数据到db2.t中:
load data infile '/data/t.csv' into table db2.t;
三、物理拷贝方法
-
执行
create table r like t; 创建一个相同表结构的空表 -
执行
alter table r discard tablespace; 这时r.ibd文件会被删除 -
执行
flush table f for export; 这时db1目录下会生成一个t.cfg文件。(db1.t整个表处于只读状态,知道unlock tables执行后才释放锁) -
在db1目录下执行
cp t.cfg r.cfg;cp t.ibd r.ibd; -
执行
unlock tables: 此时t.cfg文件会被删除。 -
执行
alter table r import tablespace: 将这个 r.ibd 文件作为表 r 的新的表空间,由于这个文件的数据内容和 t.ibd 是相同的,所以表 r 中就有了和表 t 相同的数据。
三种方法的优缺点:
- 物理拷贝的方式速度最快。 局限性有:
1.必须是全表拷贝
2. 需要到服务器上拷贝数据
3.源表和目标表都是使用innodb时才能使用。
- mysqldump生成包含INSERT文件的方法,可以在where参数增加过滤条件来实现只导出部分数据。
- 用
select … into outfile的方法是最灵活的,支持所有的 SQL 写法。但缺点就是,每次只能导出一张表的数据,而且表结构也需要另外的语句单独备份。