mysql源码学习笔记:插件的安装和卸载
来源:互联网 发布:乌龙山伯爵 知乎 编辑:程序博客网 时间:2024/06/04 18:28
版本
CentOS release 6.7环境下mysql-5.7.16 社区版
概述
mysql支持插件的开发,以插件的方式实现mysql的附加功能,既可以减少对mysql服务器源码的入侵,也可以实现动态的插拔。可以较好的实现我们需要的功能。
mysql维护一套插件框架来保证所有插件可以有效的运行,源码分析如下。
源码分析
插件的种类
当前在使用的插件共11种,在plugin.h中以宏的方式定义。其中MYSQL_MAX_PLUGIN_TYPE_NUM为插件的数量。
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */#define MYSQL_VALIDATE_PASSWORD_PLUGIN 8 /* validate password plugin type */#define MYSQL_GROUP_REPLICATION_PLUGIN 9 /* The Group Replication plugin */#define MYSQL_KEYRING_PLUGIN 10 /* The Keyring plugin type */#define MYSQL_MAX_PLUGIN_TYPE_NUM 11 /* The number of plugin types */
MySQL启动时插件初始化
...init_server_components // 插件初始化以配置文件、命令行输入的变量设置为输入参数 // 根据配置决定是否添加未装载的插件| plugin_init(&remaining_argc, remaining_argv // 初始化打开插件so的句柄数组 plugin_dl_array= new (std::nothrow) Prealloced_array<st_plugin_dl* ... // 初始化插件定义结构体的动态数组 plugin_array= new (std::nothrow) Prealloced_array<st_plugin_int* .... // 为每一种插件,初始化一个hash桶,用于存放该种类的插件 for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) if (my_hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0, // 装载静态插件,见后续描述 for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++) ...... // 装载动态插件,见后续描述 while (NULL != (item= iter++)) ......
装载静态插件
for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++){ tmp.plugin= plugin; //定义插件结构体 .... .... // 装载插件的系统变量 if (test_plugin_options(&tmp_root, &tmp, argc, argv)) | if (mysql_add_sys_var_chain(chain.first)) if (register_builtin(plugin, &tmp, &plugin_ptr)) | if (plugin_array->push_back(tmp)) // 将插件定义结构体,存入plugin_array中 | if (my_hash_insert(&plugin_hash[plugin->type],(uchar*) *ptr)) //根据插件类型,将差价定义结构体,放入hash桶中 if(...plugin_initialize(plugin_ptr)) // 调用插件自定义的初始化函数 | plugin->plugin->init(plugin) // 如果插件有状态变量,将状态变量加入到全局链表中 | if (add_status_vars(plugin->plugin->status_vars)) }
mysql_mandatory_plugins为编译时生成,存放binlog、password、innodb等插件的插件定义结构体,定义如下
struct st_mysql_plugin *mysql_mandatory_plugins[]={ builtin_binlog_plugin, builtin_mysql_password_plugin, builtin_innobase_plugin, builtin_csv_plugin, builtin_heap_plugin, builtin_myisammrg_plugin, builtin_myisam_plugin, builtin_perfschema_plugin, 0};
装载动态插件
在装载静态插件之前,会优先装在系统变量early-plugin-load 声明的插件
I_List_iterator<i_string> iter(opt_early_plugin_load_list); while (NULL != (item= iter++)) plugin_load_list(&tmp_root, argc, argv, item->ptr);
装载静态插件之后,装载系统变量plugin-load和plugin-load-add声明的插件
I_List_iterator<i_string> iter(opt_plugin_load_list); //系统变量while (NULL != (item= iter++)) plugin_load_list(&tmp_root, argc, argv, item->ptr); |while (list) // 装载插件链表 |plugin_dl_add(&dl, REPORT_TO_LOG))) // 动态的加载插件的so文件 // dl为插件的so名字,dlpath为的so全路径 plugin_dl.handle= dlopen(dlpath, RTLD_NOW))) // plugin_interface_version_sym为字符串_mysql_plugin_interface_version_ // plugin_declarations_sym为字符串"_mysql_plugin_declarations_" // sizeof_st_plugin_sym为字符串"_mysql_sizeof_struct_st_plugin_" // 在dlopen插件的so后,读取固定的变量名来获取插件的相关信息 if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym))) // 读取版本变量 if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym))) // 读取 if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym))) // 将动态库的句柄保存到全局变量plugin_dl_array中 plugin_dl_insert_or_reuse(&plugin_dl) |if (plugin_dl_array->push_back(plugin_dl)) // 根据so中读取信息,装载插件 |plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) // 装载流程同装载静态插件流程相同 for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++) tmp.plugin= plugin; //定义插件结构体 .... .... if (test_plugin_options(&tmp_root, &tmp, argc, argv)) if (register_builtin(plugin, &tmp, &plugin_ptr)) if(...plugin_initialize(plugin_ptr))
命令行安装和卸载插件
使用命令行命令安装插件,插件的具体装载流程同启动时装载大体相同
......mysql_execute_command| case SQLCOM_INSTALL_PLUGIN:| Sql_cmd_install_plugin::execute mysql_install_plugin // 初始化mysql.plugin表,为后续加入记录做准备 | tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE); | if (! (table = open_ltable(thd, &tables, TL_WRITE, ...... // 这里调用相同的接口来装载插件 | plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER); | (plugin_initialize(tmp) // 在mysql.plugin表中增加一条记录 | table->use_all_columns(); | restore_record(table, s->default_values); ...... | error= table->file->ha_write_row(table->record[0]);
命令行插件卸载
...mysql_execute_command| case SQLCOM_INSTALL_PLUGIN:| Sql_cmd_uninstall_plugin::execute mysql_uninstall_plugin // 初始化mysql.plugin表,为后续删除记录做准备 | tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE); | if (! (table = open_ltable(thd, &tables, TL_WRITE, ...... // 卸载插件 | reap_plugins | plugin_deinitialize // 删除系统状态变量 remove_status_vars(plugin->plugin->status_vars); // 如果存在系统定义的卸载函数,调用系统插件卸载函数 // 部分类型的插件存在,如audit、 if (plugin_type_deinitialize[plugin->plugin->type]) *plugin_type_deinitialize[plugin->plugin->type])(plugin) // 插件自定义卸载函数 (plugin->plugin->deinit(plugin) | plugin_del(plugin) // 删除系统变量 mysql_del_sys_var_chain(plugin->system_vars); ... plugin_vars_free_values(plugin->system_vars); // 在对应类型的hash桶中删除该插件 my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); // 在全局数组plugin_dl_array中清理dlopen的句柄 // 注意计数(存在多个插件使用一个so的情况) plugin_dl_del(&plugin->plugin_dl->dl); // 操作mysql.plugin表,将该插件对应的表记录删除 | table->use_all_columns(); | ...... | table->file->ha_delete_row(table->record[0])
阅读全文
1 0
- mysql源码学习笔记:插件的安装和卸载
- Mysql学习之--卸载源码mysql-5.6安装mysql-5.5
- MySQL的安装和卸载
- mysql的安装和卸载
- mysql的卸载和安装
- 二进制、源码安装的方式mysql卸载
- eclipse 插件的安装和卸载
- Eclipse用法:插件的安装和卸载
- Mysql学习笔记(1)-Ubuntu下安装和卸载Mysql
- 1.mysql学习笔记:mysql的源码安装
- linux下卸载mysql rpm安装方式和源码安装方式的两种方法
- linux下卸载mysql rpm安装方式 和 源码安装方式 的两种方法
- linux下卸载mysql rpm安装方式和源码安装方式的两种方法
- linux下卸载mysql rpm安装方式和源码安装方式的两种方法
- mysql卸载 学习笔记
- mysql安装和卸载
- linux mysql的卸载和安装 使用
- MySQL在Centos的卸载和安装
- 每日MySQL之026:MySQL的子查询(subquery)
- python sqlalchemy的应用
- wifi钓鱼的尝试
- 在O(1)时间内删除链表节点
- CentOS 7 下挂载NTFS文件系统
- mysql源码学习笔记:插件的安装和卸载
- 三国时期十大谋士
- 用JavaScript实现旋转轮播图
- CentOS 禁用与开启触摸板
- c++中抽象类和接口
- androidstudio二维码libzxing
- POJ 1005 I think I Need a Houseboat (水题)
- 安装 Genymotion
- 文本编辑器