一、触发条件

binlog_gtid_simple_recovery=false。

5.7.6以上版本。

Gtid 关闭或者Gtid中途开启有大量的未开启Gtid的binlog。

二、本案例回顾

版本:MySQL版本 5.7.19。

故障为:大概每半小时发生一次故障,整个Mysql压力巨大,很多简单的操作都相应缓慢。使用iotop,top等工具都发现Mysql某个线程有大量的I/O。

分析方法:使用strace发现有大量的binlog文件读取。

binlog_gtid_simple_recovery=false。

Gtid关闭,中途开启,但是留下了很多未开启Gtid的binlog。

数据库没有重启,但是由于expire_logs_days触发了binlog删除。

三、故障分析

其实本案例就是前文第七部分总结中的:

Gtid关闭,simple_recovery=flase

5.7.6以上:这种方式一定得到正确的Gtid集合

重启Mysql不扫秒全部的binlog,如果是中途打开GTID重启任然需要扫描多个binlog因为需要找到Gtid event。

purge binlog或者超过参数expire_logs_days参数设置不触发全binlog扫描,如果是中途打开GTID重启任然需要扫描多个binlog因为需要找到Gtid event。

从案例中我们得知是中途开启的Gtid,但是留下了很多未开启Gtid的binlog,从第六部分源码bool MYSQL_BIN_LOG::init_gtid_sets()函数的分析,我们知道删除binlog后也会触发正向查找来获取gtid_purged(Gtid_state.lost_gtids)。当读取到第一个binlog的时候虽然获取到了PREVIOUS GTID EVENT但是没有GTID EVENT,而simple_recovery=flase所以需要继续查找下一个文件,直到找到同时包含PREVIOUS GTID EVENT和GTID EVENT的 那个binlog才会停止,那么显然这种情况下那些Gtid关闭的时候生成的binlog将会全部扫描一遍,如果量大那么代价将是巨大的。

而案例中每半个小时会触发一次binlog切换,因为触发超过expire_logs_days参数设置导致binlog进行删除,触发了大量的binlog扫描。

显然有了前面的基础这个案例很容易分析。

四、案例模拟

这个案例非常好模拟。我打算直接使用strace查看。因为不是每位朋友都能方便使用GDB调试。

使用测试版本社区版本5.7.17:

+---------------+-----------+

| Log_name | File_size |

+---------------+-----------+

| binlog.000027 | 198 |

| binlog.000028 | 198 |

| binlog.000029 | 198 |

| binlog.000030 | 198 |

| binlog.000031 | 198 |

| binlog.000032 | 198 |

| binlog.000033 | 198 |

| binlog.000034 | 198 |

| binlog.000035 | 198 |

| binlog.000036 | 198 |

| binlog.000037 | 198 |

| binlog.000038 | 198 |

| binlog.000039 | 198 |

| binlog.000040 | 198 |

| binlog.000041 | 198 |

| binlog.000042 | 198 |

| binlog.000043 | 154 |

+---------------+-----------+

mysql> show variables like '%gtid%';

+----------------------------------+-----------+

| Variable_name | Value |

+----------------------------------+-----------+

| binlog_gtid_simple_recovery | OFF |

| enforce_gtid_consistency | ON |

| gtid_executed_compression_period | 1000 |

| gtid_mode | OFF |

| gtid_next | AUTOMATIC |

| gtid_owned | |

| gtid_purged | |

| session_track_gtids | OFF |

+----------------------------------+-----------+

8 rows in set (0.02 sec)

mysql> show variables like '%expir%';

+--------------------------------+-------+

| Variable_name | Value |

+--------------------------------+-------+

| disconnect_on_expired_password | ON |

| expire_logs_days | 1 |

+--------------------------------+-------+

2 rows in set (0.06 sec)

然后我修改了系统时间同时Mysql开启Gtid

[root@test1 ~]# date -s '2017-12-13 10:10:10'

Wed Dec 13 10:10:10 CST 2017

mysql> set global gtid_mode=1;

