mysql 写一个存储引擎_【译】从草稿开始写一个 MySQL 存储引擎(一)-Go语言中文社区...

本文主要描述了如何写一个MySQL 存储引擎 - 一个可以持久保存 MySQL 表数据的插件

简介

这篇文章总结了我在写一个新的 MySQL 存储引擎时学到的一些事情。MySQL 的存储引擎是一个能够提供 在磁盘中存储数据,并且能够提供对数据的链接的插件。存储引擎通常被作为 key/value 数据库实现,但是并不一定是这样。Oracle 的 MySQL 提供了多种存储引擎,并且所有的存储引擎都能够被重新编写。默认的存储引擎是 InnoDB,一种 key/value 库。其他的存储引擎有的能够写入 csv 文件(‘Tina’)或者专门用来归档数据('archive').Maria DB,作为一个分支,是一个更加先进并且提供了 Cassandra NoSQL 数据库接口的存储引擎,Percona 的 TokuDB key/value 库 和 xtradb,则是 InnoDB 的改进版本。

总的来说,MySQL 有13种存储引擎,MariaDB 有大约20 种。但是这些仍然不够,让我们再来添加一种。

下载源码以及第一次接触

你能够在 GitHub 上面下载 MySQL 的源码,我的工作版本是 5.7.12。

cd mysql-server

git checkout mysql-5.7-12

让我们简单看一下代码的整体结构。文件和目录的数量有点多,但是大部分和我们的工作无关,只有少部分的目录值得我们仔细查看:

include 包含全局 include 文件,你能在里面找到 mysql.h,其中包含了很多重要的宏和声明。

sql 保护了 sql 相关的代码:解析器,查询引擎等。

sql/field.h Field class 描述了一个 MySQL 行。

sql/item.h Item class 是一个解析器生成的抽象语法树的节点。

sql/sql_*.cc 这些文件实现了实际上的 SQL 操作。

sql/handler.h 存储引擎的基类

storage 这个目录包含了所有的存储引擎。

storage/innobase InnoDB 存储引擎

storage/example 一个存储引擎实例项目。

通过浏览这些代码,我们可以清晰地看出 mysql 代码的基础是相对较老的。虽然大部分的代码是通过 C++ 实现的,但是实际上仅仅是 “c 和 类”的实现方式。更多的高级 c++ 特性,例如 模板,exceptions 或者标准库都没有被使用。连接列表被实现成包裹在 "void *" 中的结构体对象(my_list.h)。mysql 还有它自己的 string 实现(string.c) 而不是使用 std::string。RAII 也没有被使用。更甚的是,你能够找到很多用于清理内存分配资源的 goto 语句。

功能的实现会非常的长(超过 1000 行代码,并且包含了多层的 if 语句 mysql_prepare_create_table),并且有一些类也非常的大。很多方法被存储在基类中而不是继承类,并且类中存储了很多的状态。

MySQL 用了几种内存自动分配(memroot_allocator.h),它们不是标准的实现。很多类使用自己的内存分配来重写了操作符 new 和 delete。

同时MySQL 的代码没有统一的编码风格。首行缩进都有多种风格,结构体的命名风格也有多种方式(。。。),空格的使用也非常随意(。。。)。

我没有和 Oracle 或者 Mysql AB 工作的人讨论过,但是我们可以基于这些代码看出他们的合作风格。缺乏同一的代码风格意味着每一位工程师都能选择他最熟悉的方式。代码风格有很大的差异,甚至在同一个文件中,每个人也可以对任意部分的代码进行修改。我曾经在做过类似的工作,所以我明白这其中有非常多的工作需要做。

如果 MySQL希望吸引新的开发者,“c 加 类”的使用,不使用标准库并且非常长且复杂的功能实现都是需要重构的。

编译,安装,运行,debug

让我们继续安装。如果你运行了之前的步骤,那么接下来你需要检查 mysql-server 目录中的代码。我们将在这个目录中运行 cmake 来生成 Makefile。我们同时将会创建一个 Debug build,虽然它会有一点慢,但是在 debug 的过程中我们会用到它。

