当删库时如何避免跑路

延时节点解决方案

删库跑路也是个老梗了,可见在运维数据库的过程中误删除数据,或者开发的代码有bug,造成数据的误删除屡见不鲜。不过现在也有许多用于恢复或预防误删除的方案,例如SQL管理系统,将要执行的SQL先交由管理员审核,然后由管理员备份一个镜像数据库,在镜像上执行该SQL,并在执行后还原镜像。这样经过层层把关就可以大大减小出现误操作的几率。

另外,利用binlog日志也可以恢复误操作的数据,所以线上运行的数据库都会开启binlog日志功能。还有就是本小节要介绍的延时节点:在Replication集群中,可以设置一个延时节点,该节点的数据同步时间要慢于集群中的其他节点,当其他节点出现误操作后,若延时节点的数据还没有被影响就可以从延时节点进行恢复。

但如果现有的数据库组建的都是PXC集群,没有Replication集群可以采用该方案吗?也是可以的,PXC集群与Replication集群并非是互斥的,我们可以将PXC集群中的某个节点设置为Master,然后增加一个延时节点设置为Slave,让这两个节点构成Replication集群进行数据同步即可。如下所示:

本小节就简单演示一下如何搭建这种异构集群下的延时节点,我这里已经事先准备好了一个PXC集群和一个用作延时节点的数据库:

这里使用PXC集群中的PXC-Node3作为Master,让其与DelayNode组成主从,而DelayNode自然就是作为延时节点了。

关于PXC集群和Replication集群的搭建可以参考如下文章,这里由于篇幅有限就不进行说明了:


为PXC节点配置延时节点

接下来开始动手实践,首先需要将这两个节点上的MySQL服务都给停掉:

systemctl stop mysqld

主从节点的配置文件都要开启GTID,否则无法利用延时节点找回数据。主节点需要增加的配置如下:

