当前位置: 首页 > news >正文

一个案例讲明白!如何更安全地实现数据备份和恢复

47201336776777e0937c71d0e060f4da.gif

9598108955bdcdfb01673349f360d38f.png

导读:对于任何一个企业来说,数据安全的重要性不言而喻。凡是涉及数据的问题,都是会造成惨重损失的大问题。能够影响数据安全的事件,都是极小概率的事件,但这些事件一旦发生,我们的业务就会遭受惨重损失。

所谓防患于未然,一个系统从设计的第一天起,就需要考虑今后在出现各种问题的时候,如何保证该系统的数据安全性。本文就来讲解如何做好提前预防,以尽量将由数据安全类问题而导致的损失降到最低。

df7512560e551f09ec2baefa05ec1ca0.png

e6d7fcd6e2eb1e67cec51bf9d0da033a.png

保证数据安全,最简单且有效的方法就是定期备份数据,这样无论因为出现何种问题而导致的数据损失,都可以通过备份来恢复数据。但是,如何备份才能最大程度地保证数据安全,并不是一件简单的事情。

2018年曾出现过一次重大故障,某著名云服务商因为硬盘损坏,导致多个客户数据全部丢失。通常来说,一个大的云服务商,数据通常都会有多个备份,即使硬盘损坏,也不会导致数据丢失的重大事故,但是因为各种各样的原因,最终的结果是数据的三个副本都被删除,数据丢失无法找回。

所以,并不是简单地定期备份数据就可以高枕无忧了。下面就以最常用的MySQL为例来讲解,如何更安全地实现数据的备份和恢复。

最简单的备份方式就是全量备份。备份的时候,把所有的数据复制一份,存放到文件中,恢复的时候再把文件中的数据复制回去,这样就可以保证恢复之后,数据库中的数据与备份时的数据是完全一样的。在MySQL中,我们可以使用mysqldump命令执行全量备份。

比如,全量备份数据库test的命令如下:

1$mysqldump -uroot -p test > test.sql

备份出来的文件是一个SQL文件,文件的内容就是创建数据库、表,写入数据等之类的SQL语句,如果要恢复数据,则直接执行这个备份的SQL文件就可以了:

1$mysql -uroot test < test.sql

不过,全量备份的代价非常高,为什么这么说呢?

首先,备份文件包含了数据库中的所有数据,占用的磁盘空间非常大;其次,每次备份操作都要拷贝大量的数据,备份过程中会占用数据库服务器大量的CPU和磁盘IO资源。同时,为了保证数据一致性,备份过程中很有可能会锁表。这些都会导致在备份期间,数据库本身的性能严重下降。所以,我们不能频繁地对数据库执行全量备份操作。

一般来说,在生产系统中,每天执行一次全量备份就已经是非常频繁的了。这就意味着,如果数据库中的数据丢失了,就只能恢复到最近一次全量备份的那个时间点,这个时间点之后的数据是无法找回的。也就是说,因为全量备份的代价比较高,不能频繁地执行备份操作,所以全量备份不能做到完全无损的恢复。

既然全量备份代价太高,不能频繁执行,那么有没有代价较低的备份方法,能让我们的数据少丢失甚至不丢失呢?增量备份可以达到这个目的。相比于全量备份,增量备份每次只用备份相对于上一次备份发生了变化的那部分数据,所以增量备份的速度更快。

MySQL自带的Binlog,就是一种实时的增量备份工具。Binlog所记录的就是MySQL数据变更的操作日志。开启Binlog之后,MySQL中数据的每次更新操作,都会记录到Binlog中。Binlog是可以回放的,回放Binlog,就相当于是把之前对数据库中所有数据的更新操作,都按顺序重新执行一遍,回放完成之后,数据自然就恢复了。这就是Binlog增量备份的基本原理。很多数据库都有类似于MySQL Binlog的日志工具,原理也与Binlog相同,备份和恢复的方法也与之类似。

下面就来通过一个例子,讲解如何使用Binlog进行备份和恢复。首先,使用“show variables like '%log_bin%'”命令确认一下是否开启了Binlog功能:

