配置参数innodb_flush_log_at_trx_commit丢失数据问题

数据丢失的定义:当事务提交了,数据因为特殊原因不存在了。

MySQL默认情况下是开启内部的XA事务和事务的实现方式是基于redo log和undo log。也可以理解为MySQL事务是采用日志现行的策略。前提未开启binlog的情况下,数据的变更首先在内存中完成,并且将事务顺序的写入到redo log中,即表示该事务已经完成,就可以返回发给客户端已提交的信息。但此时变更后的数据还在内存中,并没有刷新写入到磁盘中,当达到一定条件,将内存中的数据合并写入到磁盘,即落地到磁盘。这样做的目的是提高性能,但同时也埋下了隐患。在这个过程中,如果服务器宕机,内存中数据将会丢失,重启服务器后,通过redo log日志recovery重做日志,保障了数据不会丢失。因此只要事务能够实时写入到磁盘(redo log),InnoDB存储引擎就不会丢失数据。innodb_flush_log_at_trx_commit参数设置:

0:每秒write cache和flush disk

1:每次commit都 write cache和flush disk

2:每次commit都 write cache

安全性:当innodb_flush_log_at_trx_commit设置为0,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失。当innodb_flush_log_at_trx_commit设置为2,只有在操作系统崩溃或者系统掉电的情况下,上一秒钟所有事务数据才可能丢失。

当innodb_flush_log_at_trx_commit和sync_binlog 都为1时是最安全的,在mysqld 服务崩溃或者服务器主机crash的情况下,网上说binary log只有可能丢失最多一个语句或者一个事务,这个目前没法证明只丢一条事务。但是鱼与熊掌不可兼得,都为1会导致频繁的IO操作,因此该模式也是最慢的一种方式,性能最低。

innodb_flush_log_at_trx_commit和sync_binlog是MySQL innodb引擎的两个重要的参数,其中innodb_flush_log_at_trx_commit是将事务日志从innodb log buffer写入到redo log中,sync_binlog是将二进制日志文件刷新到磁盘上。

innodb事务日志redo,binlog逻辑过程如下: 事务写入redo log buffer中--->将log buffer刷新到redo log中,不过会先写一个TX PREPARE标记--->写binlog--->在redo log中写入TX COMMIT标记--->将写binlog成功的标记写入redo log。在这个过程中,Binlog写入成功是否整个事务的关键,如果Binlog提交成功了,redolog没有成功,在重启后会执行safe crash,会在redolog中补充commit,修复数据;如果在innodb层面提交成功,binlog没有成功,重启后这个事务会回滚掉。

当innodb_flush_log_at_trx_commit和sync_binlog 都为1,在整个事务为commit之前会write cache和flush disk,调用OS的fsync刷盘,就MySQL本身异常故障的话,是不会丢失数据的。但innodb_flush_log_at_trx_commit参数在官方文档中有以下注意事项:


也就是说如果OS层面突然断电还是会丢失数据的,丢失数据的原因还要查看fsync()这个参数,fsync函数只对由文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束,然后返回。fsync可用于数据库这样的应用程序,这种应用程序需要确保将修改过的块立即写到磁盘上。但是fsync一定非常可靠吗?答案是不一定!

因为磁盘(或RAID卡)自身通常会有硬件缓存机制,对于写操作,有write back和write through两种机制,前者将数据写至缓存就会返回,而后者则会将数据写到磁盘介质上。当使用write back机制时,fsync刷的文件数据可能只是写到磁盘缓存就返回了,导致从应用看来,写数据到磁盘的开销很小(实际上并未执行磁盘写操作);所以,使用write back机制时,即使上层应用显式fsync成功,数据也是可能丢失的,比如缓存里的数据还未刷到磁盘时掉电了,因此需要备用电池(BBU,Battery backup unit)来避免掉电时缓存数据丢失。

如果想要绝对保险,确保调用fsync或fdatasync之后数据一定能落地到磁盘上,则可以开启linux内核的write barrier机制,它可以控制在IO操作之前和之后刷新缓存来达到一定能落地磁盘的目的。Ext4 默认启用 barrier,只有当 barrier 之前的数据全部写入磁盘,才能写 barrier 之后的数据。(可通过 "mount -o barrier=0" 命令禁用该特性。)对于该特性的解释如下:

