若要使用您自己的協議追蹤外掛程式,您必須使用 WITH_TEST_TRACE_PLUGIN
CMake 選項將 MySQL 設定為 停用,因為一次只能載入一個協議追蹤外掛程式,且嘗試載入第二個外掛程式時會發生錯誤。如果您已經使用啟用測試協議追蹤外掛程式的方式來建置 MySQL 以瞭解其運作方式,則必須在您可以使用自己的外掛程式之前,重新建置不含該外掛程式的 MySQL。
本節討論如何撰寫名為 simple_trace
的基本協議追蹤外掛程式。此外掛程式提供一個架構,說明如何設定用戶端外掛程式描述符,並建立追蹤相關的回呼函式。在 simple_trace
中,這些函式很基本,除了說明必要的引數之外,幾乎沒有其他作用。若要詳細瞭解追蹤外掛程式如何使用追蹤事件資訊,請檢查測試協議追蹤外掛程式的原始碼檔案(MySQL 來源發行版 libmysql
目錄中的 test_trace_plugin.cc
)。但是,請注意,其中使用的 st_mysql_client_plugin_TRACE
結構與一般用戶端外掛程式宣告巨集中使用的結構不同。特別是,前兩個成員是明確定義的,而不是由宣告巨集隱含定義的。
數個標頭檔包含與協議追蹤外掛程式相關的資訊
client_plugin.h
:定義用戶端外掛程式的 API。這包含用戶端外掛程式描述符和用於用戶端外掛程式 C API 呼叫的函式原型(請參閱 C API 用戶端外掛程式介面)。plugin_trace.h
:包含MYSQL_CLIENT_TRACE_PLUGIN
類型用戶端外掛程式的宣告。它也包含允許的協議階段、階段之間的轉換以及每個階段允許的事件類型的描述。
若要撰寫協議追蹤外掛程式,請在外掛程式原始碼檔案中包含下列標頭檔。根據外掛程式功能和需求,也可能需要其他 MySQL 或一般標頭檔。
#include <mysql/plugin_trace.h>
#include <mysql.h>
plugin_trace.h
包含 client_plugin.h
,因此您不需要明確包含後者檔案。
使用 mysql_declare_client_plugin()
和 mysql_end_client_plugin
巨集宣告用戶端外掛程式描述符(請參閱第 4.4.2.3 節「用戶端外掛程式描述符」)。對於 simple_trace
外掛程式,描述符如下所示
mysql_declare_client_plugin(TRACE)
"simple_trace", /* plugin name */
"Author Name", /* author */
"Simple protocol trace plugin", /* description */
{1,0,0}, /* version = 1.0.0 */
"GPL", /* license type */
NULL, /* for internal use */
plugin_init, /* initialization function */
plugin_deinit, /* deinitialization function */
plugin_options, /* option-handling function */
trace_start, /* start-trace function */
trace_stop, /* stop-trace function */
trace_event /* event-handling function */
mysql_end_client_plugin;
從外掛程式名稱到選項處理函式的描述符成員,是所有用戶端外掛程式類型共用的。在通用成員之後的成員會實作追蹤事件處理。
外掛程式不需要處理的函式成員,可以在描述符中宣告為 NULL
,在這種情況下,您不需要撰寫任何對應的函式。為了說明和顯示引數語法,以下討論會實作描述符中列出的所有函式,即使其中某些函式沒有執行任何動作也是如此。
宣告所有用戶端外掛程式共用的初始化、取消初始化和選項函式,如下所示。如需引數和傳回值的說明,請參閱第 4.4.2.3 節「用戶端外掛程式描述符」。
static int
plugin_init(char *errbuf, size_t errbuf_len, int argc, va_list args)
{
return 0;
}
static int
plugin_deinit()
{
return 0;
}
static int
plugin_options(const char *option, const void *value)
{
return 0;
}
用戶端外掛程式描述符的追蹤特定成員是回呼函式。以下說明提供有關其使用方式的更多詳細資訊。每個成員都有第一個引數,該引數是指向外掛程式執行個體的指標,以防您的實作需要存取該執行個體。
trace_start()
:此函式會在每個追蹤連線的開始時呼叫(每個在外掛程式載入後開始的連線)。它會傳遞連線處理常式和追蹤開始的協議階段。trace_start()
會配置 trace_event()
函式需要的記憶體(若有的話),並傳回指向該記憶體的指標。如果不需要記憶體,則此函式會傳回 NULL
。
static void*
trace_start(struct st_mysql_client_plugin_TRACE *self,
MYSQL *conn,
enum protocol_stage stage)
{
struct st_trace_data *plugin_data= malloc(sizeof(struct st_trace_data));
fprintf(stderr, "Initializing trace: stage %d\n", stage);
if (plugin_data)
{
memset(plugin_data, 0, sizeof(struct st_trace_data));
fprintf(stderr, "Trace initialized\n");
return plugin_data;
}
fprintf(stderr, "Could not initialize trace\n");
exit(1);
}
trace_stop()
:此函式會在連線追蹤結束時呼叫。這通常發生在連線關閉時,但也可能會提早發生。例如,trace_event()
可以在任何時間傳回非零值,這會導致連線追蹤終止。trace_stop()
接著會被呼叫,即使連線尚未結束也是如此。
trace_stop()
會傳遞連線處理常式和指向 trace_start()
所配置記憶體的指標(如果沒有,則為 NULL
)。如果指標不是 NULL
,trace_stop()
應該解除配置記憶體。此函式不傳回任何值。
static void
trace_stop(struct st_mysql_client_plugin_TRACE *self,
MYSQL *conn,
void *plugin_data)
{
fprintf(stderr, "Terminating trace\n");
if (plugin_data)
free(plugin_data);
}
trace_event()
:此函式會針對每個事件發生次數呼叫。它會傳遞指向 trace_start()
所配置記憶體的指標(如果沒有,則為 NULL
)、連線處理常式、目前的協議階段和事件程式碼,以及事件資料。此函式會傳回 0 以繼續追蹤,如果應該停止追蹤,則會傳回非零值。
static int
trace_event(struct st_mysql_client_plugin_TRACE *self,
void *plugin_data,
MYSQL *conn,
enum protocol_stage stage,
enum trace_event event,
struct st_trace_event_args args)
{
fprintf(stderr, "Trace event received: stage %d, event %d\n", stage, event);
if (event == TRACE_EVENT_DISCONNECTED)
fprintf(stderr, "Connection closed\n");
return 0;
}
追蹤架構會在連線結束時關閉連線追蹤,因此只有在您想要提早終止連線追蹤時,trace_event()
才應該傳回非零值。假設您只想追蹤特定 MySQL 帳戶的連線。在驗證之後,您可以檢查連線的使用者名稱,如果不是您感興趣的使用者,則停止追蹤。
對於每次呼叫 trace_event()
,st_trace_event_args
結構會包含事件資料。其定義如下
struct st_trace_event_args
{
const char *plugin_name;
int cmd;
const unsigned char *hdr;
size_t hdr_len;
const unsigned char *pkt;
size_t pkt_len;
};
對於不同的事件類型,st_trace_event_args
結構包含以下說明的資訊。所有長度都以位元組為單位。未使用的成員設定為 0
/NULL
。
AUTH_PLUGIN
事件
plugin_name The name of the plugin
SEND_COMMAND
事件
cmd The command code
hdr Pointer to the command packet header
hdr_len Length of the header
pkt Pointer to the command arguments
pkt_len Length of the arguments
其他 SEND_
和 xxx
事件xxx
_RECEIVED
pkt Pointer to the data sent or received
pkt_len Length of the data
PACKET_SENT
事件
pkt_len Number of bytes sent
若要編譯和安裝外掛程式庫檔案,請使用第 4.4.3 節「編譯和安裝外掛程式庫」中的指示。若要讓程式庫檔案可供使用,請將其安裝在外掛程式目錄中(由 plugin_dir
系統變數命名的目錄)。
在外掛程式庫檔案編譯並安裝在外掛程式目錄中之後,您可以輕鬆地測試它,方法是將 LIBMYSQL_PLUGINS
環境變數設定為外掛程式名稱,這會影響使用該變數的任何用戶端程式。 mysql 就是這樣的一個程式
$> export LIBMYSQL_PLUGINS=simple_trace
shqll> mysql
Initializing trace: stage 0
Trace initialized
Trace event received: stage 0, event 1
Trace event received: stage 0, event 2
...
Welcome to the MySQL monitor. Commands end with ; or \g.
Trace event received
Trace event received
...
mysql> SELECT 1;
Trace event received: stage 4, event 12
Trace event received: stage 4, event 16
...
Trace event received: stage 8, event 14
Trace event received: stage 8, event 15
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> quit
Trace event received: stage 4, event 12
Trace event received: stage 4, event 16
Trace event received: stage 4, event 3
Connection closed
Terminating trace
Bye
若要停止載入追蹤外掛程式,請執行此操作
$> LIBMYSQL_PLUGINS=
也可以撰寫直接載入外掛程式的用戶端程式。您可以透過呼叫 mysql_options()
來設定 MYSQL_PLUGIN_DIR
選項,告訴用戶端外掛程式目錄的位置
char *plugin_dir = "path_to_plugin_dir";
/* ... process command-line options ... */
mysql_options(&mysql, MYSQL_PLUGIN_DIR, plugin_dir);
通常,程式也會接受 --plugin-dir
選項,讓使用者可以覆寫預設值。
如果用戶端程式需要較低層級的外掛程式管理,則用戶端程式庫包含採用 st_mysql_client_plugin
引數的函式。請參閱 C API 用戶端外掛程式介面。