前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >xtrabackup 备份还原mysql

xtrabackup 备份还原mysql

原创
作者头像
xmlgrg
发布2023-11-29 09:50:52
3060
发布2023-11-29 09:50:52
举报
文章被收录于专栏:网管运维

有一个项目要从云上整体迁移到公司机房内,里面有mysql5.6.20,这个mysql没做过备份,也没主从,然后打算通过xtrabackup先做个全备,然后再做个主从(因为在迁移的阶段,云上服务器还会有新的数据生成,主从是为了确保迁移的数据完整)

一、安装mysql5.6.20

在新机器上部署mysql5.6.20,需确保和之前的mysql版本一致

my.cnf也要基本一致

二、xtrabackup的安装

代码语言:javascript
复制

# 先安装需要的rpm包。在安装 xtrabackup
rpm -Uvh --force --nodeps --replacepkgs  *.rpm  
# 安装的版本比较旧,为了迎合 mysql5.6.20
yum localinstall percona-xtrabackup-2.2.12-1.el7.x86_64.rpm

验证是否安装成功:输入命令innob,按tab键,若自动补全innobackupex ,则说明安装成功。
验证是否安装成功:输入命令qp,按tab键,若自动补全qpress,则说明安装成功。
验证是否安装成功:输入命令pt-online,按tab键,若自动补全pt-online-schema-change,则说明安装成功。
输入pig,按tab键能自动补全pigz则说明安装成功!

创建备份目录:
mkdir -pv /devbdata//mysql_backup/xbstream_no_month_tables/full

数据库数据准备

代码语言:javascript
复制
###### mysql 创建库,并生成 记录
mysql -uroot -p'P@SSw0rdnqt123' -h 127.0.0.1
#######################  多创建几个库
CREATE DATABASE tdata;
use tdata;
#建测试表
drop table if exists t;
CREATE TABLE t (
                id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '自增主键', 
                dept tinyint not null comment '部门id',
                age tinyint not null comment '年龄',
                name varchar(30) comment '用户名称',
                create_time datetime not null comment '注册时间', 
                last_login_time datetime comment '最后登录时间'
               ) comment '测试表';
 
#手工插入第一条测试数据,后面数据会根据这条数据作为基础生成
insert into t values(1,1, 25, 'user_1', '2018-01-01 00:00:00', '2018-03-01 12:00:00');
#初始化序列变量
set @i=1;
 
#==================此处拷贝反复执行,直接符合预想的数据量===================
#执行20次即2的20次方=1048576 条记录
#执行23次即2的23次方=8388608 条记录
#执行24次即2的24次方=16777216 条记录
# 执行的时候,记得 把后面的 #注释 去掉,不然会执行有问题
insert into t(dept, age, name, create_time, last_login_time) 
select left(rand()*10,1) as dept,               #随机生成1~10的整数
       FLOOR(20+RAND() *(50 - 20 + 1)) as age,  #随机生成20~50的整数
        concat('user_',@i:=@i+1),               #按序列生成不同的name
        date_add(create_time,interval +@i*cast(rand()*100 as signed) SECOND), #生成有时间大顺序随机注册时间
        date_add(date_add(create_time,interval +@i*cast(rand()*100 as signed) SECOND), interval + cast(rand()*1000000 as signed) SECOND) #生成有时间大顺序的随机的最后登录时间
from t;
select count(1) from t;
#==================此处结束反复执行========================================
# 检查一下
select * from t limit 10;
 
 
#创建索引(视情况执行)
create index idx_dept on t(dept);
create index idx_create_time on t(create_time);
create index idx_last_login_time on t(last_login_time);

数据备份

代码语言:javascript
复制
nohup innobackupex --no-timestamp --user=root --password='P@SSw0rdnqt123' --host=192.168.56.111 --port=3306  --stream=xbstream --compress --extra-lsndir=/devbdata/mysql_backup/xbstream_no_month_tables/full /devbdata/mysql_backup/xbstream_no_month_tables/full 1> /devbdata/mysql_backup/xbstream_no_month_tables/xbstream_log 2>&1 >/devbdata/mysql_backup/xbstream_no_month_tables/full/full.xbstream  &

上面参数的说明:

