阿里云RDS备份数据恢复

公司使用的阿里云的RDS,设置的备份策略是每天凌晨3点进行全量备份。

备份文件都在阿里云上面,内网没有做任何备份。

自从携程事件出现后,我觉得公司内网也要做下数据库备份。

程序代码都在内网svn服务器,所以线上即使全删除了,也没有关系。


数据库备份,本来考虑是导出sql文件,发现单独一个千万数据表,导出sql文件大小有12G。

要是全部数据库导出,数据太庞大了。


后来发现阿里云的RDS全量备份文件,只有9G左右。所以将备份文件下载到内网,然后恢复出来就可以了。下载链接是动态链接,每次需要手动下载,比较麻烦。如果需要自动下载,需要自己开发api程序,这个暂时还没有开发好。

所以就写了个下载脚本wget.sh

#!/bin/bash


base_url='Http://rdsbak-hzf.oss-cn-hangzhou-f.aliyuncs.com/custins287919/hins550127_xtra_20150608030426.tar.gz?OSSAccessKeyId=c9gzsqpauj3dufdfdfd45hwdvafdf&Expires=143381fdfew388&Signature=1lRg61cJfdafQ%2FXbbD3rwfsdfdas%3D'

base_file=`echo $base_url | cut -d "?" -f 1 | cut -d "/" -f 5`


express_url='Http://rdsbak-hzf.oss-cn-hangzhou-f.aliyuncs.com/custins287919/hins550127_xtra_20150608030452.tar.gz?OSSAccessKeyId=c9gzsqpau54fd4f5fdsahwdvafdf&Expires=143384515fd388&Signature=1lRg61cJfdafQ%2FXbbDIfdsaffdas%3D'

express_file=`echo $base_url | cut -d "?" -f 1 | cut -d "/" -f 5`


log_url='Http://rdsbak-hzf.oss-cn-hangzhou-f.aliyuncs.com/custins287919/hins550127_xtra_20150608030435.tar.gz?OSSAccessKeyId=c9gzsqpauj4f5d1f2dsvafdf&Expires=14338fdfsda388&Signature=1lRg61cJfdafQ%2FXbbDIfdsafdas%3D'

log_file=`echo $base_url | cut -d "?" -f 1 | cut -d "/" -f 5`



cd /backup/db_base

echo `date +%Y-%m-%d' '%H:%M:%S`  base开始下载 >> /opt/base.log

wget -c ""$base_url"" -O $base_file

sleep 1

echo `date +%Y-%m-%d' '%H:%M:%S`  base下载完成 >> /opt/base.log


cd /backup/db_express

echo `date +%Y-%m-%d' '%H:%M:%S`  express开始下载 >> /opt/express.log

wget -c ""$express_url"" -O $express_file

sleep 1

echo `date +%Y-%m-%d' '%H:%M:%S`  express下载完成 >> /opt/express.log


cd /backup/db_log

echo `date +%Y-%m-%d' '%H:%M:%S`  log开始下载 >> /opt/log.log

wget -c ""$log_url"" -O $log_file

sleep 1

echo `date +%Y-%m-%d' '%H:%M:%S`  log下载完成 >> /opt/log.log



每次下班后,把下载链接更新下。然后调用任务计划执行。

01 22 14 8 * /opt/wget.sh &


线上用的是RDS mysql 5.6,版本是5.6.16

所以内网安装了一台mysql服务器,版本是mysql 5.6.16

方法如下:

yum -y install ncurses-devel cmake

创建用户和用户组

groupadd mysql

useradd -g mysql mysql

usermod -s /sbin/nologin mysql

创建目录

mkdir -p /data/3306/data /data/3306/logs

解压编译

tar zxvf mysql-5.6.16.tar.gz -C /usr/src

cd /usr/src/mysql-5.6.16

cmake  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \

-DMYSQL_DATADIR=/data/3306/data \

-DMYSQL_TCP_PORT=3306 \

-DMYSQL_UNIX_ADDR=/data/3306/mysqld.sock \

-DDEFAULT_CHARSET=utf8 \

-DDEFAULT_COLLATION=utf8_general_ci \

-DWITH_EXTRA_CHARSETS=all \

-DWITH_MYISAM_STORAGE_ENGINE=1 \

-DWITH_INNOBASE_STORAGE_ENGINE=1 \

-DENABLED_LOCAL_INFILE=1 \

-DEXTRA_CHARSETS=all \

-DWITH_EMBEDDED_SERVER=1 \

-DWITH_SSL=bundled \

-DWITH_DEBUG=0 \

-DENABLE_DOWNLOADS=1

安装

make

make install

初始化

/usr/local/mysql/scripts/mysql_install_db \

