zoukankan      html  css  js  c++  java
  • Mysql binlog 数据恢复

    Mysql binlog 相关

    MySQL 修改密码

    sudo -s
    mysql
    use mysql
    
    ALTER USER root@localhost  IDENTIFIED WITH caching_sha2_password BY '123456'
    

    MySQL 允许 root 远程登录

    mysql -u root -p
    use mysql
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456'
    flush privileges
    

    开启 MySQL 的 binlog 日志

    在my.inf主配置文件中直接添加三行

    log-bin=/var/lib/mysql/mysql-bin
    server-id=123454     #5.7以上需要
    

    然后重启服务

    查看数据库是否支持 binlog:

    show variables like '%log_bin%'  
    

    首先 binlog 需要配合定期备份一起恢复数据,如果数据库没有做定期备份,那只有 binlog 也是白瞎。

    binlog 恢复实战一

    先说明一下背景:一台 Mysql5.7 数据库,开启了 binlog,且设置了每日凌晨 1 点备份一次数据库。早上 10:30 数据库操作人员误 ##误更新/删除## 1W 条数据导致系统出现了严重问题。
    11:00 关闭系统,停止运行,并开始着手数据恢复。

    这里 ##误更新/删除/新增## 为简单的场景,比如更新或删除数据忘记添加 where 条件。我们可以通过找到当时时间点的 binlog,然后通过人工替换字符串的方式来恢复。

    数据恢复步骤如下:

    • 停止运行服务,并开始着手数据恢复。
    • 数据库执行 flush logs; 将最新的 binlog 生成。
    • 找到需要恢复的 binlog。
    • 通过分析 binlog 生成恢复 sql。
    • 执行 sql 进行恢复。

    我们可以通过时间点来找到响应的 binlog 日志,比如我们找到的 binlog 日志名字为:binlog.000001

    mysqlbinlog -D --database=release -v binlog.000001 > temp.sql
    

    然后找到出事时的 binlog 日志,大约如下:

    # at 599
    BEGIN
    ### UPDATE `release`.`co_record`
    ### WHERE
    ###   @1='5c0751c4189d4cd5b9c7223ca0ad74689f4915b5421e4cc0ac50e1e6b640c787'
    ###   @2='2021-11-02 15:07:00'
    ### SET
    ###   @1='5c0751c4189d4cd5b9c7223ca0ad74689f4915b5421e4cc0ac50e1e6b640c787'
    ###   @2='2021-11-02 15:06:00'
    # at 1923
    COMMIT/*!*/;
    

    需要对这种伪 sql 进行转换成恢复 sql。这个部分自行转换,转换好的 sql 应该长这个样子:

    UPDATE `release`.`co_record` SET xxx='5c0751c4189d4cd5b9c7223ca0ad74689f4915b5421e4cc0ac50e1e6b640c787', xxx= '2021-11-02 15:06:00';
    

    转换这个部分很烦,需要根据业务来灵活转换,但基本上就是字符串批量替换的事情。

    binlog 恢复实战二

    先说明一下背景:一台 Mysql5.7 数据库,开启了 binlog,且设置了每日凌晨 1 点备份一次数据库。早上 10:30 数据库操作人员 误更新/删除 1W 条数据导致系统出现了严重问题。
    11:00 关闭系统,停止运行,并开始着手数据恢复。

    这里 误更新/删除/新增 为复杂的场景,没有办法通过上一个办法恢复。这时候可以尝试全量恢复。

    数据恢复步骤如下:

    • 停止运行服务,并开始着手数据恢复。
    • 数据库执行 flush logs; 将最新的 binlog 生成。
    • 找到需要恢复的 binlog。
    • 全量恢复今日凌晨1点备份的数据库。
    • 恢复 binlog。

    由于每天凌晨 1 点会备份数据,只要将包含凌晨 1 点的 binlog 和以后的 binlog 找到即可。比如我们找到 binlog.000001/binlog.000002/binlog.000003/binlog.000004 四个日志文件。
    也许真实的场景只有一个或更多的 binlog 日志,但总结起来就分为四种日志:

    • binlog 记录了 凌晨 1 点前的数据,结束于备份完成后
    • binlog 记录了 备份完成后且不包含出事的记录
    • binlog 记录了 出事时的记录
    • binlog 记录了 出事后的记录且不包含出事的记录

    其中 2 4 记录是最简单的,直接恢复就可以了。 1 3 需要倒出来处理一下才可以。

    第一种情况的 binlog 包含了已经恢复的数据,当我们恢复了凌晨 1 点备份后,这份 binlog 我们就只需要恢复 1 点后的数据,所以我们要按照时间来过滤。
    例子中的 933659 就是凌晨 1 点后第一个需要恢复的数据的位置

    mysqlbinlog -D --database=release --start-position=933659 binlog.000001 | mysql -u root -p -v release
    
    

    第二种情况和第四种情况就直接按照时间先后执行即可

    mysqlbinlog -D --database=release  binlog.000002 | mysql -u root -p -v release
    
    ## 执行完 binlog.000003 后
    
    mysqlbinlog -D --database=release  binlog.000004 | mysql -u root -p -v release
    

    第三种情况是最难处理的,因为该 binlog 包含了一串错误的日志,我们需要将这部分记录去除,然后再恢复。我们这里是 误更新/删除/新增 1W 条数据。
    这里就需要人工的将这部分数据的开始位置和结束位置找到,然后跳过这部分记录恢复。
    比如我们这里例子中错误的记录是在 4500-67000 行之间,那么我们就需要分两步来恢复。

    mysqlbinlog -D --database=release --stop-position=4500 binlog.000003 | mysql -u root -p -v release
    mysqlbinlog -D --database=release --start-position=67000 binlog.000003 | mysql -u root -p -v release
    

    其实恢复就是对数据库操作的重放,binlog 记录了所有数据库的操作,只要将错误和不要的 binlog 记录剔除出去,就可以恢复。

    但是这里有一个问题,就是我们去除了误更新/删除/新增 1W 条数据的 binlog 记录,这个时候,其实后面的 binlog 恢复(10:30 以后的数据)就很容易出错。
    因为用户是在错误的数据的基础上继续更新的,我们将错误的数据去除后,就和真实的数据对应不上了,所以很大情况下我们就只能恢复到 10:30 时的数据,再往后的数据很难找回。

  • 相关阅读:
    python之面向对象封装,多态
    python之面向对象继承
    python之面向对象类空间问题以及类之间的关系
    python之面向对象初识
    python之包及logging日志
    python之规范化开发
    python之模块Ⅱ
    python之模块Ⅰ
    python函数之闭包及装饰器
    python函数之内置函数
  • 原文地址:https://www.cnblogs.com/manastudent/p/15698797.html
Copyright © 2011-2022 走看看