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 时的数据,再往后的数据很难找回。

  • 相关阅读:
    第一节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
    Tensorflow 错误:Unknown command line flag 'f'
    Python 多线程总结
    Git 强制拉取覆盖本地所有文件
    Hive常用函数 傻瓜学习笔记 附完整示例
    Linux 删除指定大小(范围)的文件
    Python 操作 HBase —— Trift Trift2 Happybase 安装使用
    梯度消失 梯度爆炸 梯度偏置 梯度饱和 梯度死亡 文献收藏
    Embedding 文献收藏
    深度学习在CTR预估中的应用 文献收藏
  • 原文地址:https://www.cnblogs.com/manastudent/p/15698797.html
Copyright © 2011-2022 走看看