MYSQL中如何实现binlog优化


这篇文章主要讲解了MYSQL中如何实现binlog优化,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。问题问题1:如何解决事务提交时flush redo log带来的性能损失WAL是实现事务持久性(D)的一个常用技术,基本原理是将事务的修改记录redo log。redo log顺序追加写入。事务开发云主机域名提交时,只需要保证事务的redo log落盘即可,通过redo log的顺序写代替页面的随机写提升数据库系统的性能。但是,该方案必须要求每个事务提交时都将其生成的redo log进行一次刷盘,效率不高。问题2:binlog和引擎层事务提交的顺序问题对于单个事务而言,日志写入顺序是先redo log再binlog,只要维持该顺序即可维持正确性。但对于一个高并发的数据库系统而言,每时每刻可能都会存在众多并发执行的事务。我们还需要通过一定的手段来维护Server层binlog和引擎层事务提交的顺序一致性。维护这种顺序一致性其实是为了保证备份工具Xtrabackup的正确性。当 binlog 作为协调者,如果其中记录的事务顺序和存储引擎层记录的顺序不一样的话,备份工具(Innodb Hot Backup)拿到备份集的位点可能会存在空洞。因为备份工具会拷贝 redo 日志,在 redo 的头部会记录最后一个提交的事务对应的 binlog 位点,备份集建立之后就会根据这个位点继续从主库 dump binlog。假如有三个事务 T1,T2,T3 已经 fsync 到 binlog 文件中,三个事务的在文件中的位点分别是 100,200,300,但是在引擎层的只有 T1 和 T3 完成了 commit 并记录到 redo 中,最后一个 commit 的事务 T3 位点是 300。此时通过备份工具拿到的数据就是这样的状态,备份集启动的时候会走崩溃恢复的流程,prepare 事务被回滚(备份集不会备份 binlog 文件,对应上个小节 xid 集合为空),自位点 300 继续从主库同步binlog并apply,导致 T2 在备库就丢失了。因此,我们必须设计一种机制来保证Server层的binlog写入顺序和存储引擎层的事务提交顺序保持一致。问题3:同时写redo和binlog带来的性能下降问题1中提到每次的事务提交会带来性能问题,而这个问题在引入binlog后会变得更加严重。每个事务提交都会增加一次文件IO,且需要刷盘。如果系统并发比较高,那么这些IO将会成为拖慢整体性能的瓶颈。解决方案问题1:Redo log组提交技术redo组提交技术思想很简单:通过将多个事务redo log的刷盘动作合并,减少刷盘次数。Innodb的日志系统里面,每条redo log都有一个LSN(Log Sequence Number)。事务将日志拷贝到redo log buffer时,都会获取当前最大的LSN,且LSN单调递增,因此可以保证不同事务的LSN不会重复。那么假设三个事务Trx1、Trx2、Trx3的日志的最大LSN分别为LSN1、LSN2、LSN3(LSN1
问题2:内部XA事务开启binlog情况下,引入内部XA事务来协调上层和存储引擎层,具体来说,在事务提交时引入两个阶段:prepare:将redo log刷盘操作以确保data页和undo页的更新已经刷新到磁盘,设置事务状态为PREPARE状态;commit:1). 写binlog并刷盘,2).调用引擎层事务提交接口。将事务状态设置为COMMIT。如此两阶段提交主要是要保证数据库崩溃时的正确性。因为一旦binlog落盘了,它就可能被下游节点消费。这种事务必须在重启后被commit而非rollback。而对于binlog未落盘的事务,崩溃恢复时直接回滚。具体来说,故障恢复时,扫描最后一个binlog文件(在flush阶段,如果binlog大小超过阀值,进行rotate binlog文件,会保证该文件记录的最后一个事务一定被提交),提取其中的xid。重做检查点以后的redo日志,读取事务的undo段信息,搜集处于prepare阶段的事务列表,将事务的xid与binlog中记录的xid对比,若存在,则提交,否则就回滚。MySQL5.6以前,为了保证数据库binlog的写入顺序和InnoDB层的事务提交顺序一致,MySQL数据库内部使用了prepare_commit_mutex锁。具体来说,在两阶段提交引擎层 prepare 的时候加锁,在引擎层 commit 之后释放锁:这样确实可以保证 binlog 和 innodb 的事务顺序一致,但是这把锁会导致所有的事务串行化执行,且每次提交都会至少调用多次fsync,效率很低。这也是接下来需要探讨并解决的一个问题。问题4参考redo log优化技术,引入组提交技术来优化binlog的写入性能。考虑未优化时事务提交流程:prepare:该阶段刷存储引擎层(innodb)的redo log并将事务状态设置为PREPARED(更新undo page上事务状态),该阶段不涉及binlog
commit:写binlog日志并刷盘,同时引擎层释放锁,释放回滚段、设置事务状态为COMMITTED等
所谓的组提交技术其本质上是将耗时的commit步骤进行更细粒度的拆分,具体来说:将步骤2的commit 分为三个阶段:Flush:写binlog,但不sync
Sync: 调用 fsync 操作将文件落盘
Commit :调用存储引擎接口提交事务这里的fsync是耗时操作,因此我们希望能攒足够多的写入后才进行一次fsync调用,在这里使用batch技术。其原理是:上述步骤中的每个阶段都有一个对应的任务链表,每个进入该阶段的线程会将自己的任务加入至该链表中,链表加锁以保证正确性。第一个加入该链表的线程会成为Leader,后续的线程成为Follower。链表中的所有任务组成一个Batch,由Leader负责执行,而Follower则等待其任务完成即可。一旦某阶段的链表任务执行完成,这些任务会进入下一个阶段,同样加入该阶段的任务链表,重复上述执行流。如此设计有以下几点好处:除此之外,MYSQL还对prepare阶段刷redo log进行了进一步优化。原来的设计是多事务可并发地刷redo log,同样效率不够高。可以将prepare阶段的redo log刷盘放在commit阶段的Flush阶段执行。但有个小问题需要说明的是:优化前每个线程各自负责自己的redo log的落盘,且知道需要flush的redo log的lsn,如果改为在Flush阶段由其Leader线程统一落盘,此时它不了解每个线程的redo log的lsn,因此它简单粗暴地flush至log_sys的最大lsn,这就保证了要提交事务的redo log一定可以被落盘。看完上述内容,是不是对MYSQL中如何实现binlog优化有进一步的了解,如果还想学习更多内容,欢迎关注开发云行业资讯频道。

相关推荐: MySQL 分区表探究细节《整理自官档》

MysqlPartition topic studyWhen partitioning by KEY or LINEAR KEY, youcan use a DATE, TIME, or DATETIME column as thepartitioning c…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 06/04 18:02
下一篇 06/04 18:02

相关推荐