「删库不一定要跑路」聊一聊数据库误删恢复

「删库不一定要跑路」聊一聊数据库误删恢复_第1张图片

一、前言

我在学习编程过程中总会遇到前辈们带着几分戏谑告诉我 rm -rf *drop database 这两条命令要谨慎使用,那么我们今天就来试试这两条命令。
「删库不一定要跑路」聊一聊数据库误删恢复_第2张图片

二、drop database 删库

1. 我们先看看数据库吧,下面就是我们这次需要删除的业务库-help。

2. 现在我们就使用 drop database 删除 help 数据库:
「删库不一定要跑路」聊一聊数据库误删恢复_第3张图片
3. 库我们已经删了,接下来讨论如何快速将它恢复,要是恢复失败了…
「删库不一定要跑路」聊一聊数据库误删恢复_第4张图片
我们先看恢复过程,后面我会介绍恢复原理和方法,这次我们使用binlog恢复数据库

mysql> show master logs ;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |  50104058 |
| mysql-bin.000002 |      1706 |
| mysql-bin.000003 |      2244 |
| mysql-bin.000004 |      3039 |
| mysql-bin.000005 |     59348 |
+------------------+-----------+
5 rows in set (0.00 sec)

mysql> show binlog events in 'mysql-bin.000005';

通过上面的命令我们确定了两个位置点start:1138 end:59256

mysqlbinlog --start-position=1138 --stop-position=59256 ./mysql-bin.000005 > tem.sql
mysql -uroot -p
source /data/tem.sql

「删库不一定要跑路」聊一聊数据库误删恢复_第5张图片
数据库就这样回来了....其实这次使用的是MySQL的二进制日志binlog 8.0以前的版本没有默认开启需要自己手动配置。当然,实际业务中binlog多用于主从复制和配合其它备份工具一起使用恢复数据,接下来我们一起学习一下binlog吧

三、binlog 介绍

  1. 简介:主要记录数据库中的变化性质日志(DDL|DML|DCL) 属于逻辑性质日志。应用于主从复制和辅助其它备份工具数据恢复。

  2. 配置:需要在mysql配置文件配置相关参数

    vim /etc/my.cnf
    server-id=6  -- 主机编号,主从中使用,5.7后要开启binlog要配置此参数
    log-bin=/data/binlog/mysql-bin -- 日志存放目录+日志名前缀 mysql-bun.0001
    sync-binlog=1 -- binlog中的刷新策略
    binlog-format=row -- binlog记录格式设置为row模型
    
  3. 查看是否开启:

    show variables like 'log_bin'; --ON开启 OFF关闭
    
    Variable_name Value
    log_bin ON
  4. 查看binlog存储位置:

    select @@log_bin_basename;
    
    @@log_bin_basename
    /var/log/binlogs/mysql-bin
  5. 存储方式:开启后二进制日志会记录操作MySQL的相关语句,存储方式有三种 :

    statement(5.6默认):SBR(statement based replication) 语句模式原封不动记录当前DDL
    ROW(5.7默认):RBR(row based replication) 记录数据行的变化(用户看不懂,需要工具分析)
    mixed(混合):MBR(mixed based replication) 以上两种模式混合
    

    MySQL比较建议使用 row 方式存储二进制日志,并且5.7版本中默认使用的是row方式。

  6. 日志操作:二进制日志默认大小可以配置 max_binlog_cache_size=100M,存储满了或者sh会自动延伸文件,可以使用 expire_logs_days 参数开启自动删除机制,默认等于0表示不会自动删除。

  7. 查看binlog日志

    show binlog events in 'mysql-bin.000003';
    
    log_name Pos Event_type Server_id End_log_pos Info
    mysql-bin.000005 1136 Query 6 1138 create database help charset utf8mb4
    mysql-bin.000005 59256 Query 6 59269 drop database help

    介绍:中间我省略了很多,我们使用binlog恢复数据有有三种方式第一种使用pos编号第二种使用GTID第三种使用时间戳,可以自行查阅相关文档,今天我只负责引出binlog。如上,我们只需要确定两个编号 删除数据库之前和创建数据库时,分别对应1138表示 create database 这条语句,而59256表示上一个语句结束的编号,如果你使用了59269那么导入出的SQL就会有drop database help 创建出来也会自动删除。

  8. 通过POS值导出SQL语句

    mysqlbinlog -d help --start-position=1138 --stop-position=59256 ./mysql-bin.000003 > tem.sql
    

    参数分别为 -d 数据库 ---start-position=POS值开始 --stop-position=POS值结束 binlog文件路径,导出SQL语句后source到数据库中即可,这种恢复方式效率很低,成本大。所以只用于辅助,接下来我们介绍备份恢复

