MySQL大表直接复制文件的copy方式

本文详细介绍了如何在MySQL中使用InnoDB引擎时,处理单独表空间(innodb_file_per_table=1)的情况,包括备份、迁移数据文件(.ibd和.cfg)、解锁、恢复操作,以及利用binlog进行数据恢复和误操作模拟的过程。

看腻了就来听听视频演示吧:https://www.bilibili.com/video/BV1Bp4y1F7kd/

  • MyISAM引擎可单独将 *.MYD和 *.MYI 拷贝到远程服务器上
  • InnoDB引擎受限于版本(MySQL5.5)无法直接拷贝.ibd文件,因为在ibdata1文件保存有表的字典信息,在ibd文件保存有事务ID和日志序列号,只能用dump方式。

操作步骤:

  • 获取备份表DDL,统计数据集(用于恢复后校样)
  • 锁表,导出表对应的数据字典文件
  • 备份表对应的数据文件和数据字典文件
  • 解锁,恢复表的相关业务操作
  • 在恢复环境上创建该表DDL(测试演练在同一环境故先删表再重建该表)
  • 关闭该表的数据空间,即会删除该表的ibd数据文件
  • 将备份数据文件和数据字典文件copy到对应数据目录下
  • 应用表空间恢复数据并进行恢复后检查
  • 验证恢复的数据集

直接上案例模拟演示:

# MySQL 6+ 可以直接拷贝的前提条件是独立表空间,即innodb_file_per_table=1
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+

# 查看测试表DDL
mysql> show create table t12\G
*************************** 1. row ***************************
       Table: t12
