天天看點

深入了解MySQL 5.7 GTID系列(九):實際案例一

原文位址:

https://www.jianshu.com/p/2c25842d58d3

深入了解MySQL 5.7 GTID系列文章共十篇,本文為第四篇,點選檢視:

第一篇:

深入了解MySQL 5.7 GTID系列(一) 第二篇: 深入了解MySQL 5.7 GTID系列(二):GTID相關内部資料結構 第三篇: 深入了解MySQL 5.7 GTID系列(三):GTID的生成時機 第四篇: 深入了解MySQL 5.7 GTID系列(四):mysql.gtid_executed&PREVIOUS GTID EVENT 第五篇: 深入了解MySQL 5.7 GTID系列(五) gtid_executed&gtid_purged什麼時候更新 第六篇: 深入了解MySQL 5.7 GTID系列(六):MySQL啟動初始化GTID子產品 第七篇: 深入了解MySQL 5.7 GTID系列(七)binlog_gtid_simple_recovery參數的影響總結 第八篇: 深入了解MySQL 5.7 GTID系列(八):GTID帶來的運維改變

該系列文章将陸續不定期更新~

一、觸發條件

深入了解MySQL 5.7 GTID系列(九):實際案例一
binlog_gtid_simple_recovery=false。
深入了解MySQL 5.7 GTID系列(九):實際案例一
5.7.6以上版本。
深入了解MySQL 5.7 GTID系列(九):實際案例一

GTID 關閉或者GTID中途開啟有大量的未開啟GTID的BINLOG。

二、本案例回顧

深入了解MySQL 5.7 GTID系列(九):實際案例一
版本:MySQL版本 5.7.19。
深入了解MySQL 5.7 GTID系列(九):實際案例一
故障為:大概每半小時發生一次故障,整個MySQL壓力巨大,很多簡單的操作都相應緩慢。使用iotop,top等工具都發現MySQL某個線程有大量的I/O。
深入了解MySQL 5.7 GTID系列(九):實際案例一
分析方法:使用strace發現有大量的BINLOG檔案讀取。
深入了解MySQL 5.7 GTID系列(九):實際案例一
深入了解MySQL 5.7 GTID系列(九):實際案例一
GTID關閉,中途開啟,但是留下了很多未開啟GTID的BINLOG。
深入了解MySQL 5.7 GTID系列(九):實際案例一

資料庫沒有重新開機,但是由于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 binary logs ,我們觀察到:

深入了解MySQL 5.7 GTID系列(九):實際案例一

受限篇幅我這裡删除了一些。我們看到很多read/lseek系統調用正是讀取BINLOG的證據。

至此整個案例模拟完成。

五、總結

前文已經描述過在5.7.6以上binlog_gtid_simple_recovery應該設定為true,這樣可以避免可能的大量的BINLOG的掃描。具體分析可以參考第七節和從第六部分源碼bool MYSQL_BIN_LOG::init_gtid_sets()函數的分析。

原文釋出時間為:2018-04-13

本文作者:高鵬(重慶八怪)

本文來自雲栖社群合作夥伴“

老葉茶館

”,了解相關資訊可以關注“

”。