1mysql> show variables like '%log_bin%';
 2
 3+---------------------------------+-----------------------------------+
 4
 5| Variable_name                   | Value                             |
 6
 7+---------------------------------+-----------------------------------+
 8
 9| log_bin                         | ON                                |
10
11| log_bin_basename                | /usr/local/var/mysql/binlog       |
12
13+---------------------------------+-----------------------------------+
14
15mysql> show master status;
16
17+-------------+--------+------------+----------------+-----------------+
18
19| File        |Position|Binlog_Do_DB|Binlog_Ignore_DB|Executed_Gtid_Set|
20
21+-------------+--------+------------+----------------+-----------------+
22
23|binlog.000001|   18745|            |                 |                 |
24
25+-------------+--------+------------+----------------+-----------------+
26

我们可以看到,当前这个数据库已经开启了Binlog,log_bin_basename表示Binlog文件在服务器磁盘上的具体位置。然后,我们用“show master status”命令查看当前Binlog的状态,结果显示了正在写入的Binlog文件,以及其当前的位置。假设我们每天凌晨用mysqldump做一个全量备份,然后开启Binlog,借助于这些备份操作,我们可以把数据恢复到全量备份之后的任意一个时刻。

下面就来做一个简单的备份恢复演示。我们先模拟一次“删库跑路”的场景,直接把账户余额表清空:

1mysql> truncate table account_balance;
2
3Query OK, 0 rows affected (0.02 sec)
4
5mysql> select * from  account_balance;
6
7Empty set (0.00 sec)
8

然后进行数据恢复,首先执行一次全量恢复,把数据库恢复到当天凌晨的状态:

1$mysql -uroot test < dump.sql
 2
 3mysql> select * from  account_balance;
 4
 5+---------+---------+---------------------+--------+
 6
 7| user_id | balance | timestamp           | log_id |
 8
 9+---------+---------+---------------------+--------+
10
11|       0 |     100 | 2020-02-13 20:24:33 |      3 |
12
13+---------+---------+---------------------+--------+

可以看到,表里面的数据已经恢复了,但还是比较旧的数据。接下来,我们再用Binlog把数据恢复到“删库跑路”之前的那个时刻:

1$mysqlbinlog --start-datetime "2020-02-20 00:00:00" --stop-datetime "2020-02-20 15:09:00" /usr/local/var/mysql/binlog.000001 | mysql -uroot
 2
 3mysql> select * from  account_balance;
 4
 5+---------+---------+---------------------+--------+
 6
 7| user_id | balance | timestamp           | log_id |
 8
 9+---------+---------+---------------------+--------+
10
11|       0 |     200 | 2020-02-20 15:08:12 |      0 |
12
13+---------+---------+---------------------+--------+
14

由恢复结果可以看出,数据已经恢复到当天的15点了。

通过定期的全量备份,配合Binlog,我们可以把数据恢复到任意一个时间点,再也不怕程序员“删库跑路”了。详细的命令,可以参考MySQL官方文档中的“备份和恢复”相关章节。

在执行备份和恢复的时候,大家需要特别注意如下两个要点。

第一,也是最重要的,“不要把所有的鸡蛋放在同一个篮子中”,无论是全量备份还是Binlog,都不要与数据库存放在同一个服务器上。最好能存放到不同的机房,甚至不同城市,离得越远越好。这样即使出现机房着火、光缆被挖断甚至地震也不怕数据丢失。

第二,在回放Binlog的时候,指定的起始时间可以比全量备份的时间稍微提前一点儿,这样可以确保全量备份之后的所有操作都在恢复的Binlog范围内,从而保证数据恢复的完整性。

因为回放Binlog的操作是具备幂等性的(为了确保回放的幂等性,需要将Binlog的格式设置为ROW格式)。

关于作者:李玥,美团基础技术部高级技术专家,极客时间《后端存储实战课》《消息队列高手课》等专栏作者。曾在当当网、京东零售等公司任职。从事互联网电商行业基础架构领域的架构设计和研发工作多年,曾多次参与双十一和618电商大促。专注于分布式存储、云原生架构下的服务治理、分布式消息和实时计算等技术领域,致力于推进基础架构技术的创新与开源。

听听作者怎么说👇

本文摘编自《电商存储系统实战:架构设计与海量数据处理》

e331713af4732733d4af406dbb9585a0.png

点击以下链接了解及购买

转载请联系微信:zj06220_0

推荐语:本书将以电商应用场景为例,讲解不同规模的存储系统应该如何构建。电商系统覆盖面广,在其他业务中遇到的技术问题,大多数在电商系统中也会遇到。本书以电商应用场景为例,讲解实战过程中常会遇到的各种存储问题。通过这样的学习方式,用户既可以快速地解决实际问题,还能提升技术能力。全书共18章,分为设计篇、高速增长篇、海量数据篇和技术展望四篇。

【新书速递】如何高效学习存储系统?一本书全都讲明白

ad1db73fbb7c07d029eab864ce8ac7d2.gif

更多精彩回顾

书讯 | 4月书讯 | 好书和最美四月天一起来了...

资讯 | DB-Engines 4月数据库排名:Redis有望甩掉“千年老七”?

书单 | 8本书助你零基础转行数据分析岗

干货 | 什么是架构?网络架构中都有什么?终于有人讲明白了

收藏 | 终于有人把Scrapy爬虫框架讲明白了

上新 | 河马书来了!线上实验领域的“圣经”火热预售中

直播 | 筑牢“数据基座” 掘金数字经济——5位大咖畅聊金融科技

活动 | Book多得的奇遇,给爱读书的你们最大的优惠力度

1e3a88c56f34b0986d7e32775296e397.gif

85e56f8bcd893ea992f254a8a442143f.gif

点击阅读全文购买

相关文章:

  • 省政协委员、南京大学人工智能学院院长周志华: 科研学习探索最重要的是“兴趣”和“勤奋”...
  • 为什么现在还有985高校给大一上C语言课?
  • 如何用数字化构建企业的“韧性”?
  • 前端应用和产品逻辑的核心:交互流
  • 2月书讯 (上)| 新年到,新书到!
  • 2月书讯(下)| 新年到,新书到!
  • Three.js 的 3D 粒子动画:群星送福
  • 如何平衡存储系统的一致性和可用性?
  • 浅谈压缩算法的那些事儿
  • 终于有人把SaaS讲明白了
  • 【第90期】关于数据分析师的学习路线,这是我见过最全面的
  • 未来 5 年,数据中台将有这 5 个重要趋势
  • 冬奥会开幕式震撼刷屏,这些黑科技立了大功!
  • 写给前端的跨平台方案、跨端引擎的本质
  • 为什么《Effective Java 第三版》推荐使用try-with-resources代替try-finally
  • android 一些 utils
  • Java 23种设计模式 之单例模式 7种实现方式
  • Mybatis初体验
  • nginx 负载服务器优化
  • python 装饰器(一)
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 读懂package.json -- 依赖管理
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 关于for循环的简单归纳
  • 聊聊redis的数据结构的应用
  • 前端面试之CSS3新特性
  • 巧用 TypeScript (一)
  • 如何进阶一名有竞争力的程序员?
  • 说说动画卡顿的解决方案
  • 无服务器化是企业 IT 架构的未来吗?
  • 正则表达式小结
  • Python 之网络式编程
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • (23)Linux的软硬连接
  • (C语言)逆序输出字符串
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (利用IDEA+Maven)定制属于自己的jar包
  • (算法设计与分析)第一章算法概述-习题
  • .jks文件(JAVA KeyStore)
  • .Net Core与存储过程(一)
  • .net 反编译_.net反编译的相关问题
  • .NET 依赖注入和配置系统
  • .net反编译工具
  • .NET委托:一个关于C#的睡前故事
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [ SNOI 2013 ] Quare
  • [C/C++]数据结构 循环队列
  • [C++]C++类基本语法
  • [CF494C]Helping People
  • [dart学习]第四篇:函数
  • [go] 迭代器模式