ITPub博客

首页 > 数据库 > 数据库开发技术 > mysql代码阅读-插件加载及存储引擎接入

mysql代码阅读-插件加载及存储引擎接入

原创 数据库开发技术 作者:liiinuuux 时间:2015-12-11 11:23:53 0 删除 编辑
初始化plugin流程

点击(此处)折叠或打开

  1. main()
  2.   -> mysqld_main()
  3.     -> init_server_components()
  4.       -> plugin_init()
  5.         -> plugin_initialize(struct st_plugin_int *plugin)

plugin_init从两个plugin数组里提取plugin。
一个是mysql_mandatory_plugins,保存强制插件
第二个是mysql_optional_plugins,存放可选插件
数组的最后一个元素时0,这点很重要
sql/sql_builtin.cc:

点击(此处)折叠或打开

  1. struct st_mysql_plugin *mysql_optional_plugins[]=
  2. {
  3.    builtin_blackhole_plugin, builtin_innobase_plugin, builtin_federated_plugin, builtin_perfschema_plugin, builtin_archive_plugin, builtin_partition_plugin, 0
  4. };

  5. struct st_mysql_plugin *mysql_mandatory_plugins[]=
  6. {
  7.   builtin_binlog_plugin, builtin_mysql_password_plugin, builtin_myisam_plugin, builtin_csv_plugin, builtin_heap_plugin, builtin_myisammrg_plugin, 0
  8. }

plugin_init初始化插件的代码

点击(此处)折叠或打开

  1. // 先循环mysql_mandatory_plugins
  2.   for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++)
  3.   {
  4.     /*
  5.     当循环到mysql_mandatory_plugins最后,遇到0,"!*builtins"就会成立,
  6.     此时将builtins指向mysql_optional_plugins并且将mandatory标记设为false。
  7.     这样虽然builtins指向其它数组了,但是最外层for的“builtins++”可以正常执行
  8.     由于mandatory变成false了,因此当遇到mysql_optional_plugins最后一个元素“0”的时候,
  9.     就不满足最外层的“*builtins || mandatory”了,至此插件加载顺利结束。
  10.     */
  11.     if (!*builtins)
  12.     {
  13.       builtins= mysql_optional_plugins;
  14.       mandatory= false;
  15.       if (!*builtins)
  16.         break;
  17.     }
  18.     for (plugin= *builtins; plugin->info; plugin++)
  19.     {
  20.       ...
  21.       if (plugin_ptr->state != PLUGIN_IS_UNINITIALIZED ||
  22.           // 插件的初始化工作由plugin_initialize函数来组织
  23.           plugin_initialize(plugin_ptr))
  24.         goto err_unlock;
  25.       ...

各类plugin的初始化函数被放到一个由这些函数的指针组成的数组plugin_type_initialize里
每个plugin的类型plugin->plugin->type是一个整数,用它作为下标访问plugin_type_initialize,就能得到初始化这类plugin所需的函数。

点击(此处)折叠或打开

  1. plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
  2. {
  3.   0,ha_initialize_handlerton,0,0,initialize_schema_table,
  4.   initialize_audit_plugin,0,0,0
  5. };

plugin_initialize里具体初始化plugin的地方,调的是函数指针

点击(此处)折叠或打开

  1. if (plugin_type_initialize[plugin->plugin->type])
  2.   {
  3.     if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
  4.     {
  5.       sql_print_error("Plugin '%s' registration as a %s failed.",
  6.                       plugin->name.str, plugin_type_names[plugin->plugin->type].str);
  7.       goto err;
  8.     }
  9.     ...

如果plugin是存储引擎,plugin->plugin->type的值就是1,初始化工作就是调用plugin_type_initialize[1],也就是ha_initialize_handlerton。
前面代码的(*plugin_type_initialize[plugin->plugin->type])(plugin)就等价于ha_initialize_handlerton(plugin)
plugin_type_initialize主要工作初始化handlerton,存到plugin->data里。然后将存储引擎的handlerton记录下来。
以后使用存储引擎需要用到handlerton里的信息。

每个存储引擎还需要加载不同的handler,存储引擎各自的“plugin->plugin->init”函数指针指向其handler的初始化函数。
ha_initialize_handlerton直接调用“plugin->plugin->init”

点击(此处)折叠或打开

  1. int ha_initialize_handlerton(st_plugin_int *plugin)
  2. {
  3.   handlerton *hton;
  4.   ...
  5.   hton= (handlerton *)my_malloc(sizeof(handlerton),
  6.                                 MYF(MY_WME | MY_ZEROFILL));
  7.   ...
  8.   plugin->data= hton; // shortcut for the future
  9.   if (plugin->plugin->init && plugin->plugin->init(hton))
  10.   {
  11.     sql_print_error("Plugin '%s' init function returned error.",
  12.                     plugin->name.str);
  13.     goto err;
  14.   }

以innodb为例plugin->plugin->init指向的是下面的innobase_init。每个存储引擎有自己的xxx_init

点击(此处)折叠或打开

  1. static
  2. int
  3. innobase_init(
  4. /*==========*/
  5.   void *p) /*!< in: InnoDB handlerton */
  6. {
  7.   ...
  8.   /*
  9.   将创建innodb的handler的函数指针放到handlerton->create。
  10.   以后每次打开一张innodb表都需要用它创建一个innodb handler。
  11.   */
  12.   innobase_hton->create = innobase_create_handler;
  13.   ...

innobase_create_handler内容很简单,就是调用ha_innobase的构造函数。
其它的也类似比如myisam的就是调ha_myisam的构造函数

点击(此处)折叠或打开

  1. static
  2. handler*
  3. innobase_create_handler(
  4. /*====================*/
  5.   handlerton* hton, /*!< in: InnoDB handlerton */
  6.   TABLE_SHARE* table,
  7.   MEM_ROOT* mem_root)
  8. {
  9.   return(new (mem_root) ha_innobase(hton, table));
  10. }

ha_innobase继承自mysql定义的handler类,handler里规定了存储引擎需要完成的各类操作
如:

点击(此处)折叠或打开

  1. virtual int update_row(const uchar *old_data __attribute__((unused)),
  2.                          uchar *new_data __attribute__((unused)))
  3.   {
  4.     return HA_ERR_WRONG_COMMAND;
  5.   }


  6.   virtual int delete_row(const uchar *buf __attribute__((unused)))
  7.   {
  8.     return HA_ERR_WRONG_COMMAND;
  9.   }
  10.   virtual int truncate()
  11.   { return HA_ERR_WRONG_COMMAND; }
  12. ...

因此mysql不需要知道innodb的细节,
只要将ha_innobase视为handler,调用handler的函数,就能使用innodb的功能

点击(此处)折叠或打开

  1. class ha_innobase: public handler
  2. {
  3.   ...
  4. }

这就是mysql与plugin形式的存储引擎对接的方式

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-1870316/,如需转载,请注明出处,否则将追究法律责任。

上一篇: mysql报Can
请登录后发表评论 登录
全部评论

注册时间:2012-11-12

  • 博文量
    94
  • 访问量
    308346