阿里巴巴DBA,原去哪儿网DBA。专注于MySQL源码研究、DBA运维、CGroup虚拟化及Linux Kernel源码研究等。 github:https://github.com/HengWang/ Email:king_wangheng@163.com 微博 :@王恒-Henry QQ :506437736
分类: Mysql/postgreSQL
2013-08-06 00:47:45
mysqlbinlog在分析mysql的binlog日志时,有时需要针对某个表的操作进行分析。但是这个表属于“冷数据”,操作记录相对较少,而其他表操作往往很频繁,binlog日志量特别大。尤其是当binlog的模式设置为ROW时,情况就更加严重了,往往如大海捞针。为了提高获取binlog日志的有效性,对mysqlbinlog功能进行扩展,增加table参数,分析指定数据库的表操作记录。
以下实现基于MySQL 5.5.18源码,实现思路:参考--database参数的逻辑;修改原则:尽量少的变更MySQL源码,尽可能的优雅实现。
首先增加两个全局变量,用于存储table参数的状态和table的值,具体如下所示:
/* One table to filter out (Added by wangheng, email to wangheng.wh@alibaba-inc.com.).*/ static bool one_table=0; static char* table_name = 0; |
过滤函数主要是根据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 */ static bool shall_skip_table(const char *log_tbname) { return one_table && (log_tbname != NULL) && strcmp(log_tbname, table_name); } |
分析发现,有表信息的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())) |
在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}, |
因为table_name参数选项,在处理时分配了内存空间,在cleanup()函数中,释放table_name变量。具体如下:
/* Free the table name. (Added by wangheng, email to wangheng.wh@alibaba-inc.com.)*/ my_free(table_name); |
在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源码进行修改,扩展部分尽可能保证不影响正常的处理逻辑。
为了方便使用mysqlbinlog的扩展功能,基于MySQL 5.5.18官方源码修改,patch发布在github上分享。
patch发布在:
;
相关的说明文档:
。
通过扩展mysqlbinlog功能,增加-T/--table参数,设置过滤数据表的操作记录,提高mysqlbinlog获取数据的有效性,减少分析数据的范围。然而,由于Query_log_event事件类型中没有提供tables信息,导致binlog在MIX和STATEMENT模式下,不能尽可能的过滤有效操作记录。