前两节介绍分析了,Engine初始化以及与Server的交互操作。leveldb是Google
出品的KV存储,关于它的介绍这里不做说明。本节将介绍如何将leveldb作为一
个存储引擎插件,集成MySQL。为了简单,这里直接将leveldb作为内置存储引擎,
并且这里只实现Create Table语句功能,后续补上。
handler是与Server交换的抽象接口,对于其中的抽象函数必须实现。这里只实现
了其中create和table_flags函数,如下:
ulonglong lvHandler::table_flags() const
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_BINLOG_ROW_CAPABLE |
HA_BINLOG_STMT_CAPABLE | HA_REQUIRE_PRIMARY_KEY |
HA_AUTO_PART_KEY);
}
/* 标识引擎能够支持的功能
* 由于leveldb属于kV存储,Key作为primary key并且是必须的
*/
int lvHandler::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
{
DBUG_ENTER("lvHandler::create");
if (form->s->keys != 1)
{
my_error(HA_ERR_UNSUPPORTED, MYF(0), "support one index");
DBUG_RETURN(HA_ERR_UNSUPPORTED);
}
if (form->s->uniques != 0 )
{
my_error(HA_ERR_UNSUPPORTED, MYF(0), "no unique");
DBUG_RETURN(HA_ERR_UNSUPPORTED);
}
leveldb::DB *db;
leveldb::Options options;
options.create_if_missing = true;
options.error_if_exists = true;
leveldb::Status status = leveldb::DB::Open(options, form->s->path.str, &db);
if (!status.ok())
{
my_error(HA_ERR_INITIALIZATION, MYF(0), status.ToString().c_str());
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
delete db;
DBUG_RETURN(0);
}
/* Create Table的核心操作,其实这里也比较简单
* 约束表必须只能存在一个Key并且只能是primary key
* 约束表不可以有索引
* 对于其他抽象函数,只是简单实现
*/
在第一节中介绍过引擎初始化流程,handlerton是engine与server交换的入口。
首先利用宏根据其名称构建插件数组,代码如下:
struct st_mysql_storage_engine lv_storage_engine =
{MYSQL_HANDLERTON_INTERFACE_VERSION};
mysql_declare_plugin(leveldb)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&lv_storage_engine, "LEVELDB",
"leveldb author",
"leveldb storage engine",
PLUGIN_LICENSE_GPL,
lv_init_func, /* Plugin Init */
lv_done_func, /* Plugin Deinit */ 0x0100 /* 1.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL, /* config options */
0, /* flags */
} mysql_declare_plugin_end;
/* 功能初步实现,以简单为主,以leveldb作为存储引擎名称
* 只实现了handlerton初始化与结束清理两个函数
*/
static int lv_init_func(void *p)
{
handlerton *tina_hton;
tina_hton = (handlerton *)p;
tina_hton->state = SHOW_OPTION_YES;
tina_hton->db_type = DB_TYPE_HASH;
tina_hton->create = lv_create_handler;
tina_hton->flags = (HTON_CAN_RECREATE | HTON_NO_PARTITION);
return 0;
}
/* handlerton初始化操作只实现了基础的create函数
* 后续文章中逐步添加功能
*/
static int lv_done_func(void *p)
{
handlerton *tina_hton;
tina_hton = (handlerton *)p;
return 0;
}
/* 省略后续添加 */
static handler *lv_create_handler(handlerton *hton,
TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) lvHandler(hton, table);
}
/* 核心构造lvHandler对象 */
核心的两个对象以实现,这里只需完成CMakeList.txt文件的编写即可,如下所示:
SET(LEVELDB_PLUGIN_STATIC "leveldb")
SET(LEVELDB_PLUGIN_MANDATORY TRUE)
SET(LEVELDB_INCLUDE "/data/leveldb/include")
SET(LEVELDB_PATH "/data/leveldb/lib64/libleveldb.a")
SET(LEVELDB_SOURCES
lv_handler.cc
lv_handler.h
lv_handlerton.cc
lv_row.cc
lv_comparator.h)
INCLUDE_DIRECTORIES(${LEVELDB_INCLUDE})
ADD_COMPILE_FLAGS(${LEVELDB_SOURCES} COMPILE_FLAGS "--std=c++11")
MYSQL_ADD_PLUGIN(leveldb ${LEVELDB_SOURCES}
STORAGE_ENGINE
MANDATORY
RECOMPILE_FOR_EMBEDDED
LINK_LIBRARIES
${LEVELDB_PATH})
完成后,需重新编译安装MySQL这里是以MySQL5.7源码进行的测试。
create table leveldb_tst(
lkey int primary key,
name varchar(20),
address varchar(100)
) engine = leveldb;
这里显示了Create Table的执行结果以及leveldb初始化的文件。
show create table语句中engine显示默认,细节有些问题,后续再纠正。
show table status显示的表engine字段正确。
通过两个简单的例子,以验证本节的功能,将leveldb集成至MySQL并实现创建表操作。
细看就很简单,这里也是MySQL分层架构的优势,可以方便集成存储引擎。
后续逐步添加功能,下节将实现数据插入功能。