MySQL 复制表的方法
1、mysqldump
执行过程:
一、将数据导出为sql 文件。
mysqldump-h$host-P$port-u$user--add-locks=0--no-create-info--single-transaction--set-gtid-purged=OFFdb1t--where="a>900"--result-file=/client_tmp/t.sql
将数据导出为sql 文件保存。上面几个参数的含义分别是:
1、–single-transaction的作用是,在导出数据的时候不需要对表db1.t加表锁,而是使用STARTTRANSACTIONWITHCONSISTENTSNAPSHOT的方法;
2、–add-locks设置为0,表示在输出的文件结果里,不增加"LOCKTABLEStWRITE;";
3、–no-create-info的意思是,不需要导出表结构;
4、–set-gtid-purged=off表示的是,不输出跟GTID相关的信息;
5、–result-file指定了输出文件的路径,其中client表示生成的文件是在客户端机器上的。
二、执行文件,添加到表中
mysql-h127.0.0.1-P13000-urootdb2-e"source/client_tmp/t.sql"
source并不是一条SQL语句,而是一个客户端命令。也就是服务器端具体执行的是文件中的一条条sql 语句,所以binlog 记录的都是具体的sql。
特点
1、生成的sql文件保存在客户端
2、默认保存数据方式是多个记录对,如下面格式
如果想要保存为一条语句只保存一条记录,那么可以加上参数–skip-extended-insert。
2、导出CSV文件(最灵活)
执行过程
一、导出为CSV 文件
select*fromdb1.twherea>900intooutfile'/server_tmp/t.csv';
注意:
1、intooutfile指定了文件的生成位置(/server_tmp/),这个位置必须受参数secure_file_priv的限制。
参数secure_file_priv的可选值和作用分别是:
1)如果设置为empty,表示不限制文件生成的位置,这是不安全的设置;
2)如果设置为一个表示路径的字符串,就要求生成的文件只能放在这个指定的目录,或者它的子目录;
3)如果设置为NULL,就表示禁止在这个MySQL实例上执行select…intooutfile操作。
2、如果同一个目录下存在同名文件,就会报错
3、一般情况下一条记录就对应CSV 文件中的一行,但是如果某个字段值中有"换行、制表符" 那么文件中也会包含,并且使用"\" 来转义。
二、导入数据
loaddatainfile'/server_tmp/t.csv'intotabledb2.t;
过程:
1、打开文件/server_tmp/t.csv,以制表符(\t)作为字段间的分隔符,以换行符(\n)作为记录之间的分隔符,进行数据读取;
2、启动事务。
3、判断每一行的字段数与表db2.t是否相同:
1)若不相同,则直接报错,事务回滚;
2)若相同,则构造成一行,调用InnoDB引擎接口,写入到表中。
4、重复步骤3,直到/server_tmp/t.csv整个文件读入完成,提交事务。
特点
1、文件保存在服务器端
2、关于binlog 的记录,过程如下:
1)主库执行完成后,将/server_tmp/t.csv文件的内容直接写到binlog文件中。
2)往binlog文件中写入语句loaddatalocalinfile‘/tmp/SQL_LOAD_MB-1-0'INTOTABLE`db2`.`t`。
3)把这个binlog日志传到备库。
4)备库的apply线程在执行这个事务日志时:
a.先将binlog中t.csv文件的内容读出来,写入到本地临时目录/tmp/SQL_LOAD_MB-1-0中;
b.再执行loaddata语句,往备库的db2.t表中插入跟主库相同的数据。
关于"local":
1)不加“local”,是读取服务端的文件,这个文件必须在secure_file_priv指定的目录或子目录下;
2)加上“local”,读取的是客户端的文件,只要mysql客户端有访问这个文件的权限即可。这时候,MySQL客户端会先把本地文件传给服务端(其他会话涉及的操作),然后执行上述的loaddata流程。
3、上面的导出操作并不会导出表结构,所以,如果向导出表结构,可以使用mysqldump 来同时导出CSV 和表结构
mysqldump-h$host-P$port-u$user--single-transaction--set-gtid-purged=OFFdb1t--where="a>900"--tab=$secure_file_priv
会在$secure_file_priv定义的目录下,创建一个t.sql文件保存建表语句,同时创建一个t.txt文件保存CSV数据。
3、物理拷贝(最快)
在5.6之前,想要直接把.frm和.ibd文件拷贝到要拷贝的目录下是不行的,因为一个Innodb表除了需要这两个文件还需要在数据字典中注册。但是从5.6 开始可以解决这一问题,在5.6 引入了可传输空间,可以通过导出+ 导入表空间来实现拷贝
过程
假设我们现在的目标是在db1库下,复制一个跟表t相同的表r,具体的执行步骤如下:
1、执行createtablerliket,创建一个相同表结构的空表;
2、执行altertablerdiscardtablespace,这时候r.ibd文件会被删除;
3、执行flushtabletforexport,这时候db1目录下会生成一个t.cfg文件;
4、在db1目录下执行cpt.cfgr.cfg;cpt.ibdr.ibd;这两个命令(这里需要注意的是,拷贝得到的两个文件,MySQL进程要有读写权限);
5、执行unlocktables,这时候t.cfg文件会被删除;
6、执行altertablerimporttablespace,将这个r.ibd文件作为表r的新的表空间,由于这个文件的数据内容和t.ibd是相同的,所以表r中就有了和表t相同的数据。
注意:
1、在第3步执行完flsuhtable命令之后,db1.t整个表处于只读状态,直到执行unlocktables命令后才释放读锁;
2、在执行importtablespace的时候,为了让文件里的表空间id和数据字典中的一致,会修改r.ibd的表空间id。而这个表空间id存在于每一个数据页中。因此,如果是一个很大的文件(比如TB级别),每个数据页都需要修改,所以你会看到这个import语句的执行是需要一些时间的。当然,如果是相比于逻辑导入的方法,import语句的耗时是非常短的。
局限
1、必须是全表拷贝,不能条件拷贝
2、需要到服务器上拷贝数据,在用户无法登录数据库主机的场景下无法使用
3、由于是通过拷贝物理文件实现的,源表和目标表都是使用InnoDB引擎时才能使用
总结
1、前两个都是逻辑备份,也就是可以跨引擎使用,最后一个不行
2、前两个可以条件拷贝,最后一个不行
3、第二个功能是最灵活的,但是在集群从库接收时会比较耗时(需要先拷贝CSV 文件数据到本地临时文件),最后一个执行效率是最高的,但是不能跨引擎,且只能进行全量拷贝。
以上就是MySQL复制表的方法的详细内容,更多关于MySQL复制表的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。