mysql中怎么防止数据丢失

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: mysql中怎么防止数据丢失

前言


放假期间,突然接到老板电话,说系统出现了数据丢失问题,犹如晴天霹雳,内心慌得一批已经准备卷铺盖回家。


今天主要给大家分享mysql数据库出现数据丢失的几个场景以及解决数据丢失问题的相应手段,让大家以后心里有谱,放假不慌。


一、事务级数据丢失


说明:

1、批量操作数据时,由于没有添加事务控制,出现事务回滚时,出现部分数据操作成功,部分数据操作失败的问题。

2、事务提交成功到数据还没有刷写到磁盘,出现数据库宕机导致的数据丢失

范围: 事务级

严重级别: 低

处理手段:


添加事务控制

开启redo log、undo log

采用强一致日志刷写策略


1、开启事务控制

示例:批量保存用户信息

@Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveBatch(Collection<User> entityList, int batchSize) {
        try {
            int size = entityList.size();
            int idxLimit = Math.min(batchSize, size);
            int i = 1;
            //保存单批提交的数据集合
            List<User> oneBatchList = new ArrayList<>();
            for(Iterator<User> var7 = entityList.iterator(); var7.hasNext(); ++i) {
                User element = var7.next();
                oneBatchList.add(element);
                if (i == idxLimit) {
                    userMapper.insertBatchSomeColumn(oneBatchList);
                    //每次提交后需要清空集合数据
                    oneBatchList.clear();
                    idxLimit = Math.min(idxLimit + batchSize, size);
                }
            }
        }catch (Exception e){
            log.error("saveBatch fail",e);
            return false;
        }
        return  true;
    }


2、开启redo log、undo log

mysql中只有InnoDB引擎支持事务,而事务机制的实现离不开redo log和undo log。

默认情况下都是开启的,不需要主动调整。但如果出现事务级别的数据丢失,就需要检查相关配置。


redo log:重做日志

undo log:回滚日志

Redo Log(重做日志)是MySQL中非常重要的日志模块。

官方解释:重做日志是一种基于磁盘的数据结构,用于在崩溃恢复期间纠正不完整事务写入的数据。

在正常操作期间,重做日志对由SQL语句或低级API调用产生的更改表数据的请求进行编码。在初始化期间和接受连接之前,会自动重播在意外关闭之前未完成更新数据文件的修改).

MySQL里经常说到的WAL技术(WAL的全称是Write-Ahead Logging),它的关键点就是日志先行(也称为写前日志,实际写数据之前,先把修改的数据记录到日志文之间中。即先写日志,再写磁盘),其实很多数据库软件设计的理念都是日志先行。(但是Redis的AOF(Append Only File)日志正好相反,它是写后日志,“写后”的意思是Redis的先执行命令,把数据写入内存,然后才记录日志),MySQL中日志先行的这个“日志”就是Redo Log。


Redo Log是InnoDB引擎特有的日志,而MySQL Server层也有自己的日志,称为binlog(不在我们本文的讨论范围,下一章我们就会见到它了,拭目以待吧)。正是因为有了Redo Log,才保证了InnoDB存储引擎的Crash-safe能力。


Redo Log是物理日志,记录的是“在某个数据页上做了什么修改(做了什么改动)”。一句话概括一下,Redo Log是为了保证已提交事务的ACID特性,同时能够提高数据库性能的技术。

90.png


3、Redo log刷写策略

我们都知道,数据只有刷写到磁盘中才是最安全的,redo log从内存到刷写到磁盘经历了三层结构。


Redo Log的三层结构:

89.png

简单来说一下Redo Log的三层结构:


粉色部分:是InnoDB一项很重要的内存结构(In-Memory Structure),即我们的Log Buffer(日志缓冲区),这一层,是MySQL应用程序用户态控制。

黄色部分:操作系统文件系统的缓冲区(FS Page Cache),这一层,是操作系统OS内核态控制。

绿色部分:就是落盘的物理日志文件。

Redo Log刷写时机:

Redo log目前有三种刷写策略,即对应可设置的值可以是0、1或2。

88+.png


策略一:最佳性能(innodb_flush_log_at_trx_commit=0)

处理过程:每隔一秒,才将Log Buffer中的数据批量write入FS Page Cache,同时MySQL主动fsync。

缺点:这种策略,如果数据库奔溃,有一秒的数据丢失。

策略二:强一致(innodb_flush_log_at_trx_commit=1)

处理过程:每次事务提交,都将Log Buffer中的数据write入FS Page Cache,同时MySQL主动fsync。这种策略,是InnoDB的默认配置,为的是保证事务ACID特性。