cd mysql-server

cmake -DCMAKE_BUILD_TYPE=Debug

make -j 5

sudo make install

你的编译文件现在安装在了 /usr/local/mysql 中。你能通过在子目录中运行 cmake 来生成独立的 Debug 和 Release builds,并且你能够选择不同的安装目录,运行 “cmake --help”来获得选项的列表。在这个文章中我仅仅会保持所有事情尽可能简单。

为了成功启动 MySQL 客户端,我们还需要做以下事情。我们需要创建一个数据目录(用来存放 表)并且初始化它们(注意你可能需要改变下面代码的文件路径):

mkdir /home/alan/tmp/mysql-data # must be empty

cd /usr/local/mysql/bin

./mysqld --initialize --datadir=/home/alan/tmp/mysql-data

最后一个命令将会生成一个 root 密码。记下它,接下来会用到。我将我的开发环境设置为空的 root 密码 - 在测试时它将会更加安全。你可以使用接下来的命令重新设置密码(用上面生成的 root 密码来替换 ):

-- start the server

./mysqld --datadir=/home/alan/tmp/mysql-data

-- in a separate terminal we can now change the password

./mysqladmin password --user=root --password=

然后我们可以创建一个新的数据库:

./mysqladmin create test --user=root --password

客户端能够被正常启动,并且之后你将可以创建表,插入数据等等。

./mysql --user=root test

逐步构建一个新的存储引擎

存储引擎被实现为一个动态的库(一个 .so 文件),并且他的源文件被存储在 msyql-server/storage 目录中。如果你仅仅希望玩一下那么你可以修改已有的 'example ' 存储引擎。我选择通过以下步骤创建我自己的 'upscaledb'。

cd mysql-server/storage

-- copy the 'ha_example' directory to 'ha_upscaledb'

cp -r ha_example ha_upscaledb

-- rename the files

cd ha_upscaledb

mv ha_example.h ha_upscaledb.h

mv ha_example.cc ha_upscale.cc

最有一步就是,使用你最喜欢的 IDE 来将 'example' 替换为 'upscaledb'以及 'EXAMPLE' 替换为 'UPSCALEDB'。不要忘记同样更改你的 CMakeLists.txt 。然后进入 mysql-server 的根目录并且再一次运行 'cmake' 和 ‘make’ 命令。新的 upscaledb 引擎现在构建好了,它的文件名是 mysql-server/storage/upscaledb/ha_upscaledb.so。

现在我们需要提示 MySQL 关于我们的新存储引擎。首先我们创建一个 安装目录 到新的 .so 文件的 symbolic link(软连接?)。通过这个连接我们的服务器将会总是使用最新版本的 .so 文件。不论我们何时修改了代码,我们只需要简单的重新编译存储引擎并且重启 MySQL 服务器就行了。

cd /usr/local/mysql/lib/plugin

sudo ln -s ~/prj/msyql-server/storage/upscaledb/ha_upscaledb.so ha_upscaledb.so

最后的步骤就是更新 MySQL 的内部系统表。我们能够使用 MySQL 的客户端完成这些。同时确保 MySQL 的服务器端仍在运行。

cd /usr/local/mysql/bin

./mysql --user=root test

mysql> INSTALL PLUGIN upscaledb SONAME 'ha_upscaledb.so';

现在你能够使用最新的存储引擎并且尝试构建表 (create table test(value INTEGER) ENGINE=upscaledb;)。现在我们的存储引擎只是一个框架并且没有任何的实现。我们将会得到一个报错。在我们开始增添程序逻辑之前我会教你如何 Debug MySQL 服务器。接下来的代码将会在 gdb 中启动服务器,并且将会让 gdb 获取所有的信号。(i.e. ctrl-c 可以结束 debugger)。

cd /usr/local/mysql/bin

gdb --args ./mysqld --gdb --datadir=/home/alan/tmp/mysql-data

尝试在你的存储引擎中的 'create()' 方法中设置一个断点,并且运行一次上述的 CREATE TABLE 命令。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值