代码语言:javascript
复制
--user=     #指定数据库备份用户
--password=  #指定数据库备份用户密码
--port=     #指定数据库端口
--host=     #指定备份主机
--socket=    #指定socket文件路径
--databases=  #备份指定数据库,多个空格隔开,如–databases=”dbname1 dbname2″,不加备份所有库
--defaults-file=       #指定my.cnf配置文件
--apply-log         #日志回滚
--incremental=          #增量备份,后跟增量备份路径
--incremental-basedir=     #增量备份,指上次增量备份路径
--redo-only         #合并全备和增量备份数据文件
--copy-back         #将备份数据复制到数据库,数据库目录要为空
--move-back   #这个选项与--copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同时保留数据文件和Backup副本
--no-timestamp          #生成备份文件不以时间戳为目录名
--stream=             #指定流的格式做备份,–stream=tar,将备份文件归档
--remote-host=user@ip DST_DIR #备份到远程主机

查看备份日志

代码语言:javascript
复制
# cat /devbdata/mysql_backup/xbstream_no_month_tables/xbstream_log

innobackupex: Backup created in directory '/devbdata/mysql_backup/xbstream_no_month_tables/full'
                       会记录二进制文件的位置,方便后期做主从
innobackupex: MySQL binlog position: filename 'mysql-bin.000003', position 62586
231110 10:43:49  innobackupex: Connection to database server closed
231110 10:43:49  innobackupex: completed OK!

库的表结构备份

代码语言:javascript
复制
cd /devbdata/mysql_backup/
mysqldump -h127.0.0.1 -uroot  -p'P@SSw0rdnqt123'   -B -R -E --triggers -d  tdata > tdata.sql
mysqldump -h127.0.0.1 -uroot  -p'P@SSw0rdnqt123'   -B -R -E --triggers -d  tdatabak > tdatabak.sql

上面参数的说明;

代码语言:javascript
复制
**********  确保数据库该有的 存储过程、函数、触发器、事件、视图 都被导出,可使用 SQLyog软件,不要导出 数据即可

mysqldump -h127.0.0.1 -uroot  -proot@123 -P5320 -B -R -E --triggers -d  数据库名 > ad.sql
总结一下:
-d 结构(–no-data:不导出任何数据,只导出数据库表结构)
-t 数据(–no-create-info:只导出数据,而不添加CREATE TABLE 语句)
-n (–no-create-db:只导出数据,而不添加CREATE DATABASE 语句)
-R (–routines:导出存储过程以及自定义函数)
-E (–events:导出事件)
–triggers (默认导出触发器,使用–skip-triggers屏蔽导出)
-B (–databases:导出数据库列表,单个库时可省略)

–tables 表列表(单个表时可省略)
①同时导出结构以及数据时可同时省略-d和-t
②同时 不 导出结构和数据可使用-ntd
③只导出存储过程和函数可使用-R -ntd
④导出所有(结构&数据&存储过程&函数&事件&触发器)使用-R -E(相当于①,省略了-d -t;触发器默认导出)
⑤只导出结构&函数&事件&触发器使用 -R -E -d

模拟删除数据库

代码语言:javascript
复制

mysql -uroot -p'P@SSw0rdnqt123' -h 127.0.0.1
drop database tdata;
drop database tdatabak;

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

mysql>

三、数据恢复

先还原表结构

代码语言:javascript
复制
mysql -uroot -p'P@SSw0rdnqt123' -h 127.0.0.1

mysql> source /devbdata/mysql_backup/tdata.sql;
mysql> source /devbdata/mysql_backup/tdatabak.sql;
mysql>  show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| tdata              |
| tdatabak           |
| test               |
+--------------------+
6 rows in set (0.00 sec)

mysql>

# 检查一下
mysql> select * from tdata.t limit 10;
Empty set (0.00 sec)

mysql>

解压备份的文件 full.xbstream

代码语言:javascript
复制
===== 解压 脚本 /devbdata/mysql_backup/xbstream_decompression.sh ===============
#!/bin/sh
#对备份的文件,进行解压
#source ~/.cshrc
source /etc/profile

export PATH=$PATH:/bin:/usr/bin:/usr/local/bin

BEGINTIME=`date +"%Y-%m-%d %H:%M:%S"`
format_time=`date +"%Y-%m-%d_%H:%M:%S"`

# 存放备份文件的绝对路径 ;在full 层级目录前
backdir=/devbdata/mysql_backup/xbstream_no_month_tables
# 日志目录
out_log=$backdir/xbstream_recovery_log_$format_time

# 创建一个用于存放解压文件的 目录
if [ ! -d "${backdir}/full/Unzip" ]; then
    mkdir ${backdir}/full/Unzip
