深入理解MySQL 5.7 GTID系列(十):实际案例二

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 1一、触发条件 本案列我测试过4个版本:percona Mysql 5.7.14 官方社区 Mysql 5.7.17 percona Mysql 5.7.19 percona Mysql 5.7.15 其中percona Mysql 5.7.14和官方社区 Mysql 5.7.17有这个问题。

一、触发条件

本案列我测试过4个版本:
percona Mysql 5.7.14
官方社区 Mysql 5.7.17
percona Mysql 5.7.19
percona Mysql 5.7.15

其中percona Mysql 5.7.14和官方社区 Mysql 5.7.17有这个问题。其他版本未知

d47e62d2b349aca45e42305ed6714efbe5ed61d9 已知percona Mysql 5.7.14或者官方社区 Mysql 5.7.17
d47e62d2b349aca45e42305ed6714efbe5ed61d9 mysqldump备份没有使用 -F, --flush-logs选项

d47e62d2b349aca45e42305ed6714efbe5ed61d9Gtid打开

二、故障描述

本故障主要是新搭建的Gtid主从库,运行一段时间后重启主从必然报错如下:

Last_IO_Error: Got fatal error 1236 from master when reading data from 
binary log: 'The slave is connecting using CHANGE MASTER TO 
MASTER_AUTO_POSITION = 1, but the master has purged binary logs 
containing GTIDs that the slave requires.'
AI 代码解读

三、故障分析

为什么重启后会报错找不到事务呢,后来发现这个Gtid事务在主库的binlog中已经没有了,应该是很久以前的。其实这个问题我们要回到mysqldump出来的文件如何进行Gtid的初始化以及mysql.gtid_executed表中。
在mysqldump不使用--set-gtid-purged的时候必然会在dump出来的脚本中包含

-- GTID state at the beginning of the backup 
 SET @@GLOBAL.GTID_PURGED='e859a28b-b66d-11e7-8371-000c291f347d:1-41';
AI 代码解读

这样一个设置GTID_PURGED的语句,它包含了主库上已经执行的全部Gtid事务。从第五节的源码和总结部分我们知道这个语句至少做了三个更改(DBA可见的只有三个):

d47e62d2b349aca45e42305ed6714efbe5ed61d9 mysql.gtid_executed表的写入
d47e62d2b349aca45e42305ed6714efbe5ed61d9 gtid_executed变量的修改
d47e62d2b349aca45e42305ed6714efbe5ed61d9 gtid_purged变量的修改

而完成了这一步实际上mysql.gtid_executed表是包含了全部的执行过的Gtid事务的,但是随后我们看到dump脚本包含了如下语句

680e58e44bf1e65b9606a0b25a223a4b0c28af6f

显然这里我们在source的时候从库的mysql.gtid_executed将被重新初始化为:

'e859a28b-b66d-11e7-8371-000c291f347d',1,32
AI 代码解读

而实际的已经执行过的Gtid是:

'e859a28b-b66d-11e7-8371-000c291f347d:1-41';
AI 代码解读

如前文第五节我们通过源码分析后总结如下:

mysql.gtid_executed表修改时机
在binlog发生切换(rotate)的时候保存直到上一个binlog文件执行过的全部Gtid,它不是实时更新的。
AI 代码解读

因此此时表中并没有完全包含全部执行过的Gtid事务,而在前文第六节的源码分析中我们知道在Gtid模块启动的时候必须要读取两个Gtid持久化的介质:

d47e62d2b349aca45e42305ed6714efbe5ed61d9 mysql.gtid_executed
d47e62d2b349aca45e42305ed6714efbe5ed61d9 binlog

来判断Gtid的集合,显然从库不可能在binlog包含这个Gtid事务,所以这样的操作步骤就导致了数据库从库后的报错,而这里的正确的步骤是压根不进行mysql.gtid_executed的重建和导入,我发现在percona Mysql 5.7.15和percona Mysql 5.7.19正是这样的。但是为了防范这个问题,我在搭建的Gtid从库导完数据后加入了两个个步骤如下:

reset master;set global gtid_purged='e859a28b-b66d-11e7-8371-000c291f347d:1-41';
AI 代码解读

这两步也就是为了从新初始化mysql.gtid_executed表,让其正确。
此问题还可以在mysqldump的时候加入-F, --flush-logs选项规避,但是-F会加入如下的MDL LOCK:

e144c4ed18df9a7e76e0ff415239979b7cec3a47

这把锁是GLOBAL级别的MDL_SHARED(S)锁,它会等到你说有的SELECT/DML/DDL语句结束后才能获得,同时会堵塞全部的SELECT/DML/DDL虽然持有时间很短如下:

4def28888ccd2230b32057608ffb539ce65ebb8e

当然要了解MDL LOCK的朋友可以参考我的文章:
http://blog.itpub.net/7728585/viewspace-2143093/
MYSQL METADATA LOCK(MDL LOCK)学习(1) :理论知识和加锁类型测试
四、故障模拟

知道了原因后也是很好模拟我使用的版本是社区版5.7.17,搭建过程就是前面说的步骤。只是导完数据后不使用reset master和set gtid_purged表进行重新初始化mysql.gtid_executed表。搭建完成后做几个事务状态正常如下:

