本文转载自微信公众号「数仓宝贝库」,作者李玥 。转载本文请联系数仓宝贝库公众号。
保证数据安全,最简单且有效的方法就是定期备份数据,这样无论因为出现何种问题而导致的数据损失,都可以通过备份来恢复数据。但是,如何备份才能最大程度地保证数据安全,并不是一件简单的事情。
2018年曾出现过一次重大故障,某著名云服务商因为硬盘损坏,导致多个客户数据全部丢失。通常来说,一个大的云服务商,数据通常都会有多个备份,即使硬盘损坏,也不会导致数据丢失的重大事故,但是因为各种各样的原因,最终的结果是数据的三个副本都被删除,数据丢失无法找回。
所以,并不是简单地定期备份数据就可以高枕无忧了。下面就以最常用的MySQL为例来讲解,如何更安全地实现数据的备份和恢复。
最简单的备份方式就是全量备份。备份的时候,把所有的数据复制一份,存放到文件中,恢复的时候再把文件中的数据复制回去,这样就可以保证恢复之后,数据库中的数据与备份时的数据是完全一样的。在MySQL中,我们可以使用mysqldump命令执行全量备份。
比如,全量备份数据库test的命令如下:
- 1$mysqldump -uroot -p test > test.sql
备份出来的文件是一个SQL文件,文件的内容就是创建数据库、表,写入数据等之类的SQL语句,如果要恢复数据,则直接执行这个备份的SQL文件就可以了:
- $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电商大促。专注于分布式存储、云原生架构下的服务治理、分布式消息和实时计算等技术领域,致力于推进基础架构技术的创新与开源。
本文摘编自《电商存储系统实战:架构设计与海量数据处理》,经出版方授权发布。(ISBN:9787111697411)转载请保留文章出处。