fi
# 第一次解压,至指定的目录,解压后的文件后缀名为 .qp
xbstream -x < ${backdir}/full/full.xbstream -C ${backdir}/full/Unzip
cd ${backdir}/full/Unzip
for f in `find ./ -iname "*\.qp"`;
do
    echo "qpress ${f}"
    # 第二次 使用 qpress 解压
    qpress -d ${f} $(dirname ${f}) && rm -rf ${f};
done

# 把 备份的时候 数据库 增量的数据 写入到 对应库的 文件里
innobackupex --apply-log --redo-only --use-memory=1G $backdir/full/Unzip 1>>$out_log 2>&1
innobackupex --apply-log --export $backdir/full/Unzip 1>>$out_log 2>&1

========================================================
执行解压 脚本
nohup sh +x /devbdata/mysql_backup/xbstream_decompression.sh &
# tail -f nohup.out
执行的时候,如果开着 终端,qpress 解压的时候 ,可能会一直在终端 打印 输出信息

需要另外打开一个终端界面,在操作其他命令 


解压后的文件目录
/devbdata/mysql_backup/xbstream_no_month_tables/full/Unzip/

恢复数据库

按照单库恢复;脚本

代码语言:javascript
复制

===================== /devbdata/mysql_backup/xbstream_recovery.sh =====================
#!/bin/sh
#恢复
#source ~/.cshrc
source /etc/profile

export PATH=$PATH:/bin:/usr/bin:/usr/local/bin

BEGINTIME=`date +"%Y-%m-%d %H:%M:%S"`
format_time=`date +"%Y-%m-%d_%H:%M:%S"`
# 存放解压后库文件的目录 ,full 层级目录 前
backdir=/devbdata/mysql_backup/xbstream_no_month_tables
out_log=$backdir/xbstream_recovery_log_$format_time
# 新数据库的存储 路径
datadir=/devbdata/.data/mysql
#MySQL数据库用户名
MyUSER=root
#MySQL数据库密码
MyPASS=P@SSw0rdnqt123
#ip地址
MyHOST=localhost
#MySQL数据库端口号
PORT=3306
#恢复数据库名,一次只能恢复一个库,需要手动修改这个库名
# `tdata` `tdatabak`
DBNAME=XXX

# 表名 为all ,表示 当前库中的 所有表
tableName=all


