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

語言: CN / TW / HK

作者:王悅

Copyright (C) 2021 wingYue

本文來源:原創投稿

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

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

使用舉例:

因為這個工具是一個 python 指令碼,於是開啟學習一下內部的機制。

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

這裡我們關注這兩個:

dbslower mysql -p 480 -m 30  # trace MySQL queries slower than 30ms

dbslower mysql -x $(which mysqld)  # trace MySQL queries with uprobes

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

我們接著看下一段

這一段是用來確認最終使用的機制 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。

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

https://dev.MySQL.com/doc/ref...

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

編輯 DTrace 指令碼

執行效果

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

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

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

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

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

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

當我們使用 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 動態探針十分靈活,熟練使用之後,對一些故障排查場景是一大利器,缺點是多數情況下需要對照程式碼進行配置。