企业级增量实战

发布时间 2023-10-08 15:57:38作者: 普里莫

企业级增量恢复实战

背景:

某大型网站,mysql数据库,数据量500G,每日更新量100M-200M

备份策略:

xtrabackup,每周六0:00进行全备,周一到周五及周日00:00进行增量备份。

故障场景:

周三下午2点出现数据库意外删除表操作。

模拟故障:

# 编辑脚本
#!/bin/bash

mysql -uroot -p123 -e "drop database if exists prod;"
mysql -uroot -p123 -e "create database if not exists prod;"
mysql -uroot -p123 -e "create table if not exists prod.t1(id int);"

num=1
while true;do
  mysql -uroot -p123 -e "insert into prod.t1 values($num);commit;"
  ((num++))
  sleep 1
done

# 创库
root@localhost [(none)] >create database logs;
# 切换到logs
root@localhost [(none)] >use logs;
# 创建表test_logs
root@localhost [logs] >create table test_logs(id int);
# 插入数据
root@localhost [logs] >insert into test_logs values(1);
root@localhost [logs] >insert into test_logs values(2);
root@localhost [logs] >insert into test_logs values(3);
# 查询表
root@localhost [logs] >select * from test_logs;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
# 修改id
root@localhost [logs] >update test_logs set id=10 where id=2;
# 删除id
root@localhost [logs] >delete from test_logs where id=3;

# 全备
innobackupex --no-timestamp /backup/full-$(date +%F)

# 第一次增量备份
innobackupex --no-timestamp --incremental --incremental-basedir=/backup/full-2023-08-03/ /backup/inc-$(date +%F-%H)

# 第二次增备
innobackupex --no-timestamp --incremental --incremental-basedir=/backup/inc-2023-08-04-00/ /backup/inc-$(date +%F-%H)

# 第三次增备
innobackupex --no-timestamp --incremental --incremental-basedir=/backup/inc-2023-08-05-00/ /backup/inc-$(date +%F-%H)

# 第四次增备
innobackupex --no-timestamp --incremental --incremental-basedir=/backup/inc-2023-08-06-00/ /backup/inc-$(date +%F-%H)

# 删除表
root@localhost [logs] >drop table test_logs;

解决思路:

# 1.停库
systemctl stop mysqld

# 2.先模拟CSR(旧库)
1)全备模拟CSR,只做redo,不做undo
innobackupex --apply-log --redo-only /backup/full-2023-08-03/

2)第一次增备合并到全备的时候,只做redo,不做undo
innobackupex --apply-log --redo-only --incremental-dir=/backup/inc-2023-08-04-00 /backup/full-2023-08-03/

3)第二次增备合并到全备的时候,只做redo,不做undo
innobackupex --apply-log --redo-only --incremental-dir=/backup/inc-2023-08-05-00 /backup/full-2023-08-03/

4)第三次增备合并到全备的时候,只做redo,不做undo
innobackupex --apply-log --redo-only --incremental-dir=/backup/inc-2023-08-06-00 /backup/full-2023-08-03/

5)第四次增备合并到全备的时候,做redo和做undo都做
innobackupex --apply-log --redo-only --incremental-dir=/backup/inc-2023-08-07-00 /backup/full-2023-08-03/

6)最后全部合并完成后,把全备redo和undo都做一遍
innobackupex --apply-log /backup/full-2023-08-03/

# 3.准备一个新环境(模拟)
## 3.1删除data目录(模拟时操作)
## 3.2生成新环境
[root@db01 scripts]# ./mysql_install_db --basedir=/app/mysql --datadir=/app/mysql/data
## 3.3启动数据库
[root@db01 scripts]# /etc/init.d/mysqld start
## 3.4新环境创建用户
mysql> grant all on *.* to test@'%' identified by '123';

# 4.将旧库的全备及增备恢复到新环境(如果全备文件很大,scp速度慢)
innobackupex -usertest -password123 -host10.0.0.51 --copy-back /backup/full-2023-08-03/

# 5.授权
[root@db01 mysql]# chown -R mysql.mysql /app/mysql/data

# 6.截取binlog
1)第一段binlog,全备后:起始位置点 95885
[root@db02 tmp]# cat /app/mysql/data/xtrabackup_binlog_pos_innodb
mysql-bin.000015        95885
2)第一段binlog,删表前:结束位置点 98277
mysqlbinlog --base64-output=decode-rows -vvv /app/mysql/data/mysql-bin.000015 | grep -i 'drop table' -C 5

## 导出第一段数据:
[root@db02 tmp]# mysqlbinlog --start-position=95885 --stop-position=98277 /app/mysql/data/mysql-bin.000015 > /tmp/inc1.sql

## 恢复第一段
[root@db02 tmp]# mysql -utest -p123 -h10.0.0.51 < /tmp/inc1.sql

3)第二段binlog,删表后,起始位置点 98411
mysqlbinlog --base64-output=decode-rows -vvv /app/mysql/data/mysql-bin.000015 | grep -i 'drop table' -C 5

## 先停连接数据库的程序,挂维护页,截取结束位置点

4)第二段binlog,停库前,结束位置点 125666

## 截取第二段:
[root@db02 tmp]# mysqlbinlog --start-position=98411 --stop-position=125666 /app/mysql/data/mysql-bin.000015 > /tmp/inc2.sql

## 恢复第二段binlog
[root@db02 tmp]# mysql -utest -p123 -h10.0.0.51 < /tmp/inc2.sql 

# 4.应用割接
- 改代码
- mysqldump 新环境的数据,恢复到旧环境
[root@db02 tmp]# mysqldump -utest -p123 -h10.0.0.51 -A -R --triggers --master-data=2 --single-transaction|gzip > /tmp/full.sql.gz

[root@db02 tmp]# zcat /tmp/full_51.sql.gz |mysql -uroot -p123

# 5.启动连接数据库的程序,取消维护页