若要使用您自己的協定追蹤外掛程式,您必須設定 MySQL 時將 WITH_TEST_TRACE_PLUGIN
CMake 選項 停用,因為一次只能載入一個協定追蹤外掛程式,並且嘗試載入第二個時會發生錯誤。如果您已經啟用測試協定追蹤外掛程式來建置 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 目錄中(由 plugin_dir
系統變數命名的目錄)。
在外掛程式庫檔案編譯並安裝在 plugin 目錄中之後,您可以透過將 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 用戶端外掛程式介面。