磁盘上配有内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写 commit 记录(类似WAL),若 commit 记录写入在先,而日志有可能损坏,那么就会影响数据完整性。Ext4 默认启用 barrier。

OS层面的sync、fsync和fdatasync函数

延迟写减少了磁盘读写次数,但是却降低了文件内容的更新速度,使得欲写到文件中的数据在一段时间内并没有写到磁盘上。当系统发生故障时,这种延迟可能造成文件更新内容的丢失。为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性,UNIX系统提供了sync、fsync和fdatasync三个函数。

1、sync函数
sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。通常称为update的系统守护进程会周期性地(一般每隔30秒)调用sync函数。这就保证了定期冲洗内核的块缓冲区。命令sync(1)也调用sync函数。

2、fsync函数
fsync函数只对由文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束,然后返回。fsync可用于数据库这样的应用程序,这种应用程序需要确保将修改过的块立即写到磁盘上。

3、fdatasync函数
fdatasync函数类似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。对于提供事务支持的数据库,在事务提交时,都要确保事务日志(包含该事务所有的修改操作以及一个提交记录)完全写到硬盘上,才认定事务提交成功并返回给应用层。

关于sync_binlog参数:

sync_binlog = 0 (mysql默认值 )由文件系统决定将binlog同步到硬盘。
sync_binlog = 1 每提交一次事务,写一次binlog,并使用fsync()同步到硬盘。
sync_binlog > 1 每提交一次事务,写一次binlog,达到sync_binlog 设定的值后,调用fsync()同步到硬盘。
如果在主从复制架构下:
在 sync_logbin = 1 的情况下, 每次提交事务都会同步到磁盘,保证日志的持久性,也可以保证主从复制的一致性 。
在 sync_logbin = 0,或者>1的值,很有可能机器出现crash,日志并没有同步到磁盘,重启后,二进制日志的position比备库同步过去的position小,造成数据不一致情况。
没有主从架构,单独数据库实例:
在 sync_logbin = 1 的情况下, 每次提交事务都会同步到磁盘,保证日志的持久性,能够保证存储下了所有提交的事务 。能够用来进行恢复。
在 sync_logbin = 0,或者>1的值,很有可能机器出现crash,日志并没有同步到磁盘,重启后,二进制日志很可能丢失已提交事务,所以不能用来进行恢复操作,因为它有丢失事务。

所以,MySQL Innodb数据丢失问题,涉及到MySQl自身参数与事务处理机制、OS层面和硬件层面的缓存刷盘参数及机制。其中一个层面出现问题,都可能出现数据丢失的情况。

原文地址:https://blog.51cto.com/wangwei007/2487410

时间: 2024-10-13 05:35:26

配置参数innodb_flush_log_at_trx_commit丢失数据问题的相关文章

android的数据与访问(1)-我的app配置参数文件放在哪儿?

系统提供数据处理方式: 1.SharedPreferences 2.文件存储 3.轻量级的数据.如SQLLite 1.简单存储 是android提供的起来年纪的数据存储方式:SharedPerences.将数据已最简单的方式永久保存.其屏蔽了对底层的文件操作,为程序人员提供简单的程序接口实现基于关键字的数据保存. 1.1SharedPreferences 一般程序需要配置参数等配套数据,在windows下是几乎和exe在一个目录的.程序启动时读取该参数文件,从而改变程序的相关内容.android

【原创】MySQL性能优化-I/O相关配置参数

本文介绍InnoDB和MyISAM两种存储引擎的I/O相关参数配置. 1.InnoDB  I/O相关配置 Innodb是一种事务型的存储引擎,为了减少提交事务时产生的io开销,innodb采用了写日志的方式,也就是在事务提交的时候会先写入事务日志中 ,而不是每次都把修改或者数据刷新到数据文件中,这样做是为了提高io的性能,因为事务的修改,使数据和索引文件通常都会映射到表空间随机的位置,所以刷新数据变更到数据文件会产生大量随机io,而记录日志是顺序io,一旦事务日志安全的写到磁盘中,数据就算是持久

通过查看mysql 配置参数、状态来优化你的mysql

mysql的监控方法大致分为两类: 1.连接到mysql数据库内部,使用show status,show variables,flush status 来查看mysql的各种性能指标. 2. 直接使用mysqladmin查看其性能指标,例如: UserParameter=mysql.uptime,mysqladmin -uroot status|cut -f2 -d":"|cut -f1 -d"T" mysqladmin两个参数,status,extended-st

Mysql一些重要配置参数的学习与整理(二)

原文地址:Mysql一些重要配置参数的学习与整理(二) 上一篇,Mysql一些重要配置参数的学习与整理(一)中,我们了解和学习了mysql配置中的一些重要参数,今天继续进行学习,mysql的配置参数很多,不可能做到面面俱到,这里的总结和整理只是针对于现实生产环境中用到的一些配置参数的学习,接下来,开始本篇的学习.    innodb_flush_log_at_trx_commit = 2        这个变量的官方定义是:Controls the balance between strict

Mysql一些重要配置参数的学习与整理(三)?

原文地址:Mysql一些重要配置参数的学习与整理(三) 之前的Mysql一些重要配置参数的学习与整理(一)和Mysql一些重要配置参数的学习与整理(二)中,对于线上mysql服务器的一些配置参数进行了学习,不过参阅官方doc后对其中的一些参数的配置的理解不是很清晰,今天与同事进行了交流和沟通,都一些重要的配置交换了意见,本篇就对其中的一些疑问点,整理一下心得.     skip-external-locking作用     在Mysql Linux 的发行版中,默认存在一行skip-extern

Mysql 配置参数详解以及优化配置

mysql有以下几种日志: 错误日志:   log-err 查询日志:   log 慢查询日志:  log-slow-queries 更新日志:   log-update 二进制日志: log-bin 要把日志生成在 /var/log 目录下(是系统日志存放的地方,只有 root 账号有写权限),需要 MySQL进程对这个目录有读写权限,一般是不这么做的,也考虑到安全问题,包括 MySQL 本身的数据安全,因为对 MySQL 的所有操作,都会记录到常规查询日志.MySQL的日志就不要用 /var

mysql 通过查看mysql 配置参数、状态来优化你的mysql

我把MYISAM改成了INNODB,数据库对CPU方面的占用变小很多' mysql的监控方法大致分为两类: 1.连接到mysql数据库内部,使用show status,show variables,flush status 来查看mysql的各种性能指标. 2. 直接使用mysqladmin查看其性能指标,例如: UserParameter=mysql.uptime,mysqladmin -uroot status|cut -f2 -d":"|cut -f1 -d"T&quo

关于ntp时间同步理论及配置参数-20170804

[原创]关于ntp时间同步理论及配置参数20170804 前言 NTP(Network Time Protocol,网络时间协议)是用来使网络中的各个计算机时间同步的一种协议.无论是平时使用的私人计算机还是在工作中搭建的服务器集群,时间的统一性和准确性是十分重要的.它是用来同步网络中各个计算机的时间的协议. 在计算机的世界里,时间非常地重要,例如对于火箭发射这种科研活动,对时间的统一性和准确性要求就非常地高,是按照A这台计算机的时间,还是按照B这台计算机的时间?NTP就是用来解决这个问题的,NT

mysql 参数 innodb_flush_log_at_trx_commit

问题,项目后台有一个定时任务,需要跑一批数据,跑完后存入到一个表里,用来做信息查询,数据大,逻辑复杂,耗时,多线程处理数据? 解答:以为程序的问题,把所有的关键点步骤都加上了日志,拿开发环境的日志看,一点没毛病,后来排查到Mysql,是不是服务器挂了,通过命令来查看,确实没有挂,是不是项目过载,也挂了,也没有,最后想起来,mysql可能不是实时刷入磁盘的,所有像运维拿到了my.cnf配置文件,果然是一个参数问题.运维让插入数据度快,innodb_flush_log_at_trx_commit 这