从源码角度看MySQL memcached plugin——1. 系统结构和引擎初始化
本章尝试回答两个问题:
一、memcached plugin与MySQL的关系;
二、MySQL系统如何启动memcached plugin。
1. memcached plugin与MySQL的关系

该图是从MySQL官方文档里对memcached的介绍图片。从图中可以看出,memcached的结构是由三个部份组成:memcached plugin、innodb_memcached和Innodb API。
在源码中,memcached plugin部份的代码会被编译成libmemcached.so;innodb_memcache和InnoDB API会被编译成innodb_engine.so。
memcached plugin层通过一组回调函数调用libmemcached.so提供的接口实现为App服务。
InnoDB API层同样也是通过一组回调函数调用InnoDB层的接口实现,功能类似于图中左侧的Handler API。而innodb_memcache通过包装这组回调函数为memcached plugin提供接口实现。
2. MySQL系统如何启动memcached plugin
在MySQL中,InnoDB存储引擎和memcached都是以插件的形式实现。memcached最底层的回调函数是由InnoDB存储引擎提供,于是在插件初始化的顺序上是InnoDB插件先于memcached插件。
InnoDB存储引擎插件调用plugin_initialize函数初始化时将一组回调函数数组的地址传给全局指针变量innodb_callback_data。memcached引擎插件调用plugin_initialize函数初始化时将innodb_callback_data作为自己的参数传入。
插件初始化使用的函数plugin_initialize的函数原型是int plugin_initialize(st_plugin_int *plugin);
参数类型为st_plugin_int的结构体。MySQL使用该结构体描述一个插件。其中有两个变量,data和plugin。plugin变量存放了插件的init和deinit回调函数,这是插件初始化时真实调用的函数;data作为plugin中的回调函数的参数存在。
int plugin_initialize(st_plugin_int *plugin);
/* A handle of a plugin */
struct st_plugin_int
{
...
st_mysql_plugin *plugin;
void *data; /* plugin type specific, e.g. handlerton */
...
};
struct st_mysql_plugin
{
...
int (*init)(MYSQL_PLUGIN); /* the function to invoke when plugin is loaded */
int (*deinit)(MYSQL_PLUGIN);/* the function to invoke when plugin is unloaded */
...
};
3.1 InnoDB如何将回调函数传给全局变量innodb_callback_data
InnoDB层提供的回调函数是个数组,数组名为innodb_api_cb。
ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_cursor_open_table,
...
};

在plugin_initialize函数里,调用plugin->plugin->init函数(innobase_init函数)。如上图:
- 将innodb_api_cb数组的地址赋值到在plugin->data->data中。
- 将plugin->data->data赋值到innodb_callback_data。
到此可以看到innodb_callback_data已经指向了一个回调函数数组的地址。
3.2 memcached如何将innodb_callback_data赋值给innodb_engine.so中的回调函数
初始化memcached插件同样调用的是plugin_initialize函数,将innodb_callback_data赋值给plugin->data之后,调用plugin->plugin->init函数(daemon_memcached_plugin_init函数)。
完成了插件初始化的基本操作之后,开启一个新的线程daemon_memcached_main,这个线程是memcached插件系统的daemon线程。
void daemon_memcached_main(memcached_context_t* p);
struct memcached_context
{
char* m_engine_library;
char* m_mem_option;
void* m_innodb_api_cb;
unsigned int m_r_batch_size;
unsigned int m_w_batch_size;
bool m_enable_binlog;
};

在开启线程daemon_memcached_main之前,会将plugin->data(innodb_callback_data)赋值给p->m_innodb_api_cb。
daemon_memcached_main在进入守护状态之前,还有两个重要的操作要做,分别是load engine和init engine函数。而这两个函数分别做了什么?
- load engine: 连接libmemcached.so的回调函数与innodb_engine.so的实现。
- init engine: 连接innodb_engine.so的innodb_callback_API的回调函数与InnoDB层的实现。
3.2.1 load engine
load_engine(engine, get_server_api,settings.extensions.logger,
&engine_handle);
load_engine的函数原型如上。在这个过程中,会load两个引擎。一个innodb_engine,一个是default_engine。
过程如下:
- 调用dlopen打开innodb_engine.so。
- 调用dlsym函数获得create_instance函数的地址。
- 调用create_instance,malloc一个struct innodb_engine的结构体innodb_engine,为innodb_engine回调函数赋值。
- 调用create_instance|create_my_default_instance为默认引擎的回调函数赋值。
load engine之后,lib_memcached.so中的回调函数会被赋值,实现是在innodb_engine.so中。

