本文共 2355 字,大约阅读时间需要 7 分钟。
mysql如何保证redolog和binlog的一致性,安全性,效率。
和数据安转相关的参数
sync_binlog:控制binlog的刷新方式(写入到磁盘)
innodb_flush_log_at_trx_commit:在innodb下控制着redo的写入方式
innodb_support_xa:外部事务,用来保证binlog和redo一致性的,俗称两段式提交
binlog_order_commits:按照binlog的写入顺序提交事务,保证redo和binlog的已执行
binlog_max_flush_queue_time: leader线程搜集binlog的超时时间
2pc提交(官方支持)
(redo日志在prepare阶段就已经sync),绝大部分都比较支持这种说法
2pc流程:(sync_binlog = 1,innodb_flush_log_at_trx_commit = 1 )
1.prepare阶段:sync redo 日志(未sync的redo存放于innodb_log_buffer_size中),系统自动完成
获取prepare_commit_mutex(一个全局锁,一次只能被一个事务获取)
2.生成binlog,将binlog写入文件系统(未提交之前binlog存放在binlog_cache_size中),sync binlog,这一步受sync_binlog控制
3.提交commit 将commit标志sync ,释放prepare_commit_mutex(这一步应该受innodb_flush_log_at_trx_commit的控制)
违背了这个参数的定义:innodb_flush_log_at_trx_commit
观点二:redo日志在最后的commit的时候才sync
2pc流程:(官方没有明显的支持这种说法)
1.prepare阶段:获取prepare_commit_mutex
2.生成binlog,将binlog写入文件系统(未提交之前binlog存放在binlog_cache_size中),sync binlog
3.提交commit 将redo log sync ,释放prepare_commit_mutex
这种方式会造成binlog的日志记录多余redo日志记录,在恢复的时候是如何恢复? 难道是以binlog为准,
不管这个事务的redo有没有提交 ,只要写binlog就认为该事务以提交(现阶段还没有找到有关该说法).
innodb数据恢复流程
1.查找未提交的redo日志(找xid)
2.用xid去binlog查找对应的日志记录
3.如果有就认为这个事务是提交的,并补充commit。如果没有就认为是没有提交的,在恢复的时候就rollback事务
###################################################################################################
以上2pc日志写入方式是在 mysql5.6之前的方式,当sync_binlog=1的时候 系统的性能非常糟糕。
从5.6 之后就开始采用BLGC方式写2pc日志,来提升性能
BLGC具体流程如下:(每一个阶段只有一个活跃的线程)
flush stage:已完成perpare阶段的线程队列
sync stage:flush队列超时(binlog_max_flush_queue_time)或者没有线程产生binlog了 ,flush队列开始sync队列,将binlog写入磁盘(合并io)
commit stage:队列进入提交阶段(这里只做提交操作,redo日志的写入已经在prepare写入)
个人理解:
flush stage:队列中的第一个线程为leader线程,后面的线程为follower线程,leader线程主要负责收集待提交binlog的线程(线程准备阶段之后自动进入flush阶段),直到队列为空,或者超时(binlog_max_flush_queue_time),才进入sync stage
sync stage:如果flush stage队列为空,则之前leader线程依然为leader线程,负责binlog的sync,否则变成follower线程(合并执行sync)
commit stage:sync完binlog的线程被放入commit队列的末尾,等待提交
5.7 的组提交:
Step1. InnoDB Prepare,记录当前的LSN到thd中。
Step2. 进入 Group Commit 的flush stage;Leader搜集队列,同时算出队列中最大的LSN。
Step3. 将InnoDB的redo log write/fsync到指定的LSN
Step4. 写Binlog并进行随后的工作(sync Binlog, InnoDB commit
也就是将 redo log的write/sync延迟到了 binlog group commit的 flush stage 之后,sync binlog之前。
通过延迟写redo log的方式,显式的为redo log做了一次组写入(redo log group write),并减少了(redo log) log_sys->mutex的竞争。
组提交
(淘宝内部mysql交流)
innodb数据丢失的问题:
组提交的理解: