两个简单的方向吧。一个是给mysql写个存储引擎,另一个是基于mysql的协议写个兼容后端实现。以下mysql一词是概称,包含mariadb,原版mysql等等各类兼容实现。
存储引擎
存储引擎的思路是一些做数据库的公司和互联网大厂里的早期思路。使用mysql的SQL引擎之类的。把结构体里实现一些必要的接口就行。可以按自己的需求来优化存储引擎的应用方向。比如可以做个一开始就做好高度索引优化的只读数据库,就不用担心索引更新之类的麻烦事了。
以下是我几年前研究MySQL存储引擎时的笔记。我并不看好这个方向,所以做完技术调研后,并未深入做实验。
是按照MySQL约定,提供某些接口实现。比如插入记录就会调用 write_row() 方法,通过索引检索时调用 index_read() 和 index_next() 方法。
MySQL与存储引擎之间的接口主要通过两个类实现 sql/handler.h 中的 handlerton 和 handler 类。前者约定事务操作接口,后者是表、索引、记录操作接口。对不支持事务的存储引擎只需要创建handler的子类,并重载方法实现即可。
实现了存储引擎后,还需要声明一下存储引擎的存在,定义一个 st_mysql_storage_engine 变量,值为 MYSQL_HANDLERTON_INTERFACE_VERSION ,如下:
struct st_mysql_storage_engine foo_storage_engine={
MYSQL_HANDLERTON_INTERFACE_VERSION
};然后调用 mysql_declare_plugin() 宏来给出存储引擎声明:
mysql_declare_plugin(foo){ /* foo为存储引擎名称 */
MYSQL_STORAGE_ENGINE_PLUGIN,
&foo_storage_engine, /* 这里即为上面定义的st_mysql_storage_engine变量 */
"FOO", /* SHOW ENGINES中显示的存储引擎名称 */
"Author Here", /* 作者名 */
"Foo storage engine", /* SHOW ENGINES中显示的存储引擎说明 */
PLUGIN_LICENSE_GPL,
init_func, /* 某函数,将在加载存储引擎时调用 */
done_func, /* 某函数,将在卸载存储引擎时调用 */
0x0001 /* 版本号0.1 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
} mysql_declare_plugin_end;这样声明后,加载存储引擎时MySQL将调用 init_func() 函数,传入handlerton变量。存储引擎至少要设置 state 、 db_type 、 create 、 flags 等属性,其中create是函数指针。若支持事务还需要设置handlerton中事务接口的实现函数。
MySQL源码里的 storage/example/ 包含一个例子,可以参考或直接修改。
兼容协议
简单的说,写一个网络协议上兼容的服务器。把用户提交的字符串(原本应该是SQL语句),做了必要处理后,返回用户以数据集或异常信息。
我知乎文章里就有多年前翻译的协议文档。
MySQL的通信协议PostgreSQL通信协议memcache通信协议我的github里也有多年前基于pgsql协议写的兼容服务器,当作RPC协议来用的。
GitHub - gashero/magicrpc: Automatically exported from code.google.com/p/magicrpc小结
总的来说,国内已经有很多公司和个人写过数据库了,难度也不高。新手用来练习一下是个有趣的例子。尤其是兼容协议的实现,当发现自己用标准的mysql客户端连接到自己的服务器,发个hello,得到个world时还是很好玩的。 |