MySQL的整体架构为server-engine架构,server层与engine层分开,具体来说,engine也是以插件plugin形式实现的。本文将通过源码,分析MySQL在启动、加载插件的过程中的一些细节。
源码版本:
Percona Server for MySQL 5.7.19
源码文件:
sql/mysqld.ccsql/sql_plugin.cc先通过GDB调试源码看一下MySQL InnoDB存储引擎初始化的函数调用图,如下:
plugin_init为插件初始化的函数,在这个函数中,插件被分为如下几个类型:
opt_early_plugin_load_listmysql_mandatory_pluginsmysql_optional_pluginsopt_plugin_load_list不同的类型,其加载顺序也不一样。
opt_early_plugin_load_list
表示必须预先加载的插件列表,这些插件由参数 --early-plugin-load指定,表示在内建插件加载之前,以及存储引擎初始化之前,需要加载的插件。比如InnoDB表空间加密依赖 keyring_file 插件,那么 keyring_file 插件必需在InnoDB存储引擎初始化之前加载。
mysql_mandatory_plugins
表示必须强制加载的内建(builtin)插件列表,比如:
binlog,初始化函数:binlog_initMEMORY,初始化函数:heap_initInnoDB,初始化函数:innobase_initMRG_MYISAM,初始化函数:myisammrg_initMyISAM,初始化函数:myisam_initPERFORMANCE_SCHEMA,初始化函数:pfs_init_funcCSV,初始化函数:tina_init_funcmysql_optional_plugins
表示可选的内建插件列表,比如:
ARCHIVE,初始化函数:archive_db_initpartition,初始化函数:partition_initializeFEDERATED,初始化函数:federated_db_initBLACKHOLE,初始化函数:blackhole_initopt_plugin_load_list
表示动态加载的插件列表,主要是my.cnf里配置的参数plugin-load,就属于这种类型,动态加载,比如下面这个示例:
[mysqld]
plugin-load="audit_log=audit_log.so"
如何确定插件入口函数
动态加载的插件,需要知道插件的动态库文件,比如audit_log.so,然后通过dlopen、dlsym打开动态链接库文件,获取插件入口地址,也就是初始化函数。而对于内建的插件,插件相关的代码已经编译到mysqld中,插件的初始化函数在编译时期就已经确定。
不管是内建插件还是动态加载的插件,都需要知道插件的入口函数,通过调用插件的入口函数,完成插件的初始化。