--basedir=/usr/local/mysql \

--datadir=/data/3306/data \

--user=mysql

编辑配置文件

cd /usr/local/mysql

cp my.cnf my.cnf.bak

vi my.cnf

 skip-name-resolve

 basedir = /usr/local/mysql

 datadir = /data/3306/data

 port = 3306

 server_id = 2

 socket = /data/3306/mysqld.sock

 pid-file = /data/3306/mysql.pid

 max_allowed_packet=16M

 log-error = /data/3306/logs/error.log

设置启动脚本,增加到开机自启动

chown mysql:mysql -R /data/3306

cp /usr/src/mysql-5.6.16/support-files/mysql.server /etc/init.d/mysqld

chmod +x /etc/init.d/mysqld

chkconfig --add mysqld

chkconfig --level 2345 mysqld on

编辑环境变量

vi /etc/profile

最后一行添加

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

启动mysql

source /etc/profile

/etc/init.d/mysqld start


增加授权用户

mysql -u root -p

grant all PRIVILEGES on *.* to xx@'%' identified by 'xx123';

flush privileges;

exit;


安装XtraBackup

由于RDS是使用XtraBackup,所以服务器必须安装,注意版本和阿里云的一样,是XtraBackup-2.2.9

安装组件

yum -y  install perl-Time-HiRes libaio* openssl*

yum clean all

安装xtrabackup

tar zxvf percona-xtrabackup-2.2.9-5067-Linux-x86_64.tar.gz -C /usr/src/

mv /usr/src/percona-xtrabackup-2.2.9-Linux-x86_64 /usr/local/xtrabackup

添加环境变量

vi /etc/profile

最后一行添加

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


source /etc/profile

查看版本

xtrabackup -v

添加文件链接

ln -s /usr/local/xtrabackup/bin/innobackupex /usr/bin/innobackupex

ln -s /usr/local/xtrabackup/bin/xtrabackup /usr/bin/xtrabackup

ln -s /usr/local/xtrabackup/bin/xbcrypt /usr/bin/xbcrypt

ln -s /usr/local/xtrabackup/bin/xbstream /usr/bin/xbstream


下载解压备份脚本(针对RDS备份文件)

wget http://oss.aliyuncs.com/aliyunecs/rds_backup_extract.sh?

chmod 755 rds_backup_extract.sh


创建目录(因为base数据库较大,所以目录必须是/home/mysql/data,恢复速度比较快。之前用的是/data/3309/data,恢复速度比蜗牛还慢,进程容易死掉。)

mkdir -p /home/mysql/data /home/mysql/logs

mkdir -p /data/3310/data /data/3310/logs

mkdir -p /data/3311/data /data/3311/logs

创建备份文件下载目录

mkdir -p /backup/db_base

mkdir -p /backup/db_express

mkdir -p /backup/db_log


解压备份

/root/rds_backup_extract.sh -f /backup/db_base/hins550356_xtra_20150805050632.tar.gz -C /home/mysql/data


恢复数据

innobackupex --defaults-file=/home/mysql/data/backup-my.cnf --apply-log /home/mysql/data

最后一行出现"innobackupex: completed OK!"就说明成功了

因为备份文件有30多个G,恢复花了2个小时。

编辑配置文件

vi /home/mysql/my.cnf


[mysqld]

 basedir = /usr/local/mysql

 datadir = /home/mysql/data

 port = 3309

 server_id = 3

 socket = /home/mysql/mysqld.sock

 max_allowed_packet=500M

 log-error = /home/mysql/logs/error.log

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

skip-name-resolve

wait_timeout=86400

interactive_timeout=86400

net_read_timeout=1000

myisam-recover=backup,force

#innodb_force_recovery=4


备注:

因为测试的备份集有坏页,所以需要启动表修复,否则有坏页的数据库表无法打开。

navicat提示2013-lost connection to MySQL server during query

启动表修复之后,表就可以打开了

mysql error日志提示

[ERROR] InnoDB: Failed to find tablespace for table '"kd_shop"."tbl_branch_list"' in the cache. Attempting to load the tablespace with space id 978591.


编辑启动脚本

vi /home/mysql/start.sh


#!/bin/sh


port=3309

rundir=/home/mysql

echo "$rundir"

/usr/local/mysql/bin/mysqld_safe --defaults-file="$rundir"/my.cnf --basedir=/usr/local/mysql --port="$port" --user=mysql --datadir="$rundir"/data --pid-file="$rundir"/mysql.pid --socket=/"$rundir"/mysqld.sock &

echo "done"


编辑停止脚本

vi /home/mysql/stop.sh


#!/bin/sh


port=3309

rundir=/home/mysql

