免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1352 | 回复: 0
打印 上一主题 下一主题

Mysql源代码分析(6): Plugin架构介绍-续 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-01 22:47 |只看该作者 |倒序浏览
Mysql源代码分析(6): Plugin架构介绍-续上篇文章我们分析了Mysql的Plugin接口以及plugin的初始化过程,这里我们继续看plugin怎么被使用的。基本还是通过例子看问题,主要分析myisam如何通过plugin接口被调用的。
myisam是mysql最早的和默认的storage engine,前面我们也看到在plugin初始化的时候是优先初始化myisam,然后才初始化其他的存储引擎。这里我们假定用户要对一个myisam的表做操作,具体看看其中涉及的调用过程。
myisam的初始化
myisam plugin的定义可以在storage/myisam/ha_isam.cc中找到:
mysql_declare_plugin(myisam)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &myisam_storage_engine,
  "MyISAM",
  "MySQL AB",
  "Default engine as of MySQL 3.23 with great performance",
  PLUGIN_LICENSE_GPL,
  myisam_init, /* Plugin Init */
  NULL, /* Plugin Deinit */
  0x0100, /* 1.0 */
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
}
mysql_declare_plugin_end;
初始化函数是myisam_init。在前面文章中提到,storage engine类型的plugin均是通过ha_initialize_handlerton初始化。myisam_init的输入参数是void *p,实际上是handlerton*。handlerton在mysql中封装了访问一个存储引擎需要的接口,每个存储引擎在全局空间有一个handlerton对象,保存在对应的内存中plugin结构的data域中。该结构具体定义可以在sql/handler.h中找到。myisam_init做的事情很简单,设置handlerton中的各个域,其中最重要的域是create,被指向了一个函数myisam_create_handler,这个函数用来创建handler,用来对于数据库文件进行操作。
打开一个表数据库表是数据库中所有操作的基础,我们看看打开一个表需要做些什么。当一个select命令进来的时候,sql_parse.cc中的execute_sqlcom_select被执行,并被传入parse出来的所有该命令要用的到表。它会调用open_and_lock_tables来打开指定的表,然后调用open_and_lock_tables_derived,再调用open_tables,再调用open_table(sql_base.cc)。一大堆调用之后真正开始干实事儿的是open_unireg_entry,名字很奇怪,但是确实就是它开始打开表了,我们仔细将仔细看这个函数,以及它调用的函数。这个函数很长,其实大部分都是在做错误处理,最重要的就以下几行:
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, const char *alias, char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags) {
   ...
   share= get_table_share_with_create(thd, table_list, cache_key, cache_key_length, OPEN_VIEW |table_list->i_s_requested_object, &error);
   open_table_from_share(thd, share, alias, ...);
   ...
}
get_table_share_with_create是创建一个table_share结构,包括了同一个类型的表公用的数据结构,open_table_from_share则通过这个公用结构打开对应的要操作的表。
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, ...) {
  share= alloc_table_share(table_list, key, key_length)); //分配内存
  my_hash_insert(&table_def_cache, (uchar*) share);  // 加入cache,以后可以直接用
  open_table_def(thd, share, db_flags); // 代开表的定义,需要读frm文件
}
open_table_def是用来打开存储表定义的文件。mysql中,每个表都有一个.frm文件,存储了表的定义,这个函数就是要打开表对应的frm文件,读入定义信息,填入TABLE_SHARE结构。
int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) {
  file= my_open(path, O_RDONLY | O_SHARE, MYF(0))
  open_binary_frm(thd, share, head, file);
}
open_binary_frm读入二进制的frm文件信息。这个函数超长,但是我们暂时只是对与plugin相关的部分感兴趣。因为每个表的storage engine信息就是从frm文件中读出来的,我们看相关的代码片段:
open_binary_frm(...) {
  ...
  plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);   // name就是storage engine的名字,比如"myisam"。这里根据名字找到对应的plugin。
  share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);  // 保存plugin的引用,供以后使用。plugin中的"data"域就是handlerton*,这将是主要的使用plugin的入口。
  ...
}
好了,TABLE_SHARE设置好了,我们回到open_unireg_entry中,继续看open_table_from_share。这才是真正打开表的地方。这个函数还是在sql/table.cc中。这个函数还是超长...,万幸的是我们还是只想关注plugin相关的内容。TABLE中有一个file结构,类型是handler*,我们以前提到过,handler就是一个打开的表的引用,显然open_table_from_share的责任之一就是要设置这个域。
int open_table_from_share(THD *thd, TABLE_SHARE *share, ... TABLE *outparam, ...) {  // outparam是打开后的表信息。
   ...
   outparam->file= get_new_handler(share, &outparam->mem_root, share->db_type()));  // 直奔主题,获取一个handler。 share->db_type()返回plugin对应的handlerton,其实就是将plugin->data强制转换成handlerton.
   ... 
   outparam->file->ha_open(outparam, ...); // 调用plugin的handler定义的open函数,做自定义的open操作。
   ...
}
get_new_handler负责根据TABLE_SHARE的内容构造一个handler对象。这个函数在sql/handler.cc中。
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, handlerton *db_type) {
  file= db_type->create(db_type, share, alloc);  // 调用plugin的create函数,来创建handler成员。
  file->init();
}
前面我们提到过对于myisam对应的create函数是myisam_create_handler,这个函数就是new了一个ha_myisam对象,而ha_myisam又是从handler继承下来的,重载了handler对应的函数。
这样一个对于应数据库表文件的handler就可以使用啦,它的第一个使用就是在open_table_from_share中被调用ha_open。ha_open在handler.cc中定义,其实就是调用了重载后了open函数。在ha_myisam中,我们可以看到open函数的定义,这里我们就不仔细看了,实现细节和myisam的文件结构相关。
看到这里一个"SELECT * from test"语句如何打开表的部分就基本清楚了,主要过程包括:
从frm文件寻找storage engine的名字,并获取对应的storage engine plugin的handlerton
调用handlerton的create函数生成handler
通过handler重载的open函数打开表文件

挺清楚的。
到了这里,我们就有了表的handler,以后凡是涉及到存储引擎的操作,都通过这个接口调用来做,这样,storage engine plugin就和mysql核心紧密结合到了一起,各司其事,共同完成复杂的sql操作。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/72491/showart_1848008.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP