MySQL深入-binlog日志及事务日志

  •  1.什么是binlog?
    •  binlog是一个二进制格式的文件,用于记录用户对数据库更新的SQL语句信息,例如更改数据库表和更改内容的SQL语句都会记录到binlog里,但是对库表等内容的查询不会记录。 - 触发变更的操作,增删改都算;
    • 二进制格式的,所以无法使用cat或者vi等去查看,需要使用mysqlbinlog去查看
  • 2.binlog干吗使?
    • 主从复制;
    • 数据库宕机时候用来数据恢复。
       
  • 3.二进制日志包括两类日志:
    • 二进制日志索引文件(文件名后缀为.index):用于记录所有的二进制文件;
    • 二进制日志文件:记录数据库所有DDL和DML(除了查询)语句事件,文件名后缀为.0000*

 

  • 4.二进制日志三种类型:

MySQL深入-binlog日志及事务日志_第1张图片


 
通常都选择row模式,虽然文件大,但是现有网络带宽情况完全满足,准确性高;
在binlog中又分成两个部分,一部分在缓存中,一部分在磁盘上,业内有一个词叫刷盘,就是将缓存的日志数据落入磁盘,根刷盘相关的两个参数:

  • binlog_cache_size:二进制日志缓存部分的大小,默认32k,设置过大,造成内存浪费,设置过小,频繁io
  • sync_binlog=[N]: 表示每多少个事务写入缓冲,刷一次盘,默认值为0,代表系统决定何时去刷,性能最好;sync_binlog=1,代表每次事务提交时就会刷新binlog到磁盘,对性能有一定的影响。sync_binlog=N,代表每N个事务提交会进行一次binlog刷新。
  • sync_binlog=N,数据库在操作系统宕机的时候,可能数据并没有同步到磁盘,于是再次重启数据库,会带来数据丢失问题。
  • 5.MySQL事务日志和binlog日志的一致性问题:提到了事务的二阶提交:https://www.csdn.net/gather_2f/MtTaMgwsNzU4NC1ibG9n.html
    • 我们MySQL为了兼容其它非事务引擎的复制,在server层面引入了 binlog, 它可以记录所有引擎中的修改操作,因而可以对所有的引擎使用复制功能; 然而这种情况会导致redo log与binlog的一致性问题;MySQL通过内部XA机制解决这种一致性的问题。
    • 第一阶段:InnoDB prepare, write/sync redo log;binlog不作任何操作;
    • 第二阶段:包含两步,1> write/sync Binlog; 2> InnoDB commit (commit in memory);
    • 当第二阶段的第1步执行完成之后,binlog已经写入,MySQL会认为事务已经提交并持久化了(在这一步binlog就已经ready并且可以发送给订阅者了)。在这个时刻,就算数据库发生了崩溃,那么重启MySQL之后依然能正确恢复该事务。在这一步之前包含这一步任何操作的失败都会引起事务的rollback。
    • 第二阶段的第2步大部分都是内存操作(注意这里的InnoDB commit不是事务的commit),比如释放锁,释放mvcc相关的read view等等。MySQL认为这一步不会发生任何错误,一旦发生了错误那就是数据库的崩溃,MySQL自身无法处理。这个阶段没有任何导致事务rollback的逻辑。在程序运行层面,只有这一步完成之后,事务导致变更才能通过API或者客户端查询体现出来。

MySQL深入-binlog日志及事务日志_第2张图片

 

MySQL会在binlog落盘之后会立即将新增的binlog发送给订阅者以尽可能的降低主从延迟


提到binlog日志又不可避免的会提到了redo log和undo log

  • 1.事务日志是什么?:参考:https://www.csdn.net/gather_2f/MtTaMgwsNzU4NC1ibG9n.html,看图
    • innoDB事务日志包括redo log 和undo log两种
    • undo log:在操作任何数据之前,记录数据被修改之前的值
      • 实现回滚操作(保证事务的原子性);出现异常或者执行rollback操作,利用备份恢复数据来实现回滚
      • 实现多个行版本控制mvcc(有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取)
      • MySQL深入-binlog日志及事务日志_第3张图片
         
    • redo log:事务中操作的任何数据,MySQL都会将最新的数据备份到一个地方,保证事务的持久性
      • redoLog详细描述:
        • 当数据库对数据做修改的时候,需要把数据页从磁盘读到buffer pool中,然后在buffer pool中进行修改,那么这个时候buffer pool中的数据页就与磁盘上的数据页内容不一致,称buffer pool的数据页为dirty page 脏数据,如果这个时候发生非正常的DB服务重启,那么这些数据还没在内存,并没有同步到磁盘文件中(注意,同步到磁盘文件是个随机IO),也就是会发生数据丢失,如果这个时候,能够在有一个文件,当buffer pool 中的data page变更结束后,把相应修改记录记录到这个文件(注意,记录日志是顺序IO),那么当DB服务发生crash的情况,恢复DB的时候,也可以根据这个文件的记录内容,重新应用到磁盘文件,数据保持一致。
      • a.redo log不是事务提交后才写入的,而是在事务执行过程中便开始写入redo日志中,假如宕机断电,有脏页未写入磁盘,在重启MySQL后根据redolog重做,便可实现达到事务未写入磁盘数据进行持久化这一特性。
      • b.在事务提交前,只需要将redo log持久化即可,不需要将数据也持久化(与a类似,助于理解)
      • redo buffer持久化策略:Innodb_flush_log_at_trx_commit 参考:https://www.csdn.net/gather_2f/MtTaMgwsNzU4NC1ibG9n.html
        • 0: 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丢失一秒的事务数据]
        • 1: 默认值,每次事务提交执行Redo buffer --> Redo log OS cache -->flush cache to dis[最安全,性能最差的方式] ;
        • 2 :每次事务提交时MySQL会把日志从redo log buffer写入到system,但只写入到file system buffer,由系统内部来fsync到磁盘文件。如果数据库实例crash,不会丢失redo log,但是如果服务器crash,由于file system buffer还来不及fsync到磁盘文件,所以会丢失这一部分的数据。
        • MySQL深入-binlog日志及事务日志_第4张图片MySQL深入-binlog日志及事务日志_第5张图片
        •  
    • redo log优势:
      • 1).当系统突然宕机,buffer pool中的dirty page 还没有刷新到磁盘的时候,可以通过redolog找到需要刷到磁盘的文件的记录
      • 2).写到redo log中是顺序io,而脏页数据直接刷到磁盘是个随机io,可以提高事务提交的速度

 

  • 2.redo log和undo log关于空间管理部分:https://www.cnblogs.com/wyy123/p/7880077.html
    • undo log -关键参数
MySQL深入-binlog日志及事务日志_第6张图片 参数1 MySQL深入-binlog日志及事务日志_第7张图片 标题

 

innodb_max_undo_log_size:控制最大undo tablespace文件的大小,当启动了innodb_undo_log_truncate(初始化空间) 时,undo tablespace 超过innodb_max_undo_log_size 阀值时才会去尝试truncate。该值默认大小为1G,truncate后的大小默认为10M。

  • innodb_undo_tablespaces :独立表空间个数,默认为0,范围0-128,0标识不开启,默认存在ibdata文件中,这块指定错了会报错,当写压力较大时候,可以设置独立undo 空间,再指定目录存放,加快读写
  • innodb_undo_log_truncate:InnoDB的purge线程,根据innodb_undo_log_truncate设置开启或关闭、innodb_max_undo_log_size的参数值,以及truncate的频率来进行空间回收和 undo file 的重新初始化。前提是设置独立undo 表空间并且设置独立表空间个数大于等于2
  • innodb_purge_rseg_truncate_frequency:用于控制purge回滚段的频度,默认为128。假设设置为n,则说明,当Innodb Purge操作的协调线程 purge事务N次时,就会触发一次History purge,检查当前的undo log 表空间状态是否会触发truncate。

     
    • redo log关键参数:
      • innodb_log_files_in_group:redo log 文件的个数,命名方式如:ib_logfile0,iblogfile1... iblogfilen。默认2个,最大100个。
      • innodb_log_file_size:文件设置大小,默认值为 48M,最大值为512G,注意最大值指的是整个 redo log系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大于最大值512G。
      • innodb_log_group_home_dir:目录
      • innodb_log_buffer_size:缓存区,默认8M,可设置1-8M
      • innodb_flush_log_at_trx_commit-见上面redo部分
    • 关于redo及undo小理解:
      • undo写过大后会根据设置参数进行初始化文件
      • redo写过大后出发开始进行回溯,覆盖写

 

  • 2.事务日志的目的?实例或者介质失败,事务日志就能派上用场 – 
    • 个人理解:undo log和redo log都有对应的buffer缓冲,一致性要求高的话,redolog缓冲满了立马写入磁盘,写完后才进行事务提交,如果说一个buffer存储的事务数量是一个,也就意味着日志立即刷入磁盘
  • 3.事务日志的恢复策略:https://blog.csdn.net/Super_Anna/article/details/51926612
    • a.只重做已经提交的事务,(返回给客户端的已经提交一定保证数据的可恢复持久性)
    • b.重做所有事务,包括未提交的和已提交的事务,再通过undo log回滚那些未提交的事务。
    • c.关于恢复策略:MySQL的innoDB引擎采用了b方式:innoDB存储引擎中的恢复机制有如下几个特点:
      • 1).在重做redolog时候,没有事务性,没有begin、commit、rollback等行为,也不关心每个日志属于哪个命令,但是事务id会记录下来,这些内容也会被当做要操作数据的一部分
      • 2)使用b策略就需要将undo log也持久化,这样就会使得持久化很复杂,因此会将undo log看做数据,将记录undo log的操作也会记录下来,这样undo log也会被当数据缓存下来,而不是在redolog前写入磁盘

                          MySQL深入-binlog日志及事务日志_第8张图片

      • 3).因为redolog没有事务性,那么被回滚等的操作也会被重新执行,回滚本质上是对数据的操作修改,因此回滚也会被记录下,因此只是相当于先做redo log再做undo log,这样数据就回到原样了

       

MySQL深入-binlog日志及事务日志_第9张图片 redolog过程
​​​

 

  • 4.快照读和当前读:
    • 快照读:sql读取的是快照版本,也就是历史版本,普通select查询就是这种,读取有cache(原有数据)——undo(事务修改过数据)两部分组成
    • 当前读:sql读取的是最新版本,通过锁机制保证读取数据其他事务无法修改,例如update,delete,insert ,select for update,SELECT … LOCK IN SHARE MODE等都是当前读
  • 5.一次undo+redo事务的简化过程
  • MySQL深入-binlog日志及事务日志_第10张图片

最终:比对融合来看各种日志

关于事务日志和binlog日志的区别:https://www.jianshu.com/p/57c510f4ec28

redo log、undo log都是MySQL引擎层处理的,而binlog是数据库层产生,假设一个10万修改的大事务,在提交前是一直向redo log中顺序记录的;而binlog是直到事务提交前,才会一次性写入到binlog

 

你可能感兴趣的:(mysql)