if [ -d "$backdir/full" ];then

  cd $backdir/full/Unzip/$DBNAME
  echo "#####start alter ${recovery_tables} discard tablespace"

  if [ "${tableName}" = "all" ]; then
     recovery_tables=`find ./ -name "*\.frm"`
  else
     recovery_tables=${tableName}
  fi

  for f in $recovery_tables
  do
     file_name=${f##*/}
     table=${file_name%.*}

      # 分区表  特殊处理、判断当前库 中 是否 含有分区表
     if [ -f "${table}.par" ]; then
        parName=`find ./ -name "${table}#P#p*.ibd"`

        if [ ! -f "${backdir}/table_sql_info.txt" ]; then
           touch ${backdir}/table_sql_info.txt
        else
           rm -rf ${backdir}/table_sql_info.txt
           touch ${backdir}/table_sql_info.txt
        fi

        mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "SHOW CREATE TABLE ${table}" >> ${backdir}/table_sql_info.txt

        sql=`cat ${backdir}/table_sql_info.txt`
        table_sql_temp=${sql#${table}}
        table_sql=${table_sql_temp%%ENGINE*}

        for p in ${parName}
        do
            parFileName=${p##*#P#}
            parTableName=${parFileName%.*}
            echo "this recovery table "
            echo "#####create temporary table ${table}_${parTableName} ."
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "${table_sql/${table}/${table}_${parTableName}}" 1>>$out_log 2>&1

            echo ">>>>finins create temporary table ${table}_${parTableName}."

            echo "#####${table}_${parTableName} start discard tablespace"
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "ALTER TABLE ${table}_${parTableName} DISCARD TABLESPACE" 1>>$out_log 2>&1
            echo ">>>>finish ${table%_*}_${parTableName} discard tablespace"
            #  .exp/.ibd/.cfg  都是解压后生成的 文件
            echo "#####start copy $table ${parTableName} .exp/.ibd/.cfg file to $datadir"
            cp ${table}\#P\#${parTableName}.ibd ${datadir}/${DBNAME}/${table}_${parTableName}.ibd
            cp ${table}\#P\#${parTableName}.exp ${datadir}/${DBNAME}/${table}_${parTableName}.exp
            cp ${table}\#P\#${parTableName}.cfg ${datadir}/${DBNAME}/${table}_${parTableName}.cfg
            chown -R mysql:mysql ${datadir}/${DBNAME}
            echo ">>>>finish copy $table ${parTableName} .exp/.ibd/.cfg file to $datadir"

            echo "#####${table}_${parTableName} start import tablespace"
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "ALTER TABLE ${table}_${parTableName} IMPORT TABLESPACE" 1>>$out_log 2>&1
            echo ">>>>finish ${table}_${parTableName} import tablespace"

            echo "start exchange partition ${table} ${parTableName}"
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "ALTER TABLE ${table} exchange PARTITION ${parTableName} with table ${table}_${parTableName}" 1>>$out_log 2>&1
            # 处理掺杂的 数据
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "INSERT INTO ${table} SELECT * FROM ${table}_${parTableName}" 1>>${out_log} 2>&1
            echo ">>>>finish exchange partition ${table} ${parTableName}"

            echo "#####start remove ${table}_${parTableName} .exp file"
            rm -rf $datadir/$DBNAME/${table}_${parTableName}*.exp
            echo ">>>>finish remove ${table}_${parTableName} .exp file"

            echo "####start remove ${table}_${parTableName} table"
            mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "DROP TABLE ${table}_${parTableName}" 1>>${out_log} 2>&1
            rm -rf $datadir/$DBNAME/${table}_${parTableName}.cfg
            echo ">>>>finish remove ${table}_${parTableName} table"
        done
     else
        echo ">>>>$table start discard tablespace"
        mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "ALTER TABLE $table DISCARD TABLESPACE" 1>>$out_log 2>&1
        echo ">>>>finish $table discard tablespace"

        echo "#####start copy $table .exp/.ibd file to $datadir"
        cp $table.ibd $table.exp $table.cfg  $datadir/$DBNAME
        chown -R mysql:mysql $datadir/$DBNAME
        echo "#####finish copy $table .exp/.ibd file to $datadir"

        echo "$table start import tablespace"
        mysql -u $MyUSER -h $MyHOST -P $PORT -p$MyPASS $DBNAME -Bse "ALTER TABLE $table IMPORT TABLESPACE" 1>>$out_log 2>&1
        echo ">>>>finish $table import tablespace"
        echo "#####start remove $table .exp file"
        rm -rf $datadir/$DBNAME/$table*.exp
        rm -rf $datadir/$DBNAME/$table*.cfg
        echo ">>>>finish remove $table .exp file"
     fi
  done
fi
   echo "#####recovery data success !!!!!"


===================== 恢复脚本 =====================

nohup  sh +x   /devbdata/mysql_backup/xbstream_recovery.sh &
tail -f nohup.out
代码语言:javascript
复制
注意:
1、数据存储引擎 类型为 MyISAM 的需要手动导入(手动从原来的数据库中 导出,然后在新库中 导入)
报错信息:cp: 无法获取"tdata.ibd" 的文件状态(stat): 没有那个文件或目录
然后去解压该库的目录下,去查看 ,是否有 MYD结尾的文件、如果有 、那就说明 显示这个表 需要手动 导入
(tdata 库名)
 # ll -h /devbdata/mysql_backup/xbstream_no_month_tables/full/Unzip/tdata/*.MYD


2、视图的会报错、等库恢复后,需要手动去确认下视图是否正常导入
报错信息:cp: 无法获取"tdata.ibd" 的文件状态(stat): 没有那个文件或目录



###!!~  特别注意
数据恢复成功后,需要手动给数据库中的每一张表 做元数据(索引) 重构
mysql -uroot -p'P@SSw0rdnqt123' -h 127.0.0.1
ALTER TABLE tdata.t ENGINE = INNODB;   // 同一个数据库里,可能 有多种存储引擎,不同的表

*** ALTER TABLE 库名.表名 ENGINE = INNODB;    // INNODB 表的存储引擎
*** ALTER TABLE 库名.表名 ENGINE = MyISAM;     // MyISAM 表的存储引擎


查看恢复情况
select * from tdata.t limit 10;


如果要做主从,可以从 xbstream_log 问价里获取 需要 的 二进制文件 信息
做主从的时候需要注意,如果主库里有定时任务,记得在 从库中全局关闭 定时任务

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档