- MySQL的存储引擎是以插件形式工作的,这应该是MySQL的一大特色了吧!根据《深入理解MySQL》的内容,5.1版本时存储引擎的插件化都还不是彻底,确切的说是刚添加的特性。为MySQL添加一个存储引擎时,需要更改一些上层代码,零散的更改本来就有点麻烦,同时工程也要重新编译一次。我听别人说,已经可以不改C/C++代码就直接添加引擎了。这样的话,折腾存储引擎的话就更方便了!
- 这段代码来自ha_innodb.cc,这是MySQL中申明存储引擎插件的标准过程。这段代码利用了宏。在plugin.h中有比较完整的定义。
mysql_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, &innobase_storage_engine, innobase_hton_name, plugin_author, "Supports transactions, row-level locking, and foreign keys", PLUGIN_LICENSE_GPL, innobase_init, /* Plugin Init */ NULL, /* Plugin Deinit */ INNODB_VERSION_SHORT, innodb_status_variables_export,/* status variables */ innobase_system_variables, /* system variables */ NULL, /* reserved */ 0, /* flags */ }, i_s_innodb_trx, i_s_innodb_locks, i_s_innodb_lock_waits, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, i_s_innodb_cmpmem_reset mysql_declare_plugin_end;
- 我以前看了一本《MySQL技术内幕:innodb存储引擎》,个人感觉这本书虽然名字像是讲底层的,其实还是面向运维的。书中基本上没有剖析代码,都是用是文字和例子来讲解。我简略地看了一遍,大概懂了一点东西,但是明显觉得不够爽。因为心中很多的疑惑没法解释。《深入理解MySQL》里面的demo存储引擎倒是有比较详细的解释,但是感觉和innodb这样的“高大上”还是没法比的。没办法了,只能硬着头皮上代码了!我是带着问题来看代码的,写的东西肯定不是系统的。
- 我心中最大的疑惑是,innodb为什么可以是多线程的?《深入》中的引擎、csv什么的都根本看不到了多线程的影子。在插件式的架构中,innodb其实就是一个动态库。这个动态库内部实现了多线程架构,总觉的不太踏实。如果这动态库被别的MySQL实例加载了,到底会不会有问题?(当然这个问题感觉我短时间回答不了)。
- 回到正题,这个innodb的存储插件声明中有一个innobase_init字段。- innobase_init是一个函数,它被赋值给谁了呢?看plugin.h中的代码片段。
struct st_mysql_plugin { int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */ void *info; /* pointer to type-specific plugin descriptor */ const char *name; /* plugin name */ const char *author; /* plugin author (for I_S.PLUGINS) */ const char *descr; /* general descriptive text (for I_S.PLUGINS) */ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ int (*init)(void *); /* the function to invoke when plugin is loaded */ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for I_S.PLUGINS) */ struct st_mysql_show_var *status_vars; struct st_mysql_sys_var **system_vars; void * __reserved1; /* reserved for dependency checking */ unsigned long flags; /* flags for plugin */ };
- 就是这个init函数指针,当插件别加载的时候,就会调用这innobase_init()函数。innobase_init()函数会调用innobase_start_or_create_for_mysql()函数。我们可以仔细看看这个函数,多线程的玄机都在这个函数中。我把新建线程的代码摘取了出来。
for (i = 0; i < srv_n_file_io_threads; i++) { n[i] = i; os_thread_create(io_handler_thread, n + i, thread_ids + i); } /***** *****/ /* Create the thread which watches the timeouts for lock waits */ os_thread_create(&srv_lock_timeout_thread, NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); /* Create the thread which warns of long semaphore waits */ os_thread_create(&srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); /* Create the thread which prints InnoDB monitor info */ os_thread_create(&srv_monitor_thread, NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); /***** *****/ os_thread_create(&srv_master_thread, NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
除了上面的几个线程,还有一个可选的purge线程。一般情况下,innodb存储引擎会有大概八个线程。这个结论和《MySQL技术内幕》的还是很接近的,我们看的innodb版本应该不一样。这大概就是innodb引擎多线程架构的初始化过程,进一步研究innodb的架构就应该去看各个线程的工作函数,以及它们之间的同步及通信机制了。
至于我那个“动态库被别的MySQL实例加载的问题”。我觉得在这个情形下,动态库的机制并不是为了代码重复利用,而是基于模块化的软件设计思想。这里的引擎不应该被别的MySQL实例加载。
发表评论