三、MySQL逻辑备份

  1. 常用逻辑备份工具:mysqldump(MBK)、replication、mydumper、load-data-in-file
  2. innodb表备份:可以采取快照备份的方式开启一个独立的事务,获取当前最新的一致性快照,将快照数据放到临时表中,转换为SQL,然后保存。
  3. 非innodb表备份:需要锁表备份。触发FTWRL,全局表锁,转换成SQL保存到文件中。
  4. mysqldump:mysql自带的逻辑备份工具,直接保存SQL文件,所以当数据量大时不管是备份或者恢复成本都比较大,如果数据量超过100G则不建议使用逻辑备份。
  5. 备份命令介绍:
    -- 连接参数:-u -p -h -P -S
    -- 备份参数:-A(全备)
    mysqldump -uroot -p -A > /Users/cooh/Desktop/备份/dump.sql
    
    -- 备份指定库:-B(指定库)
    mysqldump -uroot -p -B help sql_test > /Users/cooh/Desktop/备份/dump2.sql
    
    -- 备份指定库表
    mysqldump -uroot -p new_data new > /Users/cooh/Desktop/备份/dump3.sql
    
    -- 会打上binlog的标签 --master-data 没有开启binlog Binlogging on server not active
    mysqldump -uroot -p -A --master-data=2 > /Users/cooh/Desktop/备份/dump4.sql
    
    -- single-transaction 对于innodb引擎开启一个事务获取一致性快照,进行备份(不是完全热备)
    mysqldump -uroot -p -A --master-data=2 --single-transaction > /Users/cooh/Desktop/备份/dump4.sql
    
    -- 参数:-R 备份存储过程和函数 -E 备份事件 -triggers 备份触发器
    -- 参数:--max_allowed_packed=64M
    
  6. 关键参数:master-data

    明显可以看出使用 master-data=2 多出 -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=117409; 表示备份前二进制日志的文件信息和位置点,需要恢复数据时就可以使用这个位置点截取binlog恢复数据。mysqldump就介绍到这里,大家可以自己试试。使用它我们需要打开数据库才可以恢复,那么下面介绍一种 rm -rf * 备份恢复方法

四、PBK介绍及相关

  1. 工具:工具:MySQL Enterprise Backup(企业版)Percona Xtrabackup(PBK、XBK)
  2. PBK介绍:物理备份工具,拷贝数据文件,效率会比较高。
  3. 优势:PBK对innodb数据引擎备份对过程属于热备,备份过程中对数据库对影响比较小并且支持增量备份。
  4. redo log:PBK备份数据时有一个参数比较重要,所以我要介绍下inoodb引擎中 redo 日志。当事务执行一条DML语句时,mysql会将需要改动当数据页加载到 boffer pool 中,如果数据量非常大,需要改动大page特别多这时从内存写入硬盘的耗时会比较长,如果突然宕机那么就可能会出现数据丢失的情况,所以innodb引擎会先把需要改动的数据信息加载到 redo buffer pool内存空间,然后快速写入硬盘,如果发生宕机那么可以通过原数据+需要改动的信息重新加载到buffer pool进行整合然后 CheckPoint内存脏页(内存中发生了修改没有写入磁盘之前的数据内存页称为脏页)写入到硬盘mysql才会正常工作。总结一下,redo log 会存储一些已经提交到事务信息,维护事务到一致性。
    「删库不一定要跑路」聊一聊数据库误删恢复_第6张图片
  5. undo log:回滚日志,是事务日志的一种。在事务ACID中,实现的是 原子性 的作用。对于一致性和隔离线有着辅助的作用。在CSR中实现将redo中记录的未提交的操作进行回滚。当在事务中执行一条DML语句时,通过连接层、SQL层后innodb引擎会将数据改动的page加载的buffer pool中,加载过程中也会将修改的数据存储到undo log 回滚段中,如果需要回滚rollback时,可以根据PTR等事务编号回滚数据。
  6. undo log csr:redo也会预加载一些未提交的事务,如果发生故障时,redo先进前滚,然后发现数据中还有一些未提交的事务改动,再使用undo进行回滚。

五、rm -rf * 删库

