Py学习  »  DATABASE

做了这么久的 DBA,你真的认识 MySQL 数据安全体系?

高效运维 • 6 年前 • 655 次点击  

作者介绍:

强昌金 

去哪儿网 高级DBA
2015年加入去哪儿,担任MySQL DBA,主要负责去哪儿数据库管理平台的开发、MySQL和Redis的运维。在数据库方面,具有丰富的数据库运维、性能优化经验。

给大家分享下有关MySQL在数据安全的话题,怎么通过一些配置来保证数据安全以及保证数据的存储落地是安全的。

我是在2014年加入陌陌,2015年加入去哪儿网,做MySQL的运维,包括自动化的开发。

接下来我将从四个方面给大家介绍一下,数据库怎么通过一些配置做到数据安全的。

  • 单机安全

  • 集群安全

  • 备份安全

  • 发展

现在的行业中,数据是一个非常重要的资产。

数据是怎么保证安全呢?在日常中,大家都认为一些商业的数据库能更好的保证数据安全。他们认为对于新兴的MySQL来说,一致认为可以在互联网使用,因为互联网的数据丢了也就无所谓了,我感觉他们这是对MySQL数据库的一个误解。

我所说的数据安全是指数据落地的安全,而不是遭到黑客攻击,也不包括网络安全。

在企业刚开始起步的时候有可能资源有限,只使用单机,这时候单机有可能部署一个。

随着企业的发展,有可能单机会存在数据崩溃的问题,这将导致整个数据不可用的。因此就会往集群化的方向发展,会利用主从模式,保证数据分布到多个节点,即使某个节点崩溃后,还有其他节点是可用的。

这样就能保证真正的数据不丢吗?有可能机房出现了网络故障,或者整个机房宕机了。今年也遇到过很多整个数据不可用,备份也不可用的情况,这时候数据就丢失了。

为了更好的是保证数据安全,要进行备份。要对数据进行本地备份和远程备份,这样集群不可用的时候利用备份进行恢复。

第四方面,介绍一下MySQL基本的发展。

下面详细的对这四个部分来进行阐述。

一. 单机安全

单机安全会涉及到两个配置参数:

  • Double Write

  • innodb_flush_log_at_trx_commit

下面详细说明。

1.1 Double Write

我们企业在刚刚起步的时候只有一个节点,怎么保证我们的数据落盘?在MySQL宕机或者系统宕机数据库启动的时候它能够启起来。在启动过程中,他们会检测数据页是否是正常的,这时候我们会引入一个叫Double Write。

什么叫Double Write?对一个页面的所有操作,包括页头、页面等等,这原本是物理的操作。但是为了节约日志量,把它改成逻辑的,就会记录包括空间数、内容字段等等,等到有必要的时候才真正的将这些逻辑写变成物理写。

在写的过程中,首先保证所写的页面是正确的。如果一个页面在写的过程中由于多次写导致页面断裂,这样就不可写。这时候我们就需要一个Double Write,等于现在一个是镜像,另一个是备份。

MySQL 5.7之前有一个2M的缓存。如果在校验的过程中,这个页面有问题,就会利用Double Write将两个页面进行拷贝回来,这样我们的数据库就恢复到可用的状态。

四个问题:

  • 两次写本身页面断裂会不会有问题?
    它所要操作页面之前,记录的是数据库之前的状态是一致的。这时页面出现问题,本身就不会去写入了,就不会出现问题。

  • 最近数据是不是一直在覆盖?
    因为我们知道只有2M的空间,因此会一直覆盖去写。

  • 性能问题?
    我们知道在Double Write有两次写的。这对我们的操作是不是也有两次?我们知道它有一个缓存空间,当缓存空间满的时候,会将逻辑写变成顺序写,这对磁盘的影响是比较小的,不会导致性能消耗,但是也会带来一点点性能消耗。

  • 可不可以没有Double Write?
    有可能。

1.2 innodb_flush_log_at_trx_commit

数据库宕机分为两种情况:

  • 数据库宕机服务器正常

  • 服务器宕机

在宕机的时候,对提交到数据库的事务如果没有写到redo log文件中,数据就会丢失。

innodb_flush_log_at_trx_commit参数的三个值的策略:


这三个参数对数据库宕机是不是会导致数据的丢失呢?

在值为0的时候,每秒写入,在数据库宕机或者系统宕机时,都会有数据的丢失的。

在值为1的时候,每次操作都会去写入到真正的redo log的磁盘文件中,这时候不管数据库宕机还是操作系统宕机,都不会丢失。在启动的时候,redo log在文件中是可以进行恢复的。