pid_file="$rundir"/mysql.pid


    if test -f "$pid_file"

    then

      mysqld_pid=`cat $pid_file`

      echo "Killing mysqld with pid $mysqld_pid"

      kill -TERM  $mysqld_pid

      # mysqld should remove the pid_file when it exits, so wait for it.


      sleep 1

      while [ -s $pid_file -a "$flags" != aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ]

      do

        [ -z "$flags" ] && echo "Wait for mysqld to exit\c" || echo ".\c"

        flags=a$flags

        sleep 1

      done

      if [ -s $pid_file ]

         then echo " gave up waiting!"

      elif [ -n "$flags" ]

         then echo " done"

      fi

      # delete lock for RedHat / SuSE

      if test -f /var/lock/subsys/mysql

      then

        rm /var/lock/subsys/mysql

      fi

    else

      echo "No mysqld pid file found. Looked for $pid_file."

    fi



设置权限

chmod 755 /home/mysql/*.sh

chown mysql:mysql -R /home/mysql/*


启动3309实例

/home/mysql/start.sh


查看端口

netstat -napt | grep 3309


测试登陆,打开数据库,特别注意innodb表打开是否正常。注意,用户名是root,密码是空的。


写了一个脚本,记录恢复过程。

之前是用一个shell脚本写的,后面发现主库备份文件有30多G。

执行起来,经常出现恢复失败的情况的。

所以分为3个脚本,用任务计划分别调用


input_base1.sh


#!/bin/bash


echo "############################" >> /opt/db_base.log

#提取昨天时间,因为备份集是昨天的。

totime=`date -d "1 day ago" +"%Y%m%d"`

time=`ls -l --color=auto /backup/db_base/ | awk '{print $9}' | grep $totime`


/home/mysql/stop.sh


rm -rf /home/mysql/data/*


statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base清空数据完成" >> /opt/db_base.log



statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base解压前时间" >> /opt/db_base.log


/root/rds_backup_extract.sh -f /backup/db_base/$time -C /home/mysql/data > /opt/tar.txt



statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base解压数据完成" >> /opt/db_base.log


input_base2.sh


#!/bin/bash


innobackupex --defaults-file=/home/mysql/data/backup-my.cnf --apply-log /home/mysql/data/ 2>/opt/base_recover.log


input_base3.sh


#!/bin/bash


a=`cat /opt/base_recover.log | tail -1 | awk '{print $5}' | cut -d '!' -f 1`

if [ $a = 'OK' ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_base恢复数据完成" >> /opt/db_base.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_base恢复数据失败,程序退出" >> /opt/db_base.log


        sleep 1


        exit

fi


/bin/chown mysql:mysql -R /home/mysql


/home/mysql/start.sh



sleep 10


b=`netstat -anpt | grep 3309 | wc -l`

if [ $b -eq 0 ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_base启动数据库失败" >> /opt/db_base.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_base启动数据库完成" >> /opt/db_base.log

fi


sleep 5


#添加远程用户

/usr/local/mysql/bin/mysql -u root -S /home/mysql/mysqld.sock -e "grant all PRIVILEGES on *.* to xx@'%' identified by 'xx123';flush privileges;"


a=`echo $?`

statime=`date +%Y-%m-%d" "%H:%M:%S`

if [ $a -eq 0 ];then

        echo "$statime 设置远程用户完成" >> /opt/db_base.log

else

        echo "$statime 设置远程用户失败,程序退出" >> /opt/db_base.log

        exit

fi


#删除3天前的备份文件

find /backup/db_base -mtime +2 -type f -name "*.tar.gz" -exec rm {} \;


查看每次下载备份的时候,大概在8点半能下载完成。

设置任务计划

01 09 19 8 * /opt/input_base1.sh &

30 10 19 8 * /opt/input_base2.sh

50 10 19 8 * /opt/input_base3.sh &


其他实列恢复脚本

input_express.sh


#!/bin/bash


echo "############################" >> /opt/db_express.log

#提取昨天时间,因为备份集是昨天的。

totime=`date -d "1 day ago" +"%Y%m%d"`

time=`ls -l --color=auto /backup/db_express/ | awk '{print $9}' | grep $totime`


/data/3310/stop.sh

rm -rf /data/3310/data/*

statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_express清空数据完成" >> /opt/db_express.log

/root/rds_backup_extract.sh -f /backup/db_express/$time -C /data/3310/data

statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_express解压数据完成" >> /opt/db_express.log

#2>/opt/base_recover.log 将输出信息保存到.log文件,便于查看进度


statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base恢复前时间" > /opt/db_express.log


/usr/local/xtrabackup/bin/innobackupex --defaults-file=/data/3310/data/backup-my.cnf --apply-log /data/3310/data/ 2>/opt/express_recover.log


statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base恢复后时间" > /opt/db_express.log


sleep 30


a=`cat /opt/express_recover.log | tail -1 | awk '{print $5}' | cut -d '!' -f 1`

if [ $a = 'OK' ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_express恢复数据完成" >> /opt/db_express.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_express恢复数据失败" >> /opt/db_express.log

fi


chown mysql:mysql -R /data/3310/data

/data/3310/start.sh



sleep 10


b=`netstat -anpt | grep 3310 | wc -l`

if [ $b -eq 0 ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_express启动数据库失败" >> /opt/db_express.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_express启动数据库完成" >> /opt/db_express.log

fi


sleep 3


#添加远程用户

/usr/local/mysql/bin/mysql -u root -S /data/3310/mysqld.sock -e "grant all PRIVILEGES on *.* to xx@'%' identified by 'xx123';flush privileges;"


a=`echo $?`

statime=`date +%Y-%m-%d" "%H:%M:%S`

if [ $a -eq 0 ];then

        echo "$statime 设置远程用户完成" >> /opt/db_express.log

else

        echo "$statime 设置远程用户失败" >> /opt/db_express.log

fi



#删除3天前的备份文件

find /backup/db_express -mtime +2 -type f -name "*.tar.gz" -exec rm {} \;


input_log.sh


#!/bin/bash


echo "############################" >> /opt/db_log.log

#提取昨天时间,因为备份集是昨天的。

totime=`date -d "1 day ago" +"%Y%m%d"`

time=`ls -l --color=auto /backup/db_log/ | awk '{print $9}' | grep $totime`


/data/3311/stop.sh

rm -rf /data/3311/data/*

statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_log清空数据完成" >> /opt/db_log.log

/root/rds_backup_extract.sh -f /backup/db_log/$time -C /data/3311/data

statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_log解压数据完成" >> /opt/db_log.log

#2>/opt/base_recover.log 将输出信息保存到.log文件,便于查看进度


statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base恢复前时间" > /opt/db_log.log


/usr/local/xtrabackup/bin/innobackupex --defaults-file=/data/3311/data/backup-my.cnf --apply-log /data/3311/data/ 2>/opt/log_recover.log


statime=`date +%Y-%m-%d" "%H:%M:%S`

echo "$statime db_base恢复后时间" > /opt/db_log.log


sleep 30


a=`cat /opt/log_recover.log | tail -1 | awk '{print $5}' | cut -d '!' -f 1`

if [ $a = 'OK' ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_log恢复数据完成" >> /opt/db_log.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_log恢复数据失败" >> /opt/db_log.log

fi


chown mysql:mysql -R /data/3311/data

/data/3311/start.sh



sleep 10


b=`netstat -anpt | grep 3311 | wc -l`

if [ $b -eq 0 ];then

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_log启动数据库失败" >> /opt/db_log.log

else

        statime=`date +%Y-%m-%d" "%H:%M:%S`

        echo "$statime db_log启动数据库完成" >> /opt/db_log.log

fi


sleep 3


#添加远程用户

/usr/local/mysql/bin/mysql -u root -S /data/3311/mysqld.sock -e "grant all PRIVILEGES on *.* to xx@'%' identified by 'xx123';flush privileges;"


a=`echo $?`

statime=`date +%Y-%m-%d" "%H:%M:%S`

if [ $a -eq 0 ];then

        echo "$statime 设置远程用户完成" >> /opt/db_log.log

else

        echo "$statime 设置远程用户失败" >> /opt/db_log.log

fi



#删除3天前的备份文件

find /backup/db_log -mtime +2 -type f -name "*.tar.gz" -exec rm {} \;

 


完整任务计划

#下载备份

01 22 18 8 * /opt/wget.sh &

#清除缓存

01 */1 * * * /opt/clean_mem.sh

#恢复实列

20 06 19 8 * /opt/input_log.sh

30 06 19 8 * /opt/input_express.sh

01 09 19 8 * /opt/input_base1.sh &

30 10 19 8 * /opt/input_base2.sh

50 10 19 8 * /opt/input_base3.sh &


说明:

可能是因为备份这段时间里面有optimize table操作(任务计划删除表,优化表),所以导致有坏页。

所以调整下备份时间。

因为开启了innodb_force_recovery=4,所以导致无法写入。出现

InnoDB is in read only mode

关闭之后,就好了。

mysql的error.log日志,也没有出现

[ERROR] InnoDB: Failed to find tablespace for table '"kd_shop"."tbl_branch_list"' in the cache. Attempting to load the tablespace with space id 978591.

你可能感兴趣的:(备份,恢复,RDS,阿里云)