终于到了激动人心的环节,现在我们来模拟一次事故。从周一开始假设我们每天会做一次增量备份,数据库在周四突然被删库。下面我们进行模型:

  1. 首先进行使用PBK模拟周一的全备:

    # 进行全备份
    innobackupex --user=root --password=112233 /data/backup/
    # 修改全备文件名
    mv 2020* full
    
  2. 创建数据库插入数据模拟第一次增量备份前的改动
    「删库不一定要跑路」聊一聊数据库误删恢复_第7张图片

  3. 使用PBK基于全备进行增量备份:

    # 模仿第一次增量备份
    innobackupex --user=root --password=1122 --incremental --incremental-basedir=/data/backup/full /data/backup/
    # 修改第一次备份文件名
    mv 2020*/ add_01
    

    --incremental 开启增量备份 --incremental-basedir 上一次备份的路径

  4. 创建数据库插入数据模拟第二次增量备份前的改动:
    「删库不一定要跑路」聊一聊数据库误删恢复_第8张图片

  5. 使用PBK基于第一次增量备份进行第二次增量备份:

    # 模仿第二次增量备份
    innobackupex --user=root --password=1122 --incremental --incremental-basedir=/data/backup/add_01 /data/backup/
    # 修改第二次备份文件名
    mv 2020*/ add_02
    
  6. 创建数据库插入数据模拟数据库宕机前的改动:
    「删库不一定要跑路」聊一聊数据库误删恢复_第9张图片

  7. 此时我们创建插入三次数据只有两次进行了备份分别是x_one、x_two、x_three:
    「删库不一定要跑路」聊一聊数据库误删恢复_第10张图片

  8. 删除mysql中所以的文件数据

    # 关闭数据库
    pkill mysqld
    # 查看数据库状态
    systemctl status mysqld.service
    # 跳转到mysql文件夹
    cd /var/lib/mysql/
    # 直接删库
    rm -rf *
    
    [root@iZ2zeg3h4a24fm0w94g1zqZ mysql]# pwd
    /var/lib/mysql
    [root@iZ2zeg3h4a24fm0w94g1zqZ mysql]# ls
    [root@iZ2zeg3h4a24fm0w94g1zqZ mysql]# ll
    总用量 0
    [root@iZ2zeg3h4a24fm0w94g1zqZ mysql]# 
    

    此时 mysql 文件中所有的数据都被 rm -rf * 这条命令删光了....

六、恢复rm -rf * 删除的数据

  1. 恢复数据思路:合并整理所有增量备份到全备、启动数据库、截取binlog、恢复日志。

  2. 整理备份数据:

    # 整理基础备份
    innobackupex --apply-log --redo-only /data/backup/full
    # 合并增量备份到全备中
    innobackupex --apply-log --redo-only --incremental-dir=/data/backup/add_01  /data/backup/full
    # 最后一次增量合并可以不用加 --redo-only 回滚
    innobackupex --apply-log --incremental-dir=//data/backup/add_02 /data/backup/full
    # 整体再次prepare整个备份
    innobackupex --apply-log /data/backup/full
    
  3. 参数介绍:--apply-log 参数就是将备份过程中的产生事务中的 redo 和 undo 日志进行前滚和回滚 --redo-only 此参数将会跳过undo回滚,PBK是基于 pos_id 进行备份,我们进行的是增量备份过程中会发生未提交的事务这一部分我们先不要进行回滚,可能会影响 pos_id 位置点,如果增量备份中的 pos_id 对接不上的话会合并失败。

  4. 恢复数据:合并增量备份完成后直接将文件拷贝到mysql数据文件路径下,此时注意数据到权限,mysql可能没有权限使用文件需要授权。

    # 将恢复好的数据移动到mysql文件路径下
    cp -a /data/backup/full/* /var/lib/mysql
    # 此路径权限变成 root MySQL无权访问
    chown -R mysql.mysql /var/lib/*
    # 启动MySQL数据库
    systemctl start  mysqld.service
    

    「删库不一定要跑路」聊一聊数据库误删恢复_第11张图片

  5. 启动数据库查看数据库状态:此时发现只有x_one、x_two 两个备份的数据库,没有 x_three 需要使用binlog进行恢复数据
    「删库不一定要跑路」聊一聊数据库误删恢复_第12张图片

  6. 接下来我们使用binlog恢复数据

    # 还有一部分数据在binlog中未恢复
    cat xtrabackup_binlog_info
    # mysql-bin.000005	119080
    mysqlbinlog --skip-gtids --start-position=119080 /var/log/binlogs/mysql-bin.000005>/data/tem.sql
    # 暂时关闭binlog
    set sql_log_bin=0;
    # 导入binlog恢复数据
    source /data/tem.sql
    # 开启binlog完成恢复
    set sql_log_bin=1;
    

    「删库不一定要跑路」聊一聊数据库误删恢复_第13张图片

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | help               |
    | mysql              |
    | performance_schema |
    | sys                |
    | x_one              |
    | x_three            |
    | x_two              |
    +--------------------+
    8 rows in set (0.00 sec)
    
    mysql> use x_three;
    Database changed
    mysql> select * from number;
    +---+------+
    | a | b    |
    +---+------+
    | 1 | A    |
    | 2 | B    |
    | 3 | C    |
    +---+------+
    3 rows in set (0.00 sec)
    

七、结语

此时被rm -rf * 的数据已经全部恢复了,如果是真正的业务的话可能会需要比较长的时间,如何删库不跑路,那就是重要的数据做好备份,鸡蛋不要放在一个 今天只是简单介绍了下整体过程,没有学习DBA相关的知识可不要拿公司的库测试。

以上就是所有内容,如果您感觉不错或对您有帮助,欢迎点赞或转发,谢谢!

你可能感兴趣的:(MySQL)