在值为2的时候,是刷到操作系统的cache中,数据库宕机了,但是操作系统是完整的,能够写入到磁盘中,这时候数据是不会丢失的。

二. 集群安全

在单机的过程中,通过两个参数保证我们的数据落盘。然而,有可能服务器宕机了,再也启动不起来了,这时我们的数据等于是全部丢失了,或者可以利用备份数据进行恢复一部分的数据,这种情况对我们的企业就会导致一定的影响。

  • 主从复制

    • 异步复制

    • 半同步复制

  • MySQL Galera Cluster

此时,我们可以通过集群的模式,如搭建一主多从或者多主等等,来保证我们的数据在多个节点都有的,即使一个节点宕机以后,可以把读写服务切换到另一个节点,保证数据可用的。

2.1. 主从复制

2.1.1 sync_binlog

主从复制是异步的模式。

在默认情况下,我们都会使用简单的主从复制进行保证一主多节点进行同步。

在复制过程中最重要的一个东西就是sync_binlog,它在等于0的时候,每次刷新到cache中;等于1的时候会同步到磁盘中。

这个参数对数据丢失的影响:

同样数据库宕机分两种,一种是系统的宕机,一种是数据库宕机。数据库宕机已经写入到OS的cache中,因此不会丢失。如果恰好这时操作系统宕机,就等于丢失OS cache了,如果sync_binlog 值为0,将会丢失数据了。

2.1.2 binlog_format

二进制日志格式有三种:

  • STATEMENT

  • MIXED

  • ROW

我们现在主要使用ROW格式,会存在一个问题,就是我们日志量会稍微大一些。

2.1.3 与复制POS点相关参数

在主从复制过程中,有两个重要的文件:

  • 一个是记录master-info

  • 一个是记录relay-log-info

从MySQL 5.7版本,已经使用表结构了,建议这么做。

这两个sync-master-info和sync-relay-log-info参数,如果存在宕机,我们能知道之前复制的点在什么位置。

relay_log_recovery个参数,如果设置为1,它会找到MySQL线程最新执行的最后的位置,然后利用那个位置,重新创新一个relay-log,这个值对我们来讲非常重要。如果不设为1,会导致我们在启动过程中,点不是最新的点,会导致事物的冲突,甚至会导致主从复制的冲突。

2.2 半同步

主要说说一下三点:

  • 半同步复制特性

  • 半同步与异步对比

  • 半同步参数: rpl_semi_sync_master_wait_point

2.2.1 半同步复制特性

主库和从库会存在延时的,可能从库没有接收到主库的binlog信息。

MySQL 推出了一个半同步复制,就是主库会等待从库中至少一个节点,是否真正的获取到binlog日志,并且刷新到redo log文件中。

半同步有哪些特性呢?

  • 从库告知主库是否为半同步

  • 主库事务提交会被阻塞

  • 从库写入relay log后通知主库

  • 主库等待超时后,自动转换为异步复制

  • 主从必须同时开启半同步

首先会告诉主库自己是否配置了半同步,并且主库提交事物的时候,这个线程会进行阻塞,等待从库进行回复。如果真的没有回复,它会把这个从库降成异步复制。如果有回复,进行确认后,主库的线程就会继续做其他的事务,那么在这个过程中,它是会被阻塞掉的。

从库接收到主库的binlog后,会写入到redo log。

在半同步的复制过程中,每个事务提交的时候,会等待至少一个从节点,如果从节点已经获取到了binlog,这时候主节点才会真正的提交做后续的操作,这时候就可以保证至少有一个节点是和主节点的数据是一致的。

2.2.2 半同步复制特性

最主要的区别在于半同步复制能保证至少一个从节点会与主节点数据一致性。

2.2.3 rpl_semi_sync_master_wait_point

在半同步过程中,有一个重要的参数rpl_semi_sync_master_wait_point来进行控制,就是主库的线程提交事务后,在整个进程进行等待还是在提交事务以后再去等待。

首先讲一下这两个配置有什么影响。

AFTER_COMMIT提交完进入等待状态,等待一个从库,现场回复一个ACP确认。从库汇报了ACP确认后,进入后续的状态,就是将结果通知到客户端。

在这个状态的情况下,可能会导致从库丢数据,之所以这样是因为我们在引擎层已经提交了,这时候我们在等待的过程中,其实在这个主库上的其它会话是能够知道这个事务已经提交的结果。但是如果此时主库还在等待过程中主库宕机了,并且不可恢复,这时从库有可能没有接收到数据的,在主库上它认为这个事务已经提交成功了,就会导致从库根本没有拿到这个binlog,因此会丢失这个事务的数据。