InnoDB Engine与Default Engine是否启用?是否同时启用?
/** Cache options, tells if we will used Memcached default engine or InnoDB
Memcached engine to handle the request */
typedef enum meta_cache_opt {
META_CACHE_OPT_INNODB = 1, /*!< Use InnoDB Memcached Engine only */
META_CACHE_OPT_DEFAULT, /*!< Use Default Memcached Engine only */
META_CACHE_OPT_MIX, /*!< Use both, first use default memcached engine */
META_CACHE_OPT_DISABLE, /*!< This operation is disabled */
META_CACHE_NUM_OPT /*!< Number of options */
} meta_cache_opt_t;
默认的参数值为META_CACHE_OPT_INNODB,仅仅启用InnoDB Engine,数据通过InnoDB引擎提供的Callback方法操作;若同时启用了Memcached Default Engine(META_CACHE_OPT_MIX),那么数据读取时,首先从Default Engine中读取;记录删除时,也需要先删除Default Engine中的记录。
3.3.2 init engine
init engine调用的函数是
innodb_eng->engine.v1->initialize
实际上调用的是实现在在innodb_engine.so的innodb_initialize函数。

在这个innodb_initialize函数中调用register_innodb_cb函数为innodb_memcached_api数组赋值。两个数组的指针顺序要一一对应。
innnodb_memcached_api数组是innodb_engine.so中调用innodb层操作的回调函数数组。

以下这图是这个过程中innodb的函数指针一路传递到memcached的innodb_engine.so中的函数指针的过程。

从源码角度看MySQL memcached plugin——1. 系统结构和引擎初始化的更多相关文章
- 从源码角度看MySQL memcached plugin——0.大纲
本系列文章介绍MySQL memcached plugin插件.剖析已经完成.先把链接弄好,内容会陆续补上. 大纲如下: 系统结构和引擎初始化(已完成) 线程模型和连接的状态机 containers表 ...
- 从JDK源码角度看Short
概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然 ...
- 从JDK源码角度看Byte
Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型 ...
- 从JDK源码角度看Object
Java的Object是所有其他类的父类,从继承的层次来看它就是最顶层根,所以它也是唯一一个没有父类的类.它包含了对象常用的一些方法,比如getClass.hashCode.equals.clone. ...
- 从JDK源码角度看Boolean
Java的Boolean类主要作用就是对基本类型boolean进行封装,提供了一些处理boolean类型的方法,比如String类型和boolean类型的转换. 主要实现源码如下: public fi ...
- 从template到DOM(Vue.js源码角度看内部运行机制)
写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...
- Android布局性能优化—从源码角度看ViewStub延迟加载技术
在项目中,难免会遇到这种需求,在程序运行时需要动态根据条件来决定显示哪个View或某个布局,最通常的想法就是把需要动态显示的View都先写在布局中,然后把它们的可见性设为View.GONE,最后在代码 ...
- 从源码角度看JedisPoolConfig参数配置
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 你好,JedisPoolConfig Java中使用Jedis作为连接Redis的工具.在使用Jedis的也可以配置Jed ...
- 从源码角度看 PHP 字符串类型转换
PHP 的类型转换是比较方便的,但是越是容易使用的东西,底层的实现越是复杂,而且在使用中像我这样的新手也往往不清楚转换后的结果到底是什么.有时候,对于 Java 这种强类型的语言,使用的时候需要强制进 ...
随机推荐
- node-sass的安装问题
1.认识node-sass 我觉得要解决node-sass的问题,你首先至少要简单的了解node-sass是个什么东西?为什么要安装它? 对于在项目中使用sass的语法的时候,需要通过sass-loa ...
- JDK8 JVM性能优化-1
原文地址:https://blog.csdn.net/xingkongtianma01/article/details/80689928 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的 ...
- Oracle 12C R2 on Linux 7.X 单实例静默安装文档
禁用防火墙systemctl stop firewalld.servicesystemctl disable firewalld.service 禁用SELinuxcat /etc/selinux/c ...
- php date mktime 获取时间上的各种值
echo date("Ymd",strtotime("now")), "\n"; echo date("Ymd",str ...
- Tricks(四十九)—— 按 batch 访问越界的解决办法
使用 min 函数指定访问的最终位置,本质上是增加一个条件判断: done = false; batch_size = 10000; idx = 1; while ~done idx_end = mi ...
- Linux快捷键、文件管理和查询
Linux学习(1)-常用快捷键.文件管理和查询 阅读目录 有话要说 Shell应用技巧,常用快捷键 帮助命令 man (帮助命令) info (和man差不多) whatis (查询基本信息 ...
- Android中的动画详解系列【3】——自定义动画研究
在上一篇中我们使用到了位移动画TranslateAnimation,下面我们先来看看TranslateAnimation是如何实现Animation中的抽象方法的: /* * Copyright (C ...
- Android bitmap绘制文字自动换行
public Bitmap getNewBitMap(String text) { Bitmap newBitmap = Bitmap.createBitmap(,, Config.ARGB_4444 ...
- [Grid Layout] Place grid items on a grid using grid-column and grid-row
It’s possible to position a grid item anywhere on a grid track. To do this, let’s specify some grid- ...
- CentOS 7安装fcitx中文输入法
安装过程例如以下: 1.增加EPEL源 EPEL7差点儿是CentOS必备的源: sudo yum install epel-release 2.加入mosquito-myrepo源 mosquito ...