[[email protected] ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf
[mysqld]
...

# 设置节点的id
server_id=3
# 开启binlog
log_bin=mysql_bin
# 开启GTID
gtid_mode=ON
enforce_gtid_consistency=1

从节点需要增加的配置如下:

[[email protected] ~]# vim /etc/my.cnf
[mysqld]
...

server_id=102
log_bin=mysql_bin
# 从节点需要开启relay_log
relay_log=relay_bin
gtid_mode=ON
enforce_gtid_consistency=1

完成配置文件的配置后,启动这两个节点:

systemctl start mysqld

接着配置Slave对Master的主从关系,进入Master的MySQL命令行终端,通过如下语句查询Master当前正在使用的二进制日志及当前执行二进制日志位置:

mysql> flush logs;  -- 刷新日志
mysql> show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File                 | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| PXC-Node3-bin.000003 |      154 |              |                  |                   |
+----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

记录下以上执行结果后,进入Master的MySQL命令行终端,分别执行如下语句:

mysql> stop slave;  -- 停止主从同步
mysql> change master to master_log_file=‘PXC-Node3-bin.000003‘, master_log_pos=154, master_host=‘192.168.190.134‘, master_port=3306, master_user=‘admin‘, master_password=‘Abc_123456‘;  -- 配置Master节点的连接信息,以及从Master二进制日志的哪个位置开始复制
mysql> start slave;  -- 启动主从同步
  • Tips:通常配置主从同步会单独创建一个用于同步账户,这里为了简单起见就直接使用了现有的账户

配置完主从关系后,使用show slave status\G;语句查看主从同步状态,Slave_IO_RunningSlave_SQL_Running的值均为Yes才能表示主从同步状态是正常的:

主从关系配置完成后,接着测试一下主从的数据同步是否正常。在Master上执行一些SQL语句,如下:

mysql> create database test_db;
mysql> use test_db;
mysql> CREATE TABLE `student` (
          `id` int(11) NOT NULL,
          `name` varchar(20) NOT NULL,
          PRIMARY KEY (`id`)
       );
mysql> INSERT INTO `test_db`.`student`(`id`, `name`) VALUES (1, ‘Jack‘);

执行完成后,看看Slave上是否有正常同步:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test_db            |
+--------------------+
5 rows in set (0.00 sec)

mysql> use test_db;
mysql> select * from student;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
+----+------+
1 row in set (0.00 sec)

mysql> 

验证了主从节点能正常同步数据后,我们就可以设置Slave节点的同步延时了。在Slave节点上分别执行如下语句:

mysql> stop slave;
mysql> change master to master_delay=1200;  -- 设置同步延时为1200秒
mysql> start slave;

同样,重新配置了主从关系后,需要确认主从同步状态是正常的:


模拟误删除数据

接着演示下延时节点的作用,首先到Master节点上,将student表中的数据给删除掉,模拟误删除的情况:

mysql> use test_db;
mysql> delete from student;  -- 删除student表中的所有数据
mysql> select * from student;  -- Master上已经查询不到数据了
Empty set (0.00 sec)

mysql> 

此时,因为延时同步的原因,在Slave节点上依旧能够正常查询到被删除的数据:

mysql> use test_db;
mysql> select * from student;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
+----+------+
1 row in set (0.00 sec)

mysql> 

现在就轮到GTID上场了,我们得先让Slave节点跳过删除操作的GTID,后续才能让Master从Slave上恢复数据。否则Slave同步了该GTID的话,Slave节点上的数据也会被删除,即便在同步之前恢复了Master的数据也会造成主从数据不一致的问题。

GTID是记录在binlog中的,由于误删除操作是在Master上进行的,所以首先在Master节点上使用show master logs;语句查询binlog日志名称:

接下来我们需要在binlog文件中找到误删除操作的记录及其GTID,因为binlog文件的序号是递增的,所以最近的操作一般记录在序号最大的binlog文件中。因此执行show binlog events in ‘PXC-Node3-bin.000003‘;语句,并从结果集中查找误删除操作的记录及其GTID。如下图所示:

在Master节点上找到误删除操作的GTID后,复制该GTID。然后到Slave节点上分别执行如下语句:

mysql> stop slave;  -- 停止主从同步
mysql> set gtid_next=‘d36eaafb-c653-ee15-4458-5d6bc793bd7a:4‘;  -- 设置需要跳过的GTID
mysql> begin; commit;  -- 开启并提交事务,即模拟Slave同步了该GTID,后续就不会再进行同步,从而达到了跳过的效果
mysql> set gtid_next=‘automatic‘;  -- 恢复gtid的设置
mysql> change master to master_delay=0;  -- 设置同步延时为0是为了马上进行同步跳过该GTID
mysql> start slave;

完成以上操作后,此时Slave上依旧存在着误删除的数据:

而Master上的student表依旧为空:

完成以上的操作后,恢复同步延时的设置:

mysql> stop slave;
mysql> change master to master_delay=1200;  -- 设置同步延时为1200秒
mysql> start slave;

恢复Master节点误删除的数据

让Slave节点跳过误删除操作的GTID后,就可以开始恢复Master节点的数据了。首先停止业务系统对Master节点所在的PXC集群的读写操作,避免还原的过程中造成数据混乱。然后导出Slave节点的数据:

在Master节点上创建临时库,这是为了先在临时库验证了数据的正确性之后再导入到业务库中,避免出现意外:

create database temp_db;

然后导入数据:

把Master节点上的数据表重命名:

rename table test_db.student to test_db.student_bak;

把临时库的数据表迁移到业务库中:

rename table temp_db.student to test_db.student;

此时就成功恢复了Master节点上误删除的数据:


日志闪回方案

之前也提到了除延时节点这种解决方案外,使用binlog日志也是可以实现数据恢复的,这种恢复数据的方式通常被称为日志闪回。这里之所以还要介绍这种方案,是因为延时节点方案存在着一定的局限性:一旦在延时阶段没有发现问题并解决问题的话,那么当主从数据同步后,也无法利用从节点去实现误删除的恢复。

日志闪回方案相对于延时节点方案来说要简单一些,不需要增加额外的节点,利用当前节点就可以恢复数据。但该方案也并非全能,例如binlog日志不会记录drop tabletruncate table等操作所删除的数据,那么也就无法通过日志恢复了。不过这两种方案并不冲突,可以同时使用以提高数据恢复的可能性。

日志闪回的前提是要开启binlog日志,然后通过一些闪回工具将binlog日志解析成SQL,接着将SQL中的delete语句转换成insert语句,或者找到被误删除的数据的insert语句。最后将这些insert语句重新在数据库中执行一遍,这样就实现了数据的恢复:

闪回工具有很多,本文中采用的是binlog2sql,它是大众点评开源的基于Python编写的MySQL日志闪回工具。

安装binlog2sql

该工具的安装步骤如下:

# 安装前置工具
[[email protected] ~]# yum install -y epel-release
[[email protected] ~]# yum install -y git python3-pip

# 克隆binlog2sql的源码库,并进入源码目录
[[email protected] ~]# git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql

# 安装binlog2sql所依赖的Python库
[[email protected] ~/binlog2sql]# pip3 install -r requirements.txt

在MySQL配置文件中配置如下参数,因为binlog2sql是基于row格式的binlog进行解析的:

[mysqld]
...

binlog_format = row
binlog_row_image = full

模拟误删除数据

我这里有一张商品表,该表中有如下数据:

使用delete语句删除该表中的数据来模拟误删除:

delete from flash.goods;

然后再插入一些数据,模拟误删除后新增的数据:

INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (6, ‘苹果‘, ‘xxxx‘, ‘1‘);
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (7, ‘香蕉‘, ‘xxxx‘, ‘1‘);

通过binlog2sql恢复数据

恢复前的准备工作:

  • 停止应用对数据库的读写操作,避免还原后覆盖新写入的数据
  • 热备份数据库,以保证还原工作万无一失,关于备份相关内容可以参考:关于数据库的各种备份与还原姿势详解
  • 清空需要恢复数据的数据表的全部记录,避免主键、唯一键约束的冲突

因为要恢复的是商品表,所以清空商品表的全部记录:

delete from flash.goods;

之前也提到了最近的操作一般记录在序号最大的binlog文件中,所以得查询数据库中的binlog文件名:

然后使用binlog2sql解析指定的binlog日志,具体命令如下:

[[email protected] ~/binlog2sql]# python3 binlog2sql/binlog2sql.py -uadmin -p‘Abc_123456‘ -dflash -tgoods --start-file=‘PXC-Node3-bin.000003‘ > /home/PXC-Node3-bin.000003.sql
  • binlog2sql/binlog2sql.py:被执行的Python文件
  • -u:用于连接数据库的账户
  • -p:数据库账户的密码
  • -d:指定逻辑库的名称
  • -t:指定数据表的名称
  • --start-file:指定需要解析的binlog的文件名
  • /home/PXC-Node3-bin.000003.sql:指定将解析生成的SQL写到哪个文件

接着查看解析出来的SQL内容:cat /home/PXC-Node3-bin.000003.sql。这里截取了有用的部分,如下图,可以看到delete语句和insert语句都有我们要恢复的数据:

能得到这些语句接下来就简单了,要么将delete语句转换成insert语句,要么直接复制insert部分的SQL语句到数据库上执行即可。我这里就直接复制insert语句了:

INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (1, ‘蛋糕‘, ‘好吃‘, ‘1‘); #start 3170 end 3363 time 2020-01-27 18:00:11
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (2, ‘柠檬茶‘, ‘爽过吸大麻‘, ‘1‘); #start 3459 end 3664 time 2020-01-27 18:00:56
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (3, ‘豆奶‘, ‘好喝‘, ‘0‘); #start 3760 end 3953 time 2020-01-27 18:01:10
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (4, ‘窝窝头‘, ‘一块钱四个‘, ‘1‘); #start 4049 end 4254 time 2020-01-27 18:01:37
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (5, ‘鸡腿‘, ‘鸡你太美‘, ‘0‘); #start 4350 end 4549 time 2020-01-27 18:02:08
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (6, ‘苹果‘, ‘xxxx‘, ‘1‘); #start 5052 end 5243 time 2020-01-27 18:06:24
INSERT INTO `flash`.`goods`(`id`, `name`, `desc`, `status`) VALUES (7, ‘香蕉‘, ‘xxxx‘, ‘1‘); #start 5339 end 5530 time 2020-01-27 18:06:24

执行完以上SQL后,可以看到成功恢复了商品表中被删除的数据:

原文地址:https://blog.51cto.com/zero01/2468486

时间: 2024-10-05 19:02:16

当删库时如何避免跑路的相关文章

从删库到恢复到跑不了路-数据恢复工程师解说顺丰删库事件

本文由北亚数据恢复中心(http://www.frombyte.com)张宇所写,如有错误,祝愿各位中秋节删库还跑不了路. 事件回顾: 据悉,顺丰科技数据中心的一位邓某因误删生产数据库,导致某项服务无法使用并持续590分钟.事发后,顺丰将邓某辞退,且在顺丰科技全网通报批评.真实地玩了一把"从删库到跑路".毫无疑问地,我们又突然象被打了鸡血般,整了整衣领,挺了挺胸,存在感立马爆棚,拉个小板凳,就着中秋节的月光,絮絮叨叨地讲讲想当年.想当年,我国那啥机构,设备升级改造,生产库在线热迁,脚本

记一次差点删库跑路的事故

故事这样发生的,那是一个中午.... 老板:小a呀,咱测试项目部署在百度云服务器上,测试数据库部署在阿里云上,为了节省点流量,你把阿里云上的测试数据库迁移到百度云上吧. 小a : 好的,老板. 小a登陆测试服务器一看,咦?竟然有mysql的服务在跑,试着登陆了一下,密码不对,于是他仔细想了想,好像并没有任何项目用到这个数据库,这...是什么情况,难道是centos自带的吗 于是小a去问了度娘,还真的有centos自带mysql这一说,为了减少数据库版本不一致可能会导致的麻烦,小a果断卸载了原本的

又一次redis被删库跑路,索要0.6比特币

还在和媳妇儿逛街,突然同事打来电话说redis库被清空. 于是,媳妇儿说你真是乌鸦嘴,早上还说redis如何被提权的事情. 怎么刚出来就碰上了? 会不会是你搞的? 于是无形中又背锅了. 见×××姐如此着急,边安慰,边提醒让同事查一下,是什么时候发生的事情,受害面积有多大? 但是×××姐很镇静的说,不可以啊,我们ucloud云商上的redis的机器,是禁止外网登录的,所有外网的6379端口都被禁用了. 仅限本机登录,于是,我问你有加密码嘛?×××姐说,便于程序研发效率,内网环境,自然就没有加密码.

“删库跑路”这件事情真的发生了 ,还是技术总监干的!

程序员经常相互开玩笑说,大不了我们"删库跑路",这是一句玩笑话,基本上也没有人这样干,但是这两天我看到了一个新闻,真有人这样干了,还是一名技术总监. 事情的经过大概是这样子的: 邱某是某某科技公司的技术总监,2014年入职到杭州的一家科技公司,这家公司的主业业务是提供 SaaS 服务. 从2014年入职到2018年,公司的主要系统都由他搭建,包括公司的SAAS系统.API系统.电子合同的签署等服务,2018年初公司大概有4万多用户. 不知道由于什么样的原因,2018年4月,老板宓某某找

删库跑路的背后,是企业对数据安全的反思

这几天,一直在关注微盟删库事件的进展,在3月1日晚上,微盟发布最新公告称数据已经全面找回.而此时,距离事故发生的2月23日晚,过了有足足七天七夜,也就是7*24小时. 01  关于“删库跑路"的段子一直都在,而这样的真实事件也不是第一次发生了. 2018年6月,某科技公司总监因为被离职而一气之下删除了公司数据库上的一些关键索引和部分表格.虽然他事后察觉后果严重,进行了恢复,但依然给该公司造成了经济损失,被判处有期徒刑二年六个月,缓刑三年. 2018年9月,顺丰出现过一位高级工程师因手误删除了线上

Oracle删库跑路

--10g R2 startup mount exclusive restrict; alter system enable restricted session; drop database; --11g startup mount exclusive; alter system enable restricted session; drop database; --RAC 12.1.0.2.0删库 1.先停止所有节点实例 2.在其中一节点操作,先关闭rac模式 startup nomount

P5270 无论怎样神树大人都会删库跑路

题目地址:P5270 无论怎样神树大人都会删库跑路 暴力模拟都会吧...... 50分代码: #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 6; int n, T, Q, m, c[N], r[N], mx, cnt, d[N], ans, s[N], now; vector<int> e[N]; queue<int> q; int main() { cin >> n &g

程序员如何彻底地删库跑路

原文:程序员如何彻底地删库跑路 删除是删除数据最便捷的方法,如 Linux 用户最经常采用rm删除命令.实际上并没有真正的将数据从硬盘上删除,只是将文件的索引删除而已,让操作系统和使用者认为文件已经删除,又可以把腾出空间存储新的数据.数据恢复极易恢复此类不见的数据,而且也有很多专门进行数据恢复的软件. 彻底删除的原理:磁盘可以重复使用,前面的数据被后面的数据覆盖后,前面的数据被还原的可能性就大大降低了,随着被覆盖次数的增多,能够被还原的可能性就趋于 0,但相应的时间支出也就越多. 覆盖原理(ov

理解Linux文档的默认安全机制、隐藏属性、特殊权限,妈妈在也不用担心你从删库到跑路!!!

写在前面 前面的章节 详解Linux文档属性.拥有者.群组.权限.差异,介绍了文档的基本权限,包括读写执行(r,w,x),还有若干的属性,包括是否为目录(d).文件(-).链接文件(l).拥有者.所属群组.容量大小(字节数).最后修改时间等等,可以通过chown.chgrp.chmod来变更这些属性和权限. 默认安全机制 首先,我们使用管理员root账户分别创建文件file001和目录dir001: 从上图可以看到, 文件file001的默认权限为rw-r--r--,即拥有者可读写,同群组下账户