文档章节

从源码解读Mysql 5.7性能和数据安全性的提升

l
 linux-tao
发布于 2017/05/22 16:31
字数 1995
阅读 10
收藏 0

下面我们从源码来分析mysql的事务提交以及事务在何时将binlog复制到从库的。

MYSQL_BIN_LOG::ordered_commit,这个是事务在binlog阶段提交的核心函数,通过该函数,实现了事务日志写入binlog文件,以及触发dump线程将binlog发送到slave,在最后的步骤,将事务设置为提交状态。

我们来分析MYSQL_BIN_LOG::ordered_commit这个函数的核心过程,该函数位于binlog.cc文件中。

源码解析

MYSQL_BIN_LOG::ordered_commit,这个函数,核心步骤如下:

第一步骤:flush

Stage#1: flushing transactions to binary log:

步骤1 :将事务的日志写入binlog文件的buffer中,函数如下:

process_flush_stage_queue(&total_bytes,&do_rotate, &wait_queue);

从5.6开始,mysql引入了group commit 的概念,这样可以避免每个事务提交都会锁定一次binlog.另外,还有一个用处,就是mysql的5.7的基于logical_clock的并行复制。在一个组里面(其实是一个队列),这一组队列的头事务是相同的,因此这一组事务的last_committed(上一组的最后一个提交的事务)的事务也是同一个。我们都知道,last_committed相同的事务,是可以在从库并行relay(重演)的。该函数process_flush_stage_queue的作用,就是将commit队列中的线程一个一个的取出,然后执行子函数 flush_thread_caches(head);循环的代码如下:将各自线程中的binlog cache写入到binlog中。

/* Flush thread caches to binary log. */

for (THD *head= first_seen ; head ; head = head->next_to_commit)

{

std::pair<int,my_off_t>result= flush_thread_caches(head);

total_bytes+= result.second;

if(flush_error == 1)

flush_error= result.first;

#ifndef DBUG_OFF

no_flushes++;

#endif

}

第二步骤SYNC to disk

Stage#2: Syncing binary log file to disk

第二步:将binlog file中cache的部分写入disk.但这个步骤参数sync_binlog起决定性的作用。

我们来看看源码,除了这些还有哪些细节步骤,看完源码分析之后,你应该有新的收获与理解。

在执行真正的将binlog写到磁盘之前,会进行一个等待,函数如下:

stage_manager.wait_count_or_timeout(opt_binlog_group_commit_sync_no_delay_count,

opt_binlog_group_commit_sync_delay,

Stage_manager::SYNC_STAGE);

等待的时间由mysql参数文件中的binlog_group_commit_sync_delay,binlog_group_commit_sync_no_delay_count 这两参数共同决定,第一个表示该事务组提交之前总共等待累积到多少个事务,第二个参数则表示该事务组总共等待多长时间后进行提交,任何一个条件满足则进行后续操作。因为有这个等待,可以让更多事务的binlog通过一次写binlog文件磁盘来完成提交,从而获得更高的吞吐量。

接下来,就是执行sync_binlog_file,该函数会用到mysql参数文件中sync_binlog参数的值,如果为0,则不进行写磁盘操作,由操作系统决定什么时候刷盘,如果为1,则强制进行写磁盘操作。

再接下来,执行update_binlog_end_pos函数,用来更新binlog文件的最后的位置binlog_end_pos,该binlog_end_pos是一个全局的变量。在执行更新该位置之前,先得找到最后一个提交事务的线程(因为是group commit,多个事务排队提交的机制)。因为已经将要提交事务的线程组成了一个链表,通过从头到尾找,可以找到最后一个线程。代码如下:

if(update_binlog_end_pos_after_sync)

{

THD*tmp_thd= final_queue;

while(tmp_thd->next_to_commit != NULL)

tmp_thd= tmp_thd->next_to_commit;

update_binlog_end_pos(tmp_thd->get_trans_pos());

}

接下来,我们来看一下这个函数update_binlog_end_pos,这个函数很简单,传入一个pos,然后将其赋值给全局变量binlog_end_pos,接下来就是最核心的一行代码,signal_update(),发送binlog更新的信号,因此从主库同步binlog到从库的dump线程,会接收到这个binlog已有更新的信号,然后启动dump binlog的流程。

函数update_binlog_end_pos的完整代码如下。

semisync

通过上面的步骤介绍,我们看到,在binlog文件的最新位置更新的时候,就已经通过signal_update函数发送信号给binlog的dump线程,该线程就可以将事务的binlog同步到从库,从库接收到日志之后,就可以relay日志,实现了主从同步。因此,再次重复说明一下,按照上面的解释,在事务真正提交完成之前就开始发送了binlog已经更新的信号,dump线程收到信号,即可以进行binlog的同步。而semisync的作用是什么呢?

实际上,有没有semisync机制,上面介绍的mysql的有关事务提交中关于binlog的流程都是一样的,semisync的作用,只是主从之间的一个确认过程,主库等待从库返回相关位置的binlog已经同步到从库的确认,(而实际实现则是等待dump线程给用户会话线程一个回复),没有得到确认之前(或者等待时间达到timeout),事务提交则在该函数(步骤)上等待直至获得返回。具体执行binlog已经同步到某个位置的的确认函数为repl_semi_report_binlog_sync,函数如下:

int repl_semi_report_binlog_sync(Binlog_storage_param *param,

constchar *log_file,

my_off_t log_pos)

{

if(rpl_semi_sync_master_wait_point == WAIT_AFTER_SYNC)

return repl_semisync.commitTrx(log_file, log_pos);

return 0;

}