mysql> show slave status \G
*************************** 1. row ***************************
 Master_Log_File: binlog.000002
 Read_Master_Log_Pos: 5077
 Relay_Log_File: test1-relay-bin.000002
 Relay_Log_Pos: 2498
 Relay_Master_Log_File: binlog.000002
 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes
 Exec_Master_Log_Pos: 5077
 Relay_Log_Space: 2705
 Last_IO_Errno: 0
 Last_IO_Error: 
 Seconds_Behind_Master: 0
 Retrieved_Gtid_Set: e859a28b-b66d-11e7-8371-000c291f347d:42-49
 Executed_Gtid_Set: e859a28b-b66d-11e7-8371-000c291f347d:1-49
 Auto_Position: 1
AI 代码解读

但是这个时候我们发现mysql.gtid_executed表已经出现了问题如下:

00c47d7ad5cd85b53055bd0ab1c4ca11d91e38d4

很容易发现33-41之间是没有持久化的。如果这个时候如果我们使用purge binary logs to 来清理掉主库的日志那么必将出现问题,如果不清理也会出现Gtid事物重新执行的情况。我们做清理模拟线上错误。主库执行:

mysql> show binary logs;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000001 | 9974 |
| binlog.000002 | 5121 |
| binlog.000003 | 194 |
+---------------+-----------+
3 rows in set (0.01 sec)

mysql> purge binary logs to 'binlog.000003';
Query OK, 0 rows affected (0.04 sec)

mysql> show binary logs;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000003 | 194 |
+---------------+-----------+
1 row in set (0.00 sec)
AI 代码解读

备库重启后错误重现:

c900c6b79c9a8f2d2f05b3691f787c8785a0c558

我们发现I/O thread 试图获取主库的33-41的Gtid事务的事务,已经不能获取,实际上即使能获取也会造成事务的重新执行,我们看到Executed_Gtid_Set已经出现了两个连续的区间:

Executed_Gtid_Set: e859a28b-b66d-11e7-8371-000c291f347d:1-32:42-49
AI 代码解读

五、总结

前文已经描述过mysql.gtid_executed表的作用和其更改时机,如果我们对其有深刻的了解这个案例也是很容易分析的,当然解决办法在第八节主从搭建的步骤中我已经给出了,也就是在搭建完成后进行reset master和set global gtid_pruged两步重新初始化一下mysql.gtid_executed表。


原文发布时间为:2018-04-25

本文作者:高鹏(重庆八怪)

本文来自云栖社区合作伙伴“老叶茶馆”,了解相关信息可以关注“老叶茶馆”。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
73530
分享
相关文章
数据库数据恢复——MySQL简介和数据恢复案例
MySQL数据库数据恢复环境&故障: 本地服务器,安装的windows server操作系统。 操作系统上部署MySQL单实例,引擎类型为innodb,表空间类型为独立表空间。该MySQL数据库没有备份,未开启binlog。 人为误操作,在用Delete命令删除数据时未添加where子句进行筛选导致全表数据被删除,删除后未对该表进行任何操作。
服务器数据恢复—云服务器上mysql数据库数据恢复案例
某ECS网站服务器,linux操作系统+mysql数据库。mysql数据库采用innodb作为默认存储引擎。 在执行数据库版本更新测试时,操作人员误误将在本来应该在测试库执行的sql脚本在生产库上执行,导致生产库上部分表被truncate,还有部分表中少量数据被delete。
85 25
MySQL原理简介—11.优化案例介绍
本文介绍了四个SQL性能优化案例,涵盖不同场景下的问题分析与解决方案: 1. 禁止或改写SQL避免自动半连接优化。 2. 指定索引避免按聚簇索引全表扫描大表。 3. 按聚簇索引扫描小表减少回表次数。 4. 避免产生长事务长时间执行。
MySQL原理简介—6.简单的生产优化案例
本文介绍了数据库和存储系统的几个主题: 1. **MySQL日志的顺序写和数据文件的随机读指标**:解释了磁盘随机读和顺序写的原理及对数据库性能的影响。 2. **Linux存储系统软件层原理及IO调度优化原理**:解析了Linux存储系统的分层架构,包括VFS、Page Cache、IO调度等,并推荐使用deadline算法优化IO调度。 3. **数据库服务器使用的RAID存储架构**:介绍了RAID技术的基本概念及其如何通过多磁盘阵列提高存储容量和数据冗余性。 4. **数据库Too many connections故障定位**:分析了MySQL连接数限制问题的原因及解决方法。
100 23
10个案例告诉你mysql不使用子查询的原因
大家好,我是V哥。上周与朋友讨论数据库子查询问题,深受启发。为此,我整理了10个案例,详细说明如何通过优化子查询提升MySQL性能。主要问题包括性能瓶颈、索引失效、查询优化器复杂度及数据传输开销等。解决方案涵盖使用EXISTS、JOIN、IN操作符、窗口函数、临时表及索引优化等。希望通过这些案例,帮助大家在实际开发中选择更高效的查询方式,提升系统性能。关注V哥,一起探讨技术,欢迎点赞支持!
322 5
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
一个 MySQL 数据库死锁的案例和解决方案
本文介绍了一个 MySQL 数据库死锁的案例和解决方案。
463 3
基于案例分析 MySQL 权限认证中的具体优先原则
【10月更文挑战第26天】本文通过具体案例分析了MySQL权限认证中的优先原则,包括全局权限、数据库级别权限和表级别权限的设置与优先级。全局权限优先于数据库级别权限,后者又优先于表级别权限。在权限冲突时,更严格的权限将被优先执行,确保数据库的安全性与资源合理分配。
108 4
案例剖析,MySQL共享锁引发的死锁问题!
案例剖析,MySQL共享锁引发的死锁问题!
大数据-117 - Flink DataStream Sink 案例:写出到MySQL、写出到Kafka
大数据-117 - Flink DataStream Sink 案例:写出到MySQL、写出到Kafka
471 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等