技術分享 | dbslower 工具學習之探針使用
愛可生 · 程式 ·

技術分享 | dbslower 工具學習之探針使用

作者:王悅


Copyright (C) 2021 wingYue


本文來源:原創投稿


*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。


最近使用了 bcc 工具集中的 dbslower ,這個工具可以探測 MYSQL 指定閾值下的慢 query ,使用非常方便。

使用舉例:

是一個python腳本,於是打開學習一下內部的機制。首先開

因為這個工具是一個 python 腳本,於是打開學習一下內部的機制。

首先開始的一段是一些使用案例:

,使用非常方便。使用舉例:因為這個工具

這裡我們關注這兩個:

dbslower mysql -p 480 -m 30 # trace MySQL queries slower than 30msdbslower mysql -x $(which mysqld) # trace MySQL queries with uprobes

同樣是檢測慢日誌,一種是提供 pid ,另一種是提供二進位文件地址,粗看之下只是使用方式的不同,其實其中完全走向了不同的機制。

我們接著看下一段

slower,這個工具可以探測MYSQL指定閾值下的慢query

這一段是用來確認最終使用的機制 mode ,如果提供 pid ,那麼 mode=「MYSQL57」 ,如果提供的是二進位地址,那麼 mode=「USDT」 。

這裡 USDT 指的是(Userland Statically Defined Tracing)用戶態靜態探針,也就是說,當使用 pid 時,腳本實際使用了 USDT 靜態探針機制,而使用二進位文件時,則使用了另一種動態探針機制。要繼續理解下面的段落,我們先來看一下靜態探針和動態探針到底是指什麼。

探針的分類

探針大致可以分為兩類,靜態探針和動態探針。

靜態探針就比如我們上文看到的 USDT ,對應 MySQL 中,則是 MySQL DTrace 的實現。這類探針需要事先在代碼中定義並在編譯時開啟。

需要說明的是 MySQL DTrace 在 MySQL5.7.18 被棄用,在 MySQL8.0 被徹底刪除,所以我們只能在早期的版本中進行 DTrace 檢測。MySQL 的 DTrace 包含了很多的探針,比如 query-start 和 query-done 用於檢測一條語句的執行過程,比如 connection-start 和 connection-done 用於檢測客戶端連接的過程,這些探針都是需要在代碼中實現的。且啟用探針需要增加編譯參數 -DENABLE_DTRACE=1。

來源。最近使用了bcc工具集中的db

我們來看一個官方示例直觀的了解一下:

https://dev.MySQL.com/doc/refman/5.7/en/dba-DTrace-server.html

這裡使用了 query-start 和 query-done 這兩個探針,來獲取語句執行時間

編輯 DTrace 腳本

*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明

執行效果

可惜靜態探針在新版的 MySQL 上已經沒有了,我們就不去深究了。

除了靜態探針,還有一類是動態探針,就比如bfs技術中經常使用到的 uprobes 和 kprobes ,這類探針比較靈活,可以在程序運行時動態添加,如果熟悉代碼,可謂是神器。

我使用 MySQL8.0 作為實驗環境,簡單寫了一個利用 uprobes 列印 query 的示例。

2021wingYue本文來源:原創投稿

這裡的關鍵在於{ printf("%s\n", str(*arg1)); },意思是列印出 dispatch_command方 法的第二個參數指向的內容。

同樣的原理,變更一下函數,能動態列印任何我們想要的變量內容,或者利用探針寫一些 bpf 腳本,能夠實現許多功能,十分好用。

好了,回到我們的 dbslower 腳本上來。實際上這個腳本同時實現了靜態探針和動態探針兩種機制。

作者:王悅Copyright(C)

當我們使用 pid 時,比如dbslower MySQL -p 480 -m 30 ,變量 mode 值為 「USDT」 ,走入了上圖的 else 段落,即利用了query__startquery__done 這兩個靜態探針,當探針被觸發時,掛載到對應的處理函數query_startquery_end,這兩個處理函數中的邏輯很簡單,就是獲取對應的 query 內容,記錄時間等,有興趣的話可以去腳本中查看,這裡就不羅列了。

另一種情況,當我們使用二進位文件地址時,比如dbslower MySQL -x $(which MySQLd) ,變量 mode 值為 「MYSQL57」 ,走入了上圖的if段落,mysql_func_name 在腳本中被賦予的值是 dispatch_command 函數,即利用了 bfp ,在函數 dispatch_command 執行前後插入了動態探針,同樣的,當探針被觸發時,掛載到對應的處理函數query_startquery_end進行時間的計算。

總結

  1. dbslower 腳本利用探針檢測 MySQL query 執行時間。
  2. 當 dbslower 使用 pid 時,實際利用了靜態探針機制,需要在編譯時開啟-DENABLE_DTRACE=1 ,且該機制在 MySQL 新版本中被刪除了,需要特別注意。
  3. 當 dbslower 使用 mysqld 二進位路徑時,實際是利用了動態探針機制,動態探針可以在程序運行時動態添加,無論新舊版本的 MySQL 都可以使用。
  4. bpf 的 uprobe 動態探針十分靈活,熟練使用之後,對一些故障排查場景是一大利器,缺點是多數情況下需要對照代碼進行配置。
聲明:文章觀點僅代表作者本人,PTTZH僅提供信息發布平台存儲空間服務。
喔!快樂的時光竟然這麼快就過⋯
繼續其他精彩內容吧!
more