zoukankan      html  css  js  c++  java
  • MySQL-5.7组提交(Group Commit)原理

    环境说明:

    以下讨论的前提 是设置MySQL的crash safe相关参数为双1。

    • sync_Binlog=1:MySQL 每次在提交事务前会将二进制日志同步到磁盘上,保证在服务器崩溃时不会丢失事务。
    • innodb_flush_log_at_trx_commit=1:每次COMMIT后立即刷新同步数据到硬盘。

    相关知识概述:

    1 WAL机制(Write Ahead Log)

    WAL指的是对数据文件进行修改前,必须将修改先记录日志。MySQL为了保证ACID中的一致性和持久性,使用了WAL。

    2 Redo log

    Redo log就是一种WAL的应用。当数据库忽然掉电,再重新启动时,MySQL可以通过Redo log还原数据。也就是说,每次事务提交时,不用同步刷新磁盘数据文件,只需要同步刷新Redo log就足够了。相比写数据文件时的随机IO,写Redo log时的顺序IO能够提高事务提交速度

    3 组提交(Group Commit)

    3.1 在没有开启Binlog时

    Redo log的刷盘操作将会是最终影响MySQL TPS的瓶颈所在。为了缓解这一问题,MySQL使用了组提交,将多个刷盘操作合并成一个,如果说10个事务依次排队刷盘的时间成本是10,那么将这10个事务一次性一起刷盘的时间成本则近似于1。

    3.2 当开启Binlog时

    为了保证Redo log和Binlog的数据一致性,MySQL使用了二阶段提交,由Binlog作为事务的协调者。而引入“二阶段提交”使得Binlog又成为了性能瓶颈,先前的“Redo log组提交”也成了摆设。为了再次缓解这一问题,MySQL增加了“Binlog组提交”机制,目的同样是将Binlog的多个刷盘操作合并成一个,结合Redo log本身已经实现的“组提交”,分为三个阶段“Flush阶段”、“Sync阶段”、“Commit阶段”完成“Binlog组提交”,最大化每次刷盘的收益,弱化磁盘瓶颈,提高性能。

    4 事务二阶段提交

    参见《MySQL-5.7事务二阶段提交机制.md》


    Binlog组提交原理:

    1 概述

    注意:在MySQL中每个阶段都有一个队列,每个队列都有一把锁保护,第一个进入队列的事务会成为leader,leader领导所在队列的所有事务,全权负责整队的操作,完成后通知队内其他事务操作结束。

    2 阶段描述

    2.1 Flush阶段

    1. 首先获取队列中的事务组;
    2. 将Redo log中prepare阶段的数据刷盘(图3中Flush Redo log步骤);
    3. 将Binlog数据写入文件,当然此时只是写入文件系统的缓冲,并不能保证数据库崩溃时Binlog不丢失 (图4中Write Binlog步骤);
    4. Flush阶段队列的作用是用于支撑Redo log的组提交
    5. 如果在这一步完成后数据库崩溃,由于协调者Binlog中不保证有该组事务的记录,所以MySQL可能会在重启后回滚该组事务。

    2.2 Sync阶段

    1. 这里为了增加一组事务中的事务数量,提高刷盘收益,MySQL使用两个参数控制获取队列事务组的时机,分别如下。
      • Binlog_group_commit_sync_delay=N:在等待N μs后,开始事务刷盘(图3中Sync Binlog步骤)
      • Binlog_group_commit_sync_no_delay_count=N:如果队列中的事务数达到N个,就忽视Binlog_group_commit_sync_delay的设置,直接开始刷盘(图4中Sync Binlog步骤)
    2. Sync阶段队列的作用是用于支持Binlog的组提交
    3. 如果在这一步完成后数据库崩溃,由于协调者Binlog中已经有了事务记录,MySQL会在重启后通过Flush 阶段中Redo log刷盘的数据继续进行事务的提交。

    2.3 Commit阶段

    1. 首先获取队列中的事务组;
    2. 依次将Redo log中已经prepare的事务在引擎层提交(图1中InnoDB Commit步骤)
    3. Commit阶段不用刷盘,如上所述,Flush阶段中的Redo log刷盘已经足够保证数据库崩溃时的数据安全了
    4. Commit阶段队列的作用是承接Sync阶段的事务,完成最后的引擎提交,使得Sync可以尽早的处理下一组事务,最大化组提交的效率

    组提交在Binlog上的表现:

    单纯通过SHOW BINLOG EVENTS无法发现有关组提交的任何信息,但是通过mysqlbinlog工具,便可以发现组提交的内部信息,类似如下。

    [root]# mysqlbinlog mysql-bin.0000006 | grep last_committed
    #150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1
    #150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2
    #150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3
    #150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4
    #150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5
    #150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6
    #150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7
    #150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8
    #150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9
    #150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10
    #150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11
    #150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12
    #150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13
    ...
    

    可以发现MySQL 5.7二进制日志较之原来的二进制日志内容多了last_committedsequence_number这两项内容。这两个值即所谓的“逻辑时间戳标记(Logical Clock)”,可以用于控制多线程复制(MTS)特性。

    • sequence_number:该值随着事务顺序增长每个事务对应一个序列号。该值在事务二阶段提交的Prepare阶段被记录存储,用于标记最新提交的事务。
    • last_committed:表示事务提交的时候,上次事务提交的序列号(sequence_number),如果事务具有相同的last_committed,则表示这些事务都在一组内。该值在事务二阶段提交的Commit阶段被记录存储

    参考资料:

    1. 《[原理解析] MySQL组提交(group commit)》
      https://mp.weixin.qq.com/s/_LK8bdHPw9bZ9W1b3i5UZA

    2. 《MySQL 5.7新特性:并行复制原理(MTS)》
      https://blog.csdn.net/andong154564667/article/details/82117727

  • 相关阅读:
    Flipboard web移动端-打造每秒60帧的流畅体验
    android开源代码演示项目CodeBox
    Material风格的文件管理器
    android:ToolBar详解
    GossipView:圆圈布局的自定义view
    9个完整android开源app项目
    android-波浪效果ripple-background
    Android Studio 简单介绍和使用问题小结
    ActionItemBadge:在actionbar上显示badge数字提示
    在ContentResolver中使用Group By
  • 原文地址:https://www.cnblogs.com/autopenguin/p/15429410.html
Copyright © 2011-2022 走看看