目的
mysqlbinlog在分析mysql的binlog日志時,有時需要針對某個表的操作進行分析。但是這個表屬于“冷數據”,操作記錄相對較少,而其他表操作往往很頻繁,binlog日志量特別大。尤其是當binlog的模式設置為ROW時,情況就更加嚴重了,往往如大海撈針。為了提高獲取binlog日志的有效性,對mysqlbinlog功能進行擴展,增加table參數,分析指定數據庫的表操作記錄。
實現
以下實現基于MySQL 5.5.18源碼,實現思路:參考--database參數的邏輯;修改原則:盡量少的變更MySQL源碼,盡可能的優雅實現。
1、增加全局變量
首先增加兩個全局變量,用于存儲table參數的狀態和table的值,具體如下所示:
/* One table to filter out (Added by wangheng, email to wangheng.wh@alibaba-inc.com.).*/
staticbool one_table=0;
staticchar* table_name = 0;
2、增加過濾函數
過濾函數主要是根據one_table狀態和table的值,比較當前事件涉及的表是否需要獲取。具體如下所示:
/*
* Check the given table should be filtered out, according to the --table=X option
* @param
*???? log_tbname: Name of table.
* @return
*???? 0 : Skip.
*???? N: Filtered out.
* @author:? wangheng
* @email? : wangheng.wh@alibaba-inc.com
*/
staticbool shall_skip_table(const char *log_tbname)
{
return one_table &&
(log_tbname != NULL) &&
strcmp(log_tbname, table_name);
}
3、增加調用邏輯
分析發現,有表信息的Log_event結構有:Table_map_log_event和Create_file_log_event兩個結構,其中Table_map_log_event僅在ROW模式下有效,Create_file_log_event是在Load data時調用。為了盡快能少的減少修改引入的新問題,邏輯處理僅對這兩個部分增加過濾函數的邏輯調用。具體如下:
case CREATE_FILE_EVENT:
{
Create_file_log_event* ce= (Create_file_log_event*)ev;
if (shall_skip_database(ce->db)
/* Filtered out the events of given table. (Added by wangheng, email to wangheng.wh@alibaba-inc.com) */
|| shall_skip_table(ce->table_name))
……
case TABLE_MAP_EVENT:
{
Table_map_log_event *map= ((Table_map_log_event *)ev);
if (shall_skip_database(map->get_db_name())
/* Filtered out the events of given table.(Added by wangheng, email to wangheng.wh@alibaba-inc.com.). */
|| shall_skip_table(map->get_table_name()))
4、增加輸入參數選項
在my_long_options參數選項中增加輸入參數--table/-T,用于設置過濾的表名。具體如下:
/*Add the -T/--table option. (Added by wangheng, email to wangheng.wh@alibaba-inc.com.)*/
{"table", 'T', "List entries for just this table in given database of -d/--database option. (row mode only).",
&table_name, &table_name, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
5、釋放參數變量
因為table_name參數選項,在處理時分配了內存空間,在cleanup()函數中,釋放table_name變量。具體如下:
/* Free the table name. (Added by wangheng, email to wangheng.wh@alibaba-inc.com.)*/
my_free(table_name);
6、設置標記變量
在table參數設置后,通過one_table變量標記當前有表需要過濾,從而在shall_skip_table()時過濾表操作記錄。需要在get_one_option()函數中,設置one_table變量。具體如下:
/* Set the table filter flag. (Added by wangheng, email to wangheng.wh@alibaba-inc.com.)*/
case't':
one_table = 1;
break;
以上過程,盡可能少的對MySQL源碼進行修改,擴展部分盡可能保證不影響正常的處理邏輯。
PATCH
為了方便使用mysqlbinlog的擴展功能,基于MySQL 5.5.18官方源碼修改,patch發布在github上分享。
patch發布在:
相關的說明文檔:
結論:
通過擴展mysqlbinlog功能,增加-T/--table參數,設置過濾數據表的操作記錄,提高mysqlbinlog獲取數據的有效性,減少分析數據的范圍。然而,由于Query_log_event事件類型中沒有提供tables信息,導致binlog在MIX和STATEMENT模式下,不能盡可能的過濾有效操作記錄。