通过观察上述函数,我们可以看到有个rpl_semi_sync_master_wait_point变量与WAIT_AFTER_SYNC比较,如果不相等,则直接返回,直接返回则表示不需要在此时此刻确认binlog是否已经同步,而这个变量的取值来自于半同步参数semi_sync_master_wait_point的初始设置,我们可以设置为after_sync与after_commit。这两个参数含义的区别是:after_sync是在将binlog sync到disk之后(具体是否真正sync由参数sync_binlog的值决定)进行日志同步确认,而after_commit是将事务完成在innodb里面提交之后再进行binlog的同步确认。两者确认的时间点不同,after_sync要早于after_commit.

接下来,我们来看repl_semisync.commitTrx 这个函数,这个函数有两个传入参数,一个是binlog文件,一个binlog文件的位移。我们来看这个函数的含义吧。算了,还是直接用源码的注释来解释吧。

从源码解读Mysql 5.7性能和数据安全性的提升从源码解读Mysql 5.7性能和数据安全性的提升

上面的注释说得相当清楚,就是该commiTRX函数会等待binlog-dump返回已经同步到该位置的报告,如果还没有同步到该位置,则继续等待,直到超时返回。

当会话线程收到该函数的返回时,事务的提交过程继续往下走,直至在innodb真正提交。

总结

通过上述对mysql的事务提交过程中的前段分析,应该可以了解semi-sync的同步机制与异步机制的区别,semi-sync的主从同步机制与异步机制在同步的处理方式上无任何区别,唯一的区别就是semi-sync在事务提交中段(假如设置为after_sync)或者提交后的阶段(after_commit), 有一个验证该事务涉及的binlog是否已经同步到从库,而这个同步验证,会拉长整个事务的提交时间,因为事务提交在数据库中几乎是串行(如果按group commit为一个单位,就算是完全地串行),是影响mysql吞吐量的关键点,当这个关键点被拉长,所以对全局的影响就被放大。虽然仅仅多了这么一个确认的动作,但当主库处于semisync的同步状态与异步状态的吞吐量相比,相差了好几倍。上述解释就是其真正的原因。

原文来自:http://www.yunweipai.com/archives/17900.html

本文地址:http://www.linuxprobe.com/mysql5-performance-improvement.html

© 著作权归作者所有

共有 人打赏支持
l
粉丝 17
博文 868
码字总数 996237
作品 0
深圳
运维
私信 提问
MySQL 5.7.9 GA稳定版新特性解读

2015年10月22日,MySQL发布5.7.9稳定版,虽然MySQL官方手册里已经有很多关于MySQL 5.7新特性的介绍,在这里,还是 让我们一起看看在MySQL 5.7里有哪些值得我们关注的新特性吧。 1、安全性 用...

我就叫你女王吧
2016/05/17
12
0
MySQL 5.7.9 GA稳定版新特性解读

2015年10月22日,MySQL发布5.7.9稳定版,虽然MySQL官方手册里已经有很多关于MySQL 5.7新特性的介绍,在这里,还是让我们一起看看在MySQL 5.7里有哪些值得我们关注的新特性吧。 1、安全性 用户...

大王叫我来巡山Zd
2016/03/31
62
0
MySQL 5.7.6 发布,提升性能和安全性

今天 Oracle 发布了 MySQL 5.7.6 milestone 16,至此,MySQL 5.7 已经开发两年了。相比 MySQL 5.6,有特别多的改进。团队主要关注速度,性能据报告是比之前版本提升了 2 至 3 倍! 新特性列表...

oschina
2015/03/11
20.8K
19
与技术谈一场永不分手的恋爱

找到一份合适的工作,就像在工作的八小时之内有了一个心仪的恋人。 老张我呢,原来在上学那会儿,不是特别爱学习,本人长得呢也特别帅(现在做了技术可惜了哈哈!)所以特招漂亮女孩的喜欢,...

superZS
2017/07/21
0
0
你的MySQL服务器开启SSL了吗?

作者介绍 赵海亮,现任职于58赶集集团-安居客MySQL DBA,主要从事安居客MySQL数据库的优化、升级、迁移等工作。 最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现...

赵海亮
2017/07/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

租房软件隐私保护如同虚设

近日,苏州市民赵先生向江苏新闻广播新闻热线025-84658888反映,他在“安居客”手机应用软件上浏览二手房信息,并且使用该软件自动生成的虚拟号码向当地一家中介公司进行咨询。可电话刚挂不久...

linux-tao
今天
1
0
分布式项目(五)iot-pgsql

书接上回,在Mapping server中,我们已经把数据都整理好了,现在利用postgresql存储历史数据。 iot-pgsql 构建iot-pgsql模块,这里我们写数据库为了性能考虑不在使用mybatis,换成spring jd...

lelinked
今天
4
0
一文分析java基础面试题中易出错考点

前言 这篇文章主要针对的是笔试题中出现的通过查看代码执行结果选择正确答案题材。 正式进入题目内容: 1、(单选题)下面代码的输出结果是什么? public class Base { private Strin...

一看就喷亏的小猿
今天
2
0
cocoapods 用法

cocoapods install pod install 更新本地已经install的仓库 更新所有的仓库 pod update --verbose --no-repo-update 更新制定的仓库 pod update ** --verbose --no-repo-update...

HOrange
今天
3
0
linux下socket编程实现一个服务器连接多个客户端

使用socekt通信一般步骤 1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。 2)客户端:socker()建立套接字,连接(connect)服务器,连接上后...

shzwork
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部