为了解决这个问题,在MySQL 5.7会推出另外一种状态进行等待—-AFTER_SYNC,就是同步完立马进行等待。

如果这时候主库宕机了,从库有可能接收到这个binlog,并且应用到从库的数据库中,这时主库还没有进入到提交,因此主库的数据是没有提交的,有可能从库会多出一部分数据。

我个人认为,多出的数据,总比丢失的好。当我们的服务切入到从库,服务在处理的过程中,会根据多出来的数据做相应的处理,总比没有相对来说更好一些。

2.3 MySQL Galera Cluster

上面说的主从复制,不管使用异步复制还是半同步复制,都可能出现丢失数据的问题。去哪儿网,经过几年的发展,多年的研究,大量的在使用Galera Cluster。

MySQL Galera Cluster 注意点:

  • 基于binlog复制模式

  • DDL执行卡死

  • DDL优先

  • DDL执行过程中不能退出

  • Flow Control

在支付的业务中,我们要强烈要求数据是一致性的,这时候PRC能够非常好的满足这个特点。包括多点写入,在日常维护中经常遇到一个问题,有可能需要重启数据库,或者迁移数据库。

主从复制的架构,需要将业务的读写请求切换到另外一个节点。如果流量慢慢切入到别的节点就OK了,这时对业务的影响几乎是没有的,所以我们可以非常大胆的做一些切换操作。

double write如果我们没有开,有可能数据库就启动不起来,启动不起来也没有任何问题,因为相当于这个新的节点加入到PCRC的过程中,就会执行一个SYNC的操作,会把数据拉取过来,只不过数据恢复的时间较长一些。

redo log这个参数是为了可以提高一些性能。sync-binlog,甚至binlog都不用开。

有了集群,这时候对业务来说,对企业来说,应该比较放心了,数据应该不会丢失了。但是,今年出现了好几个案例,就是数据库机房宕机,或者集群宕机以后,没有备份可以用了,所有的数据都丢失了,我们只能强烈的依赖于备份。

今年上半年出现了两个比较大的故障,就是连备份都不可用了。这时候备份安全对我们企业,对我们业务来说是非常重要的。

三. 备份安全

备份中分为两个:

  • 数据备份

  • binlog备份

数据备份中,我们可以每天对数据,对整个机器的数据进行一个镜像,或者用别的MySQL Double等等进行备份。

binlog有可能我们在数据备份的时候也只是备份某一点的数据备份,在这次备份到下次备份之间,这种数据是怎么恢复呢?我们可以用binlog。

3.1 数据备份

备份方式分为:

  • 冷备

  • 热备

备份工具分为:

  • 逻辑备份工具

    • mysqldump

    • mysqldumper

    • mysqlpump

    • select … into outfile

  • 物理备份工具

    • InnoDB ibbackup

    • Percona XtraBackup

逻辑备份工具,就是把dump文件保存起来,这会存在一个问题,有可能dump的时间很长,恢复的时间也就很长了。

这在整个数据库想要依赖于这个备份节点恢复的时候,整个业务等待的时间就很长了。如果用逻辑备份,恢复时间越长,对业务的影响越大。所以,我们尽量采用一个物理的备份,如XtraBckup。

备份存储分为:

  • 本地存储

  • 远程存储

我们的备份数据库存储在本地的服务器上的话,可能存在备份文件不可用了,会导致数据的丢失。

因此,我们要优先考虑远程备份,可以把MySQL数据文件备份到异地的机房。

3.2 binlog备份

有了数据备份后,它只是某个点的镜像,上一次备份和下一次备份之间的数据怎么办呢?只能通过binlog了,因此也需要备份binlog,而且最好也是存到远程上。

四. 发展

我们在使用过程中,业务刚刚起步,有可能先单机模式,随着业务的发展,我们就会扩展到复制模式,随着业务的再次壮大以及业务重要性的要求,就会开始引入集群模式了,保证数据真正的不丢失,即使一个节点出现宕机,其他节点还有完整的数据。

END



更多相关文章阅读

微信月活9亿的高效运维之路

从鹿晗恋爱事件看运维的节假日准备工作

Linux Bash 提示符的一些骚操作

我们离 Google SRE 还有多远?

六个人如何运维一万台服务器?

运维需要懂的那些安全技能

运维的耻辱感



点击阅读原文关注大会官网


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/LUfR2Qrxea
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/3721
 
655 次点击