首页 数据库 MySQL下200GB大表备份,利用传输表空间解决停服发版表备份问题

MySQL下200GB大表备份,利用传输表空间解决停服发版表备份问题

问题背景

在停服发版更新时,需对 200GB 大表(约 200 亿行数据)进行快速备份以预防操作失误。

因为曾经出现过有开发写的发版语句里,UPDATE语句的WHERE条件写错了,原本只需要更新几行数据,最终导致更新了半张表的数据。

MySQL版本是MySQL 8.0.X,为了预防这种情况,需要对某个重要的大表进行预先备份,以便可以及时回滚,及时恢复,及时回退,对于备份方法大概有下面几种:

方案 优点 缺点
mysqldump 导出 简单易用 大表导出耗时(200GB 可能需数小时)
CREATE TABLE...SELECT 直接 SQL 操作 数据复制慢,锁表风险高
表空间 传输 秒级备份 ,零数据复制 需操作系统权限,依赖文件拷贝
主从复制/延迟复制 无需停服,恢复灵活 需主从架构,维护成本高
这个场景的核心需求:停服更新的时间非常有限,比如1个小时之内要完成更新。

操作流程
前面两种都比较简单,通过导数据的方法来备份旧表,万一出现问题,可以使用导出来的数据进行快速恢复,第三种方法估计比较少人用,下面是具体操作方法

源表与备胎表结构

-- 源表(aa)
CREATE TABLE aa (
id int(11) DEFAULT NULL,
sname VARCHAR(100)
) ENGINE=InnoDB;

-- 备胎表(bb)
CREATE TABLE bb (
id int(11) DEFAULT NULL,
sname VARCHAR(100)
) ENGINE=InnoDB;

greatsql> INSERTINTO aa SELECT1,"nihao";
2、查看两个表的表ID和表空间ID,可以看到aa表的表ID是1081 表空间ID是13,bb表的表ID是1082 表空间ID是14

greatsql> select * from information_schema.innodb_tables where name='school/aa'\G
*************************** 1. row ***************************
TABLE_ID: 1081
NAME: school/aa
FLAG: 33
N_COLS: 6
SPACE: 13
ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
INSTANT_COLS: 0
TOTAL_ROW_VERSIONS: 0
1 row in set (0.01 sec)

greatsql> select * from information_schema.innodb_tables where name='school/bb'\G
*************************** 1. row ***************************
TABLE_ID: 1082
NAME: school/bb
FLAG: 33
N_COLS: 6
SPACE: 14
ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
INSTANT_COLS: 0
TOTAL_ROW_VERSIONS: 0
1 row in set (0.00 sec)
3、备胎表卸载表空间:

greatsql> ALTER TABLE bb DISCARD TABLESPACE; -- 加锁并生成配置文件
4、源表执行表空间导出:

greatsql> USE school;
greatsql> FLUSH TABLES aa FOR EXPORT;
5、拷贝表空间文件(ibd和cfg文件),然后重新赋予权限,确保导入表空间时候不会出现问题

$ cd /data/mysql/mysql3306/data/school
$ cp aa.ibd bb.ibd
$ cp aa.cfg bb.cfg
$ chown -R mysql:mysql /data/mysql/mysql3306/data/*
6、在相同数据库下,备胎表导入表空间

greatsql> USE school;
greatsql> UNLOCK TABLES;
greatsql> ALTER TABLE bb IMPORT TABLESPACE;
7、查询表数据,验证数据一致性

greatsql> USE school;
greatsql> SELECT * FROM bb;
greatsql> SELECT * FROM aa;
查询表数据正常,没有任何问题

greatsql> SELECT * FROM aa;
+------+-------+
| id | sname |
+------+-------+
| 1 | nihao |
+------+-------+
1 row in set (0.01 sec)

greatsql> SELECT * FROM bb;
+------+-------+
| id | sname |
+------+-------+
| 1 | nihao |
+------+-------+
1 row in set (0.00 sec)
查看表的数据文件,没什么问题

$ ll
total 228
-rw-r----- 1 mysql mysql 114688 Mar 4 16:51 aa.ibd
-rw-r----- 1 mysql mysql 781 Mar 4 16:52 bb.cfg
-rw-r----- 1 mysql mysql 114688 Mar 4 16:52 bb.ibd

8、再次查看两个表的表ID和表空间ID,可以看到aa表的表ID是1081 表空间ID是13(没有变化),bb表的表ID是1083 表空间ID是14(表空间ID已经变了),bb表的表ID变了是防止与现有表冲突

 

mysql> select * from information_schema.innodb_tables where name='school/aa'\G
*************************** 1. row ***************************
TABLE_ID: 1081
NAME: school/aa
FLAG: 33
N_COLS: 6
SPACE: 13
ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
INSTANT_COLS: 0
TOTAL_ROW_VERSIONS: 0
1 row in set (0.00 sec)


mysql> select * from information_schema.innodb_tables where name='school/bb'\G
*************************** 1. row ***************************
TABLE_ID: 1083
NAME: school/bb
FLAG: 33
N_COLS: 6
SPACE: 14
ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single
INSTANT_COLS: 0
TOTAL_ROW_VERSIONS: 0
1 row in set (0.00 sec)
9、发版更新与回滚

-- 发版操作(示例)
greatsql> UPDATE aa SET sname = 'new_value' WHERE id > 1;
10、如果发版有问题,直接交换表名,最快速度恢复整个表的数据

-- 回滚操作(交换表名)
greatsql> ALTER TABLE aa RENAME TO aa_temp;
greatsql> ALTER TABLE bb RENAME TO aa;
总结
整个操作最重要的是第4步,操作系统级别的拷贝就完成了整个表的备份,相比于数据倒来倒去在速度上要快不少。另外,第5步的备胎表也可以不用导入,只有当发现发版出现问题时候,再导入也可以。

这种方法的关键优势如下

直接拷贝 .ibd 文件,无需逐行复制数据。
零锁表时间:FLUSH TABLES tablename FOR EXPORT 仅短暂加锁(秒级)。
快速恢复:通过表名交换实现秒级回滚。
特别适合于这几种场景:无主从架构的单实例环境、大表快速备份、停服时间敏感。

当然,如果有主从架构的话,则更加推荐使用第四种方法,在操作上也更加可控,短时间也能保证能够完成。

站心网

问题背景在停服发版更新时,需对 200GB 大表(约 200 亿行数据)进行快速备份以预防操作失误。因为曾经出现..

为您推荐

服务器安装数据库MySQL8.0版本,打包导入到MySQL5.6失败的结局方式

最近数据库升级为mysql8.0,在使用过程中发现一些问题,首先mysql8.0有很多新特性,对服务器配置要求较高,所有就考虑把数据库版本切换到MySQL5.6,经过多出测试处理发现在8.0数据库打包的数据导入到5.6总是报错,或..

MySQL查询建表规范

因为之前一直再查找一些比较好的数据库规范,以方便在开发时连接 MySQL 进行查询/建表的时候,能根据规范来执行,达到提高 查询速度 / 执行 SQL 的性能 和提升 MySQL 的整体性能, 这里主要是存放一些比较好的一些数..

必须掌握的MySQL优化指南(2)

4|0表分区MySQL 在 5.1 版引入的分区是一种简单的水平拆分,用户需要在建表的时候加上分区参数,对应用是透明的无需修改代码。对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成,实现分区的代码实..

mysql分表简单介绍

一、Mysql分表的原因1、当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会停在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。2、mysql中有一种机制是表锁定..

MySQL创建用户与授权

一, 创建用户: 命令:CREATE USER'username'@'host' IDENTIFIED BY 'password'; 说明:username - 你将创建的用户名, host - 指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost, ..

必须掌握的MySQL优化指南(1)

1.单表优化除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度。一般以整型值为主的表在千万级以下,字符串为主的表在五百万以下是没有太大问题的。而事实上很多时..

Mysql查询的一些操作(查表名,查字段名,查当月,查一周,查当天)

查询数据库中所有表名select table_name from information_schema.tables where table_schema='tools' and table_type='base table';查询指定数据库中指定表的所有字段名column_nameselect column_n..

MySQL查看、修改字符集及Collation

前言在使用MySQL的过程中,可能会出现初始设计使用的字符集或Collation不符合当前需求的情况。如使用utf8的表(MySQL中的utf8即utf8mb3)要支持emoji,而utf8mb3不支持emoji(emoji需要4个字节,而utf8mb3最长只支持..

MySQL SQL调优之索引

本篇记录MySQL的索引知识学习笔记,也方便自己以后查找复习一、索引的概念MySQL官方给出的索引定义:索引(Index)是帮助MySQL高效获取数据的数据结构。所以说索引就是排好序的快速查找数据结构二、索引分类MySQL的索..

mysql随机获取一条或者多条数据

语句一:select * from users order by rand() LIMIT 1MYSQL手册里面针对RAND()的提示大概意思就是,在 ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描,导致效率相当相当的低,效率不行,切..

Mysql子查询

子查询出现在select语句中的select语句,称为子查询或内查询。外部的select查询语句,称为主查询或外查询。子查询分类按结果集的行列数不同分为4种标量子查询(结果集只有一行一列)列子查询(结果集只有一列多行)..

MySQL批量插入的分析

1、背景我们在工作中基本都会碰到批量插入数据到DB的情况,这个时候我们就需要根据不同的情况选择不同的策略。只要了解sql,就应该知道,向table中插入数据的命令,至少有insert和replace这两种,使用哪一种命令,和..

Mysql查询一段时间内的数据

select * from wap_content where week(created_at) = week(now)如果你要严格要求是某一年的,那可以这样查询一天:select * from table where to_days(column_time) = to_days(now());select * from table where da..

MySQL 5.x和MySQL 8.x数据库的区别

MySQL 是开源关系型数据库的代表,广泛应用于不同规模的 Web 和企业应用中。从 MySQL 5.x 到 MySQL 8.x 的升级带来了大量功能改进和性能提升。为了帮助大家更直观地理解两者的区别,本文将通过详细介绍并结合实际的 ..

宝塔里mysql停止了自动启用脚本

mysql突然停止的原因有多种,这里不列举,可以排查具体原因。如果停止后,还可以手工正常启用mysql,那可以考虑把shell脚本添加到宝塔的计划任务里,定时每隔几分钟检测一次,让mysql自动检测停止后立马启用。ps=`ps..

MySQL如何建数据库

MySQL是一款非常流行的关系型数据库管理系统。无论是在企业还是个人项目中,都经常使用MySQL数据库。在使用MySQL之前,需要先创建一个数据库。本文将介绍如何建立MySQL数据库。一、安装MySQL在开始建立MySQL数据库之..

mysql怎么随机查询数据

MySQL是一种广泛使用的关系型数据库管理系统,在进行数据查询时,随机查询数据是一项很有用的技能。以下是一些方法和技巧,可以帮助你使用MySQL在数据中进行随机查询。方法一:使用RAND()函数进行随机排序RAND()函数..

10个c#基础面试题和答案

以下是10个常见的 C# 基础面试题及其答案:C# 中的值类型和引用类型有什么区别?答案:值类型直接存储数据的值,而引用类型存储对数据的引用。值类型在栈上分配内存,而引用类型在堆上分配内存。什么是命名空间(Nam..

数据库系列:MySQL引擎MyISAM和InnoDB的比较

1 比较和分析MyISAM和InnoDB是两种不同的数据库存储引擎,它们在数据存储结构、事务支持、锁的支持、外键支持、主键观念、性能和优化方式等方面都存在明显的差异。数据存储结构:MyISAM在磁盘上存储了三个文件,包括..

使用docker搭建Nginx + PHP + mysql环境

Nginx+PHP+Mysql是比较常用的网站环境,使用docker布置网站环境也是比较常用的方式,以下就给大家介绍如果使用docker来搭建Nginx+PHP+Mysql的运行环境。前提准备:macOs环境、docker环境(安装docker可以百度,对mac..

发表回复

返回顶部

微信分享

微信分享二维码

扫描二维码分享到微信或朋友圈

链接已复制