Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • MySQL

    • 基础部分

    • 实战与处理方案

      • SQL语句练习
      • MySQL性能提高方案
      • 监控MySQL状态是否正常
      • 误删数据
      • 如何将一张表的数据插入到另一张表当中
        • 方法一、insert...select批量插入
        • 方法二、mysqldump方法
        • 方法三、导出CSV文件
          • 数据导出
          • 数据加载
        • 方法四、物理拷贝
        • 总结
    • 面试

  • ORM框架

  • 数据库
  • MySQL
  • 实战与处理方案
phan
2023-07-12
目录

如何将一张表的数据插入到另一张表当中

# 如何将一张表的数据插入到另一张表当中

场景:当前需要从t1表当中取出数据,插入到t2表当中。

# 方法一、insert...select批量插入

如果对对源表t1的扫描行数和加锁范围都比较小的情况下,可以使用批量插入的方式。在MySQL8.0版本下,已经支持使用临时表处理批量插入。

insert into t2 select * from t1 where a>33;
1

💣存在的问题:如果当前表t1是一个高并发业务表,会把t1锁住,从而影响业务响应时间。

# 方法二、mysqldump方法

使用mysqldump命令将数据导出成一组insert语句:

mysqldump -h$host -P$port -u$user --add-locks --no-create-info --single-transaction  --set-gtid-purged=OFF db1 t --where="a>900" --result-file=/client_tmp/t.sql
1
  • –single-transaction:导出数据时不需要对t1表加锁,而是使用START TRANSACTION WITH CONSISTENT SNAPSHOT开启事务,并创建快照读视图。
  • –add-locks:设置为0,表示输出的文件结果里,不增加”Lock tables t write“,即插入数据时不会锁表然后再写。
  • –no-create-info:表示不需要导出表结构
  • –set-gtid-purged=off:不需要输出t1表里与GTID相关的信息
  • –result-file:指定输出文件的路径,client表示输出在客户端机器上

最终得到.sql文件里的insert into语句,value就会包括多条t1表的记录。使用source客户端命令,执行文件内所有的SQL语句。

# 方法三、导出CSV文件

# 数据导出

MySQL提供以下语法将查询结果导出到服务端本地目录当中:

select * from db1.t wher a>900 into outfile '/server_tmp/t.csv';
1

注意以下几个点:

  1. 文件结果保存在MySQL服务端。
  2. 指定的文件生成位置(/server_tmp)必须受到参数secure_file_priv的限制:
    • 设置为empty:表示不限制文件生成的位置
    • 设置为一个表示路径的字符串:要求生成的文件只能放在这个指定的目录或者他的子目录
    • 设置为NULL:表示禁止在这个MySQL实例上执行上面的csv导出语句
  3. 导出命令不会覆盖文件,因此导出之前需要确认在目标文件目录下是否存在t.csv文件。否则会报错
  4. 这条命令生成的文本文件中,如果一行数据中某个字段包含换行符,那么生成的这一行文本也会进行换行(从而出现一行数据导出了两行文本)。解决方法是加上\转义字符。
  5. 导出命令不会生成表结构文件,因此导出之前还需要使用其它工具获取表结构定义。

另外可以使用mysqldump工具-tab参数,直接同时导出表结构定义和csv数据文件:

mysqldump -h$host -P$port -u$user ---single-transaction  --set-gtid-purged=OFF db1 t --where="a>900" --tab=$secure_file_priv
1

# 数据加载

最后执行以下load data命令将数据导入目标表当中,考虑到主备复制的问题(statement格式下备库机器找不到csv文件,同步终止),整个流程如下:

  1. 主库t2执行以下语句,完成数据导入:

    load data infile '/server_tmp/t.csv' into table db2.t;
    
    1
  2. 主库会将csv文件内容直接写到binlog文件当中。同时往binlog中写入如下语句(指定备库文件地址):

    load data local infile ‘/tmp/SQL_LOAD_MB-1-0’ INTO TABLE `db2`.`t`;
    
    1
  3. 备库的binlog同步应用线程(客户端)收到binlog后:

    • 将csv文件读出并写入到''/tmp/SQL_LOAD_MB-1-0'(执行同步应用线程的客户端的机器上)
    • 执行binlog中的load data语句

# 方法四、物理拷贝

一个InnoDB表除了包含表结构定义.frm文件和表数据.ibd文件,还需要在数据字典中注册,系统才能够接受和识别。

因此单纯将两个文件拷贝到目标文件目录下,并不能真正实现表数据的拷贝。MySQL5.6引入可传输空间的方法:

  1. 执行create table r like t,创建一个相同表结构的空表。
  2. 执行alter table r discard tablespace,此时删除r.ibd文件
  3. 执行flush table t for export,此时db1目录下会生成一个t.cfg文件
  4. db1目录下执行cp t.cfg r.cfg;cp t.ibd,r,ibd;两个命令复制源表的cfg文件和ibd数据。
  5. 执行unlock tables,此时t.cfg文件会被删除,并且释放读锁。
  6. 执行alter table r impory tablespace,将r.ibd文件作为表r新的表空间,由于这个文件的数据内容和t.ibd是相同的,所以表r中就有了和表t相同的数据。

✨如果出现误删表的情况,最快恢复的方法:①利用备份恢复误删之前的数据。②然后再将临时库中的表拷贝到生产库。

# 总结

💣mysqldump:可以通过–where添加可过滤字段,从而可以只导出部分数据。缺点在于不能使用包含join的复杂条件where查询。

💣导出csv:支持导出任意数据,并且支持所有SQL写法。缺点在于只能导出一张表的数据,并且表结构需要另外的语句单独备份。

💣物理拷贝:速度最快。缺点在于①必须是全表拷贝,不能进行筛选备份部分数据。②必须到t1源表的服务器上拷贝数据,执行对应语句和cfg文件。③源表和目标表都是使用InnoDB

编辑 (opens new window)
#数据库
上次更新: 2023/12/15, 15:49:57
误删数据
MySQL面试

← 误删数据 MySQL面试→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式