ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL-5.7组提交(Group Commit)原理

2021-10-20 16:33:55  阅读:237  来源: 互联网

标签:Binlog 事务 Group log 5.7 committed 提交 MySQL


环境说明:

以下讨论的前提 是设置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

标签:Binlog,事务,Group,log,5.7,committed,提交,MySQL
来源: https://www.cnblogs.com/autopenguin/p/15429410.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有