缺点:这种策略,性能较其余两种策略较差。

策略三:折衷(innodb_flush_log_at_trx_commit=2)

处理过程:每次事务提交,都将Log Buffer中的数据write入FS Page Cache;每隔一秒,MySQL主动将FS Page Cache中的数据批量fsync。

缺点:这种策略,如果操作系统奔溃,最多有一秒的数据丢失。(因为OS也会fsync,MySQL主动fsync的周期是一秒,所以最多丢一秒数据。磁盘IO次数不确定,因为操作系统的fsync频率并不是MySQL能控制的)

综上,为了防止事务级数据丢失,必须设置redo log的刷写级别为强一致(innodb_flush_log_at_trx_commit=1)


二、page级数据丢失


说明: 由于mysql数据页page损坏出现的数据丢失

范围: page级

严重级别: 中

处理手段:


开启Doublewrite Buffer,默认开启

Linux文件系统页(OS Page)的大小是4KB,MySQL的页(Page)大小默认是16KB,

所以MySQL将Buffer Pool中一页数据刷入磁盘,要写4个文件系统里的页(也可以说成一个MySQL数据页映射4个系统页)。

87.png

如上图所示,MySQL里Page 1的页,物理上对应磁盘的Page 1、Page 2、Page 3、Page 4四个页。

这个操作并非原子,如果执行到一半断电,会不会出现问题呢?

答案:会,这就是所谓的“页数据损坏”。


MySQL内Page 1的页准备刷入磁盘,才刷了3个文件系统里的页,掉电了,则会出现:重启后,MySQL内Page 1的页,物理上对应磁盘上的Page 1、Page 2、Page 3三个页,数据完整性被破坏。(Redo Log无法修复这类“页数据损坏”的异常,因为Redo Log修复的前提是“页数据正确”并且Redo日志正常)


针对上面出现的情况,如何解决这类“页数据损坏”的问题呢?


很容易想到的方法是,能有一个“副本”,对原来的页进行还原,这个存储“副本”的地方,就是Doublewrite Buffer。Doublewrite Buffer,它与传统的“Buffer”又不同,它分为内存和磁盘的两层架构。(传统的“Buffer”,大部分是内存存储;而DWB里的数据,是需要落地的)


Doublewrite Buffer工作流程:

86.png

如上图所示,当有页数据要刷盘时:


第1步:页数据先memcopy到DWB的内存里;

第2步:DWB的内存里的数据页,会先刷到DWB的磁盘上;

第3步:DWB的内存里的数据页,再刷到数据磁盘存储.ibd文件上;

备注:DWB内存结构由128个页(Page)构成,所以容量只有:16KB × 128 = 2MB。


DWB为什么能解决“页数据损坏”问题呢?

假设步骤2掉电,磁盘里依然是Page 1、Page 2、Page 3、Page 4的完整数据。只要有页数据完整,就能通过Redo Log还原数据;假如步骤3掉电,DWB磁盘结构里存储着完整的数据。所以,一定不会出现“页数据损坏”问题。同时写了DWB磁盘和Data File,总有一个地方的数据是OK的。


是否开启DoubleWrite


SHOW VARIABLES LIKE 'innodb_doublewrite';


85.png


三、磁盘级数据丢失


说明: 磁盘损坏导致的数据丢失

范围: 磁盘级

严重级别: 严重

处理手段:


磁盘矩阵

数据库集群

冷热备份

不要以为数据正确完整的写到磁盘上就万事大吉,在程序整体架构的考虑中,除了软件层面的问题,必须还要考虑硬件层面的风险。

比如,由于Mysql存储数据的磁盘由于故障损坏了,造成了整个系统的数据丢失,这样的情况将使灾难性的。那么我们该如何应对磁盘级的数据丢失风险呢?其核心就是就好数据备份。


磁盘矩阵

核心是利用多块磁盘的冗余存储,保障即是一块磁盘损坏也不会出现数据丢失。


RAID1 是磁盘阵列中单位成本最高的一种方式。因为它的原理是在往磁盘写数据的时候,将同一份数据无差别的写两份到磁盘,分别写到工作磁盘和镜像磁盘,那么它的实际空间使用率只有50%了,两块磁盘当做一块用,这是一种比较昂贵的方案。

84.png

优点:是简单,一般做硬件运维的同事都能操作。

缺点:成本较高,备份数据的精读较粗,一般是整个服务器级别,往往是财大气粗的政府机关和银行在使用。另外不能做到远程宰备,如果整机房都出了问题,往往还是会出现数据丢失。


数据库集群备份Replication

通过搭建mysql数据库集群,让集群中每台服务器保存完整的数据库信息,这样即使一台服务器上的数据出现了丢失,也能从备份的数据库中找回。

而且mysql的主备数据库可以实现无感知的切换,宅难恢复的速度更快。

而且通过主备数据库,也可以方便实现数据库的读写分离,缓解单台数据库上的读写压力。

是目前最主流的数据库灾备方式。

83.png

优点:程序级别的数据备份,更节省成本,能较方便的实现远程备份,宅难恢复更快。

缺点:如果是程序勿操作导致的数据丢失,从库也会执行相同操作,造成数据无法找回。


冷热备份

MySQL备份功能在实际应用中的重要程度不需要多说,在误删重要数据后或者数据库被攻击后,备份数据的作用就突显出来了。


MySQL备份方式从不同的角度分析有不同的分类。 从运行状态分析,有冷备份和热备份之分。冷备份一般是在数据库关闭或者暂时不对外提供服务时,选择某一时间节点对完整数据库进行快照备份。热备份一般是在数据库运行的状态下,直接对数据进行备份,不影响MySQL对外提供服务。这里主要讲下这两种方式的实现。


直接通过MySQL自带的mysqldump工具进行备份


-- 数据备份
mysqldump -uroot -proot test > /data/backup/test.sql
-- 数据恢复
mysql -f -uroot -proot test < /data/backup/test.sql


一般将备份的数据文件存放在其他服务器上。


总结


本文主要对mysql数据库数据丢失的几种常见场景进行了介绍。作为程序开发者可能只需要注意程序开发中过程中事务的使用规范,但是如果作为项目负责人、架构师等视角来看,必须把数据库运维的问题也考虑在内,做到软硬件风险全盘考虑,防止出现重大事故。


事务级数据丢失:添加事务控制,开启Redo log并采用强一致(innodb_flush_log_at_trx_commit=1)刷写机制。

数据页损坏级别的数据丢失:数据双写机制double wirte

如何防止磁盘级别的数据丢失:磁盘矩阵,数据库集群,数据库冷热备份。


MySQL各种“Buffer”之Doublewrite Buffer

MySQL各种“Buffer”之Log Buffer

MySQL的冷热备份

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
存储 NoSQL 关系型数据库
redis与mysql的数据一致性问题(数据丢失)
redis与mysql的数据一致性问题(数据丢失)
14 0
|
11月前
|
关系型数据库 MySQL 程序员
使用Mysql Navcat导出查询数据excel时出现数据丢失
使用Mysql Navcat导出查询数据excel时出现数据丢失
105 0
|
SQL JavaScript 安全
php操作mysql防止sql注入(合集)
php操作mysql防止sql注入(合集)
324 0
|
SQL 安全 前端开发
网站mysql防止sql注入攻击 3种方法总结
mysql数据库一直以来都遭受到sql注入攻击的影响,很多网站,包括目前的PC端以及手机端都在使用php+mysql数据库这种架构,大多数网站受到的攻击都是与sql注入攻击有关,那么mysql数据库如何防止sql注入呢?下面我们SINE安全技术针对于这个sql注入问题总结3种方案去防止sql注入攻击。
888 0
网站mysql防止sql注入攻击 3种方法总结
|
关系型数据库 MySQL
MySQL防止重复插入相同记录 insert if not exists
MySQL防止重复插入相同记录 insert if not exists
1210 0
|
关系型数据库 MySQL 数据库
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
441 0
公司mysql docker容器挂了,数据丢失,老板要起诉我。。
|
SQL 关系型数据库 MySQL
mysql防止注入的模糊查询
mysql防止注入的模糊查询
347 0
mysql防止注入的模糊查询
|
关系型数据库 MySQL 数据库
【MySQL】如何最大程度防止人为误操作MySQL数据库?这次我懂了!!
今天,一位哥们打电话来问我说误操作了他们公司数据库中的数据,如何恢复。他原本的想法是登录数据库update一个记录,结果忘了加where条件,于是悲剧发生了。今天,我们不讲如何恢复误操作的数据(后面专门讲如何恢复误删除的数据),我们讲讲如何从源头上避免这样的问题,这才是避免类似问题的根本措施。
146 0
|
关系型数据库 MySQL
再也不怕数据丢失!阿里云RDS MySQL 8.0上线回收站功能
MySQL 在生产环境使用过程中,会伴随着开发和运维人员的误操作,比如 DROP TABLE / DATABASE,这类 DDL 语句不具有可操作的回滚特性,而导致数据丢失,AliSQL 8.0 新特性支持回收站功能(Recycle Bin),临时把删除清理的表转移到回收站,并保留可设置的时间。
5401 0