Query OK, 0 rows affected (0.02 sec)

mysql> set global gtid_mode=2;

Query OK, 0 rows affected (0.01 sec)

mysql> set global gtid_mode=3;

Query OK, 0 rows affected (0.02 sec)

mysql> show variables like '%gtid_mode%';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| gtid_mode | ON |

+---------------+-------+

1 row in set (0.02 sec)

到一步我们已经达到了触发的标准,只要手动触发一次flush binary logs,让binlog刷新就会看到。当然线上是binlog满了做的切换。

这个时候开始做strace,并且做flush tables,我们观察到

mysql> flush binary logs;

Query OK, 0 rows affected (0.30 sec)

strace:

[pid 6551] 10:17:15.936738 read(62, "/mysql/mysql5.7.17/binlog.000027"..., 528) = 528 <0.000039>

[pid 6551] 10:17:15.936834 stat("/mysql/mysql5.7.17/binlog.000027", {st_mode=S_IFREG|0640, st_size=198, ...}) = 0 <0.000025>

[pid 6551] 10:17:15.936925 lseek(3, 0, SEEK_SET) = 0 <0.000017>

[pid 6551] 10:17:15.936983 read(3, "/mysql/mysql5.7.17/binlog.000043"..., 165) = 165 <0.000018>

[pid 6551] 10:17:15.937076 lstat("/mysql", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000020>

[pid 6551] 10:17:15.937144 lstat("/mysql/mysql5.7.17", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000586>

[pid 6551] 10:17:15.937819 unlink("/mysql/mysql5.7.17/binlog.000027") = 0 <0.000109>

[pid 6551] 10:17:15.938009 stat("/mysql/mysql5.7.17/binlog.000028", {st_mode=S_IFREG|0640, st_size=198, ...}) = 0 <0.000021>

[pid 6551] 10:17:15.938119 lstat("/mysql", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000020>

[pid 6551] 10:17:15.938228 lstat("/mysql/mysql5.7.17", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000021>

[pid 6551] 10:17:15.938314 unlink("/mysql/mysql5.7.17/binlog.000028") = 0 <0.000073>

.....

[pid 6551] 10:17:15.954677 lstat("/mysql/mysql5.7.17", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000019>

[pid 6551] 10:17:15.954756 unlink("/mysql/mysql5.7.17/binlog.000041") = 0 <0.000099>

[pid 6551] 10:17:15.954920 stat("/mysql/mysql5.7.17/binlog.000042", {st_mode=S_IFREG|0640, st_size=198, ...}) = 0 <0.000021>

[pid 6551] 10:17:15.955022 lstat("/mysql", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000018>

[pid 6551] 10:17:15.955087 lstat("/mysql/mysql5.7.17", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000018>

[pid 6551] 10:17:15.955159 unlink("/mysql/mysql5.7.17/binlog.000042") = 0 <0.000130>

受限篇幅我这里删除了一些。我们看到很多read/lseek系统调用正是读取binlog的证据。

至此整个案例模拟完成。

五、总结

前文已经描述过在5.7.6以上binlog_gtid_simple_recovery应该设置为true,这样可以避免可能的大量的binlog的扫描。具体分析可以参考第七节和从第六部分源码bool MYSQL_BIN_LOG::init_gtid_sets()函数的分析。

深入浅出mysql gtid_Mysql 5.7 Gtid内部学习(九) 实际案例(一)相关推荐

  1. Mysql 5.7 Gtid内部学习(十) 实际案例(二)

    本案例是我真实遇到过的一个坑,也在前文中不止一次的提到,当时也是非常纳闷,其实知道原因后只能说为什么会这么坑. 一.触发条件 本案列我测试过4个版本 percona Mysql 5.7.14 官方社区 ...

  2. mysql gtidpurged_Mysql 5.7 Gtid内部学习(五) mysql.gtid_executed表/gtid_executed变量/gtid_purged变量的更改时机...

    本节将集中讨论下面三种Gtid更新的时机,这部分相当重要,后面的故障案列会和这节有关.下面先来看一下他们的定义 mysql.gtid_executed表:Gtid持久化的介质,Mysql启动阶段会读取 ...

  3. mysql 5.6 开启gtid_MySQL 5.6 GTID 原理以及使用

    简介 GTID是MySQL 5.6的新特性,其全称是Global Transaction Identifier,可简化MySQL的主从切换以及Failover.GTID用于在binlog中唯一标识一个 ...

  4. Mysql一些重要配置参数的学习与整理(二)

    2019独角兽企业重金招聘Python工程师标准>>> 原文地址:Mysql一些重要配置参数的学习与整理(二) 上一篇,Mysql一些重要配置参数的学习与整理(一)中,我们了解和学习 ...

  5. mysql入门很简单系列视频-学习笔记

    mysql入门很简单系列视频-学习笔记 视频链接:mysql入门很简单系列视频 https://www.bilibili.com/video/av14920200/ 以前主要就了解DDL.DML.DC ...

  6. MySQL 5.7 基于 GTID 的主从复制实践

    MySQL 5.7 基于 GTID 的主从复制实践 Posted by Mike on 2017-07-03 运维之美 Home About Archives Tags 在 「MySQL 5.7多源复 ...

  7. 深入浅出Mysql - 优化篇(锁)

    深入浅出Mysql - 优化篇(锁) 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保 ...

  8. 深入浅出Mysql - 基础篇(列类型/运算符/函数)

    深入浅出Mysql - 基础篇(列类型/运算符/函数) 每一个常量.变量和参数都有数据类型,它用来指定一定的存储格式.约束和有效范围.MySQL提供了多种数据类型,主要包括数值型.字符串类型.日期和时 ...

  9. Mysql一些重要配置参数的学习与整理(一)

    2019独角兽企业重金招聘Python工程师标准>>> 原文地址:Mysql一些重要配置参数的学习与整理(一) 最近一直在进行mysql的学习,主要是学习mysql的一些配置参数,了 ...

最新文章

  1. compass安装使用960 Grid System
  2. 今天什么日子啊,这么倒霉。。。
  3. 网站站内优化新方案,SEO运营人员值得一看
  4. 小甲鱼python课件源代码_[Python基础] 小甲鱼零基础入门Python学习视频+全套源码课件 Python视频教程 96讲...
  5. C#中的cookie编程
  6. pcb过孔漏铜_【企业资讯】大正瑞地:专注PCB药水二十年,品质、性能可靠
  7. 爬虫案列:京东商城长裤信息获取
  8. 2020年中国基层医疗研究报告
  9. React基础----ReactJS的使用(一)
  10. php 去除空格和换行
  11. 要实现动态加载JS脚本有4种方法:
  12. 如何将照片中的文字转变成可编辑的文章(如何将书上的文字转变为可编辑的文字)
  13. Hi3559a移植Opencv3.0
  14. html rtf转换,如何使用JavaScript将HTML转换为RTF
  15. Re27:读论文 LADAN Distinguish Confusing Law Articles for Legal Judgment Prediction
  16. Python GUI教程:信号、槽、事件
  17. 多系统折腾记录(老电脑MBR分区)
  18. 数字时代:DevOps工程师的必备技能清单
  19. HTML没有随手机静音,华为手机静音找不到?这个功能设置好,喊一声就可以找到!...
  20. iOS系统字体如何使用

热门文章

  1. (转)C#中的委托(Delegate)和事件(Event)
  2. Latex的空格 转载
  3. spring集成compass中出现的问题和总结
  4. STL不是线程安全的啊
  5. python制作软件excel_利用Python制作一个 截图+Excel操作浏览器小工具
  6. Java面向对象之抽象方法抽象类、接口的使用
  7. bug 执行nrm 报错internal/validators.js:121 throw new ERR_INVALID_ARG_TYPE(name, ‘string‘, value);
  8. python2.7安装报错_python2.7源码安装方式
  9. python爬虫--自学笔记
  10. java安装选择哪个可选功能_java章节习题及期末考试题答案.doc