Create Table: CREATE TABLE `t12` (
  `pid` bigint(20) unsigned NOT NULL DEFAULT '0',
  `pname` varchar(20) DEFAULT NULL,
  `project` varchar(20) DEFAULT NULL,
  `tvalue` decimal(5,2) DEFAULT NULL,
  `unit` varchar(8) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
# 查看测试表数据
mysql> select * from t12;
+-----+--------+---------+--------+------+
| pid | pname  | project | tvalue | unit |
+-----+--------+---------+--------+------+
|   1 | 王五   | 身高    | 172.34 | cm   |
|   2 | 王五   | 体重    |  69.52 | kg   |
|   3 | 王五   | 年龄    |  22.00 | 岁   |
|   4 | 赵六   | 身高    | 170.52 | cm   |
|   5 | 赵六   | 体重    |  80.52 | kg   |
|   6 | 赵六   | 年龄    |  26.00 | 岁   |
+-----+--------+---------+--------+------+
6 rows in set (0.00 sec)

# 表加全局读锁,即把.cfg数据字典文件导出到磁盘上
mysql> flush tables t12 for export;
Query OK, 0 rows affected (0.00 sec)

# 拷贝数据目录对应库名下的 t12.ibd 和 t12.cfg文件,然后修改属性
[root@db01 mdb]# mkdir /tmp/mysql_back
[root@db01 mdb]# ll t12.*
-rw-r----- 1 mysql mysql   585 Sep  2 16:16 t12.cfg
-rw-r----- 1 mysql mysql  8690 Sep  2 16:11 t12.frm
-rw-r----- 1 mysql mysql 98304 Sep  2 16:11 t12.ibd
[root@db01 mdb]# cp t12.ibd /tmp/mysql_back
[root@db01 mdb]# cp t12.cfg /tmp/mysql_back
[root@db01 mdb]# chown -R mysql.mysql /tmp/mysql_back/t12.*
[root@db01 mdb]# ll /tmp/mysql_back/t12.*
-rw-r----- 1 mysql mysql   585 Sep  2 16:18 /tmp/mysql_back/t12.cfg
-rw-r----- 1 mysql mysql 98304 Sep  2 16:18 /tmp/mysql_back/t12.ibd

# 解锁,模拟删表
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> drop table t12;
Query OK, 0 rows affected (0.00 sec)
# 创建原表结构
mysql> CREATE TABLE `t12` (
    ->   `pid` bigint(20) unsigned NOT NULL DEFAULT '0',
    ->   `pname` varchar(20) DEFAULT NULL,
    ->   `project` varchar(20) DEFAULT NULL,
    ->   `tvalue` decimal(5,2) DEFAULT NULL,
    ->   `unit` varchar(8) DEFAULT NULL
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

# 关闭表的数据空间并会删除其数据文件t12.ibd
mysql> alter table t12 discard tablespace;
Query OK, 0 rows affected (0.01 sec)

# 再把备份的t12.ibd 和 t12.cfg文件拷贝过来
[root@db01 mdb]# mv /tmp/mysql_back/t12.cfg .
[root@db01 mdb]# mv /tmp/mysql_back/t12.ibd .
[root@db01 mdb]# ll t12.*
-rw-r----- 1 mysql mysql   585 Sep  2 16:18 t12.cfg
-rw-r----- 1 mysql mysql  8690 Sep  2 16:26 t12.frm
-rw-r----- 1 mysql mysql 98304 Sep  2 16:18 t12.ibd

# 应用表空间恢复数据并进行恢复后检查
mysql> alter table t12 import tablespace;
Query OK, 0 rows affected (0.01 sec)
mysql> check table t12;
+---------+-------+----------+----------+
| Table   | Op    | Msg_type | Msg_text |
+---------+-------+----------+----------+
| mdb.t12 | check | status   | OK       |
+---------+-------+----------+----------+
1 row in set (0.00 sec)

# 验证数据是否恢复回来
mysql> select * from t12;
+-----+--------+---------+--------+------+
| pid | pname  | project | tvalue | unit |
+-----+--------+---------+--------+------+
|   1 | 王五   | 身高    | 172.34 | cm   |
|   2 | 王五   | 体重    |  69.52 | kg   |
|   3 | 王五   | 年龄    |  22.00 | 岁   |
|   4 | 赵六   | 身高    | 170.52 | cm   |
|   5 | 赵六   | 体重    |  80.52 | kg   |
|   6 | 赵六   | 年龄    |  26.00 | 岁   |
+-----+--------+---------+--------+------+
6 rows in set (0.00 sec)

MySQL的binlog系列和奇技操作:

先来聊聊MySQL的binlog文件解析
接着说说mysqlbinlog解析工具如何做数据恢复
再来谈谈如何从binlog文件恢复误update的数据,模拟Oracle的闪回功能
接着聊聊如何从binlog文件恢复误delete的数据,模拟Oracle的闪回功能
借用binlog2sql工具轻松解析MySQL的binlog文件,再现Oracle的闪回功能
再来介绍另一个binlog文件解析的第三方工具my2sql
顺带来聊聊MySQL误删ibdata数据文件的恢复
MySQL大表直接复制文件的copy方式

<think>首先,用户的问题是:“我想查找copy操作时的锁方式 请问copy操作的锁方式”。用户提到了“copy操作”,这可能涉及到MySQL中的数据库操作,特别是复制或数据迁移。 从引用中,我可以提取相关信息: - 引用[1]: 讨论死锁时,提到innodb_trx、data_locks、innodb_lock_waits等有数据。 - 引用[2]: 解释了不同参数组合的锁定行为,比如ALGORITHM=COPY LOCK=EXCLUSIVE会导致锁,适用小迁移需停服;ALGORITHM=INPLACE LOCK=NONE理想情况下允许读写并发;LOCK=SHARED允许读禁止写适用读多写少场景。 - 引用[3]: 给出了一个实例分析,复制粘贴错误导致连续锁死,涉及到write_lock_bh的锁操作。 - 引用[4]: 提到mysql解决命令,涉及批量操作和临时文件。 - 引用[5]: 讨论MyISAM和InnoDB引擎的拷贝方式,InnoDB不能用直接拷贝文件方式。 用户特别询问“copy操作时的锁方式”,结合引用[2],ALGORITHM=COPY通常涉及到重构,会使用锁。 关键点从引用[2]: - ALGORITHM=COPY LOCK=EXCLUSIVE:锁方式为排他锁(EXCLUSIVE LOCK),这会阻止所有读写操作,适用小迁移需停服。 在MySQL中,COPY算法通常在ALTER TABLE操作中使用,当修改结构时,如果使用COPY算法,MySQL会创建一个新复制数据,然后重命名。这期间会锁。 所以,对于“copy操作时的锁方式”,很可能是指使用COPY算法时的锁行为。 可能的操作包括: - 执行ALTER TABLE ... ALGORITHM=COPY,这会触发重构。 - 或者在数据迁移中使用类似命令。 锁方式: - 当使用ALGORITHM=COPY时,通常需要锁定以防止并发修改。锁类型通常是排他锁(EXCLUSIVE LOCK),这意味着在操作期间,被锁定,不允许任何读写操作。 从引用[2]: - ALGORITHM=COPY LOCK=EXCLUSIVE:锁定行为为排他锁。 用户提到“copy操作”,可能泛指数据复制操作,如复制结构或数据。 在MySQL中,复制方式包括: - CREATE TABLE new_table AS SELECT * FROM old_table; 这会锁吗?取决于引擎和事务隔离级别。 通常,对于InnoDB,SELECT操作可能用共享锁,但写入操作会锁。 在COPY算法中,锁是明确的。 所以,回答应聚焦于使用COPY算法时的锁行为。 回答结构: - 解释什么是COPY操作。 - 描述锁方式。 - 参考提供的引用。 系统指令要求: - 使用中文回答。 - 结构清晰。 - 添加引用标识。 - 生成相关问题。 先回答问题: “copy操作”在MySQL中,通常指使用ALGORITHM=COPY操作,如ALTER TABLE。锁方式是排他锁(EXCLUSIVE LOCK),会阻止所有并发读写操作,直到操作完成。这适用于需要停服的场景。 从引用[2]: ALGORITHM=COPY LOCK=EXCLUSIVE小迁移,需停服 [^2]。 也提到其他锁方式,但用户问COPY操作。 在引用[4]中,也提到批量操作可能涉及锁。 引用[3]有锁错误,但相关。 确保回答真实可靠。 最终回答提纲: 1. 解释COPY操作:在MySQL中,COPY操作通常指使用COPY算法进行重构或数据复制,例如在ALTER TABLE语句中指定ALGORITHM=COPY。 2. 锁方式:当使用COPY算法时,MySQL会获取排他锁(EXCLUSIVE LOCK),这会导致被完全锁定,不允许任何读写操作。这意味着在操作期间不可用,所有并发访问都会被阻塞。 3. 适用场景:适用于小迁移或修改,需要停机维护的场景。 4. 引用支持:基于引用[2]。 5. 其他考虑:避免复制粘贴错误导致死锁,如引用[3]所示。 6. 生成相关问题。 </think>### COPY操作的锁方式MySQL中,“COPY操作”通常指在执行特定命令(如`ALTER TABLE`指定`ALGORITHM=COPY`或数据迁移命令)时,使用COPY算法重构复制数据的过程。这类操作涉及物理复制数据到新结构,因此需要锁定以防止并发数据不一致。以下是详细解释: #### 1. **COPY操作的锁机制** - **锁类型:排他锁(EXCLUSIVE LOCK)** 当使用`ALGORITHM=COPY`时(例如`ALTER TABLE table_name ALGORITHM=COPY`),MySQL会获取的排他锁。排他锁会阻塞所有读写操作(包括`SELECT`, `INSERT`, `UPDATE`, `DELETE`),直到COPY操作完成。这本质上是将置于“只维护”状态,不允许任何并发访问。 - 例如:在迁移小或修改结构时,COPY算法会创建一个新副本,复制数据到新,再重命名替换原。整个过程全程持有排他锁[^2]。 - **锁现**: - 会话执行COPY操作期间,其他会话尝试访问该会被阻塞(显示为`Waiting for table metadata lock`状态)。 - 可以通过查询`information_schema.innodb_trx`、`data_locks`等系统观察锁状态(例如检查`lock_mode=X`示排他锁)[^1]。 #### 2. **COPY操作的典型场景与参数示例** - **参数组合**:`ALGORITHM=COPY`通常与`LOCK=EXCLUSIVE`绑定使用: - `LOCK=EXCLUSIVE`: 强制排他锁,确保操作期间无并发干扰。 - 适用场景:小迁移或结构修改,需停机维护(停服),因为高并发环境下长时锁会导致服务中断[^2]。 - 示例命令: ```sql ALTER TABLE orders ALGORITHM=COPY, LOCK=EXCLUSIVE; -- 或隐式使用COPY算法的操作,如某些旧版本MySQL的OPTIMIZE TABLE ``` - **与其他锁方式的对比**: - `ALGORITHM=INPLACE LOCK=NONE`:理想情况,无锁或轻量锁,允许读写并发(适合在线操作)。 - `LOCK=SHARED`:共享锁,允许读但禁止写(适合读多写少场景)。 - COPY操作的排他锁是最严格的,牺牲并发性保证数据一致性[^2]。 #### 3. **潜在风险与优化建议** - **风险**: - **长时锁**:COPY操作涉及全数据复制,对耗时久,可能引起服务阻塞或超时。 - **死锁风险**:编程错误(如复制粘贴导致重复加锁,如引用[3]中的`write_lock_bh`未解锁)可能引发连续死锁(hang)。 - **引擎限制**:InnoDB引擎无法直接拷贝文件(如.ibd),需用SQL命令执行COPY操作,而MyISAM支持文件级拷贝[^5]。 - **优化建议**: - **避免直接COPY**:对优先使用`ALGORITHM=INPLACE`减少锁冲突。 - **分批操作**:通过`SELECT ... INTO OUTFILE`导出数据到临时文件,再分批次`LOAD DATA`导入,减少单次锁时长[^4]。 - **监控锁状态**:使用命令`SHOW OPEN TABLES`或查询`data_locks`实时检测锁争用。 #### 4. **总结** COPY操作的锁方式是排他锁(EXCLUSIVE LOCK),适用于需强一致性的小操作,但需停机维护。实际应用中,应评估小和并发需求,优先选择更轻量的INPLACE算法以避免服务中断[^2][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值