原文位址:
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>id_purged什麼時候更新 第六篇: 深入了解MySQL 5.7 GTID系列(六):MySQL啟動初始化GTID子產品 第七篇: 深入了解MySQL 5.7 GTID系列(七)binlog_gtid_simple_recovery參數的影響總結 第八篇: 深入了解MySQL 5.7 GTID系列(八):GTID帶來的運維改變該系列文章将陸續不定期更新~
一、觸發條件



GTID 關閉或者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 binary logs ,我們觀察到:
受限篇幅我這裡删除了一些。我們看到很多read/lseek系統調用正是讀取BINLOG的證據。
至此整個案例模拟完成。
五、總結
前文已經描述過在5.7.6以上binlog_gtid_simple_recovery應該設定為true,這樣可以避免可能的大量的BINLOG的掃描。具體分析可以參考第七節和從第六部分源碼bool MYSQL_BIN_LOG::init_gtid_sets()函數的分析。
原文釋出時間為:2018-04-13
本文作者:高鵬(重慶八怪)
本文來自雲栖社群合作夥伴“
老葉茶館”,了解相關資訊可以關注“
”。