MySQL中ext的使用方法介绍(mysql中ext)
MySQL中ext的使用方法介绍
在MySQL中,ext是指扩展存储引擎。MySQL提供了多个内置的存储引擎,如MyISAM和InnoDB,但是有时候这些内置的存储引擎不能满足特殊的需求。这时就需要通过MySQL的扩展存储引擎来实现。本文将介绍MySQL中ext的使用方法。
一、ext的安装
MySQL扩展存储引擎需要用到C/C++编译器和MySQL头文件。在安装MySQL后,可以使用以下命令安装扩展存储引擎:
sudo apt-get install libmysqlclient-dev
sudo apt-get install libmysqld-dev
安装完成后,需要重新编译MySQL:
sudo cmake -DWITH_EXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8mb4 .
sudo makesudo make install
二、ext的使用
在MySQL中使用ext,需要先创建扩展存储引擎。创建扩展存储引擎需要创建以下文件:
– ha_foo.cc:代码文件,实现存储引擎的核心逻辑。
– config.h:配置文件,定义需要使用哪些MySQL头文件和C++库。
– CMakeLists.txt:编译文件,用于编译生成扩展存储引擎的二进制文件。
下面我们以创建一个名为foo的扩展存储引擎为例,介绍具体步骤。
1. 创建ha_foo.cc文件,实现存储引擎的核心逻辑。
“`c++
#include “mysql/plugin.h”
#include “ha_foo.h”
static handler* foo_create_handler(handlerton*hton, TABLE_SHARE*table, MEM_ROOT*mem_root) {
return new (mem_root) ha_foo(hton, table);
}
ha_foo::ha_foo(handlerton*hton, TABLE_SHARE*table) : handler(hton, table) {
// 构造函数,可以初始化一些参数
}
ha_foo::~ha_foo() {
// 析构函数,需要释放资源
}
int ha_foo::open(const char*name, int mode, uint test_if_locked) {
// 打开表
}
int ha_foo::close(void) {
// 关闭表
}
int ha_foo::write_row(uchar*buf) {
// 写入行
}
int ha_foo::update_row(const uchar*old_data, uchar*new_data) {
// 更新行
}
int ha_foo::delete_row(const uchar*buf) {
// 删除行
}
int ha_foo::index_read_map(uchar*buf, const uchar*key, key_part_map keypart_map,
enum ha_rkey_function find_flag) {
// 索引读取行
}
…
/*
* 定义存储引擎的信息
*/
static struct st_mysql_storage_engine foo_storage_engine = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
“foo”, /* 插件名称 */
NULL, /* 插件属性 */
foo_create_handler, /* handler创建函数 */
NULL, /* 插件初始化函数 */
NULL, /* 插件退出函数 */
NULL, /* 插件状态函数 */
NULL, /* 插件信息函数 */
1, /* 插件 API 版本号 */
STANDARD_MYSQL_EXTENSION_LAYER_BASE, /* 插件基础层次 */
0 /* 插件当前层次 */
};
/*
* 注册存储引擎
*/
mysql_declare_plugin(foo)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&foo_storage_engine,
“foo storage engine plugin”,
“GPL”,
NULL,
NULL,
NULL,
NULL,
NULL
}
mysql_declare_plugin_end;
2. 创建config.h文件,定义需要使用哪些MySQL头文件和C++库。
```c++#ifndef __FOO_CONFIG_H__
#define __FOO_CONFIG_H__
/* MySQL头文件 */#include
#include
#include
#include
#endif /* __FOO_CONFIG_H__ */
3. 创建CMakeLists.txt文件,用于编译生成扩展存储引擎的二进制文件。
“`cmake
project(foo)
include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/include)
set(PLUGIN_FOO_SRC ha_foo.cc)
add_library(foo MODULE ${PLUGIN_FOO_SRC})
target_link_libraries(foo mysqlclient)
set_target_properties(foo PROPERTIES PREFIX “”)
set_target_properties(foo PROPERTIES OUTPUT_NAME “foo”)
4. 编译扩展存储引擎。
执行以下命令:
cmake ../
make
make install
5. 在MySQL中加载扩展存储引擎。
在MySQL的配置文件中添加以下内容:
[mysqld]
…
plugin_dir=/usr/local/mysql/lib/plugin
…
将上面创建的扩展存储引擎文件复制到/usr/local/mysql/lib/plugin目录下。然后在MySQL中执行以下命令来加载扩展存储引擎:
```sqlCREATE TABLE t1 (id INT, name VARCHAR(100)) ENGINE=foo;
在以上命令中,ENGINE=foo指定使用扩展存储引擎foo来创建表t1。
三、ext的示例
以下为一个示例程序,实现了一个简单的存储引擎,可以写入、更新、删除、读取和扫描数据:
“`c++
#include “mysql/plugin.h”
#include “ha_foo.h”
static handler* foo_create_handler(handlerton*hton, TABLE_SHARE*table, MEM_ROOT*mem_root) {
return new (mem_root) ha_foo(hton, table);
}
ha_foo::ha_foo(handlerton*hton, TABLE_SHARE*table) : handler(hton, table) {
row_size = 7;
}
ha_foo::~ha_foo() {
}
int ha_foo::open(const char*name, int mode, uint test_if_locked) {
return 0;
}
int ha_foo::close(void) {
return 0;
}
int ha_foo::write_row(uchar*buf) {
uint32_t id = uint4korr(buf);
uint16_t len = uint2korr(buf + 4);
char*name = (char*)(buf + 6);
std::cout<"write_row: id="<<id<<" name="<<name<<std::endl;
data[id] = std::string(name, len);
return 0;
}
int ha_foo::update_row(const uchar*old_data, uchar*new_data) {
uint32_t id = uint4korr(old_data);
uint32_t old_len = uint2korr(old_data + 4);
char*old_name = (char*)(old_data + 6);
uint32_t new_len = uint2korr(new_data + 4);
char*new_name = (char*)(new_data + 6);
std::cout<<" update_row:="" id="<<id<<" old_name="<<old_name<<" new_name="<<new_name<<std::endl;
if (data.find(id) == data.end()) {
return HA_ERROR_RECORD_NOT_FOUND;
}
data[id] = std::string(new_name, new_len);
return 0;
}
int ha_foo::delete_row(const uchar*buf) {
uint32_t id = uint4korr(buf);
std::cout<<" delete_row:="" id="<<id<<std::endl;
if (data.find(id) == data.end()) {
return HA_ERROR_RECORD_NOT_FOUND;
}
data.erase(id);
return 0;
}
int ha_foo::index_read_map(uchar*buf, const uchar*key, key_part_map keypart_map,
enum ha_rkey_function find_flag) {
uint32_t id = uint4korr(key);
std::cout<<" index_read_map:="" id="<<id<<std::endl;
auto it = data.find(id);
if (it == data.end()) {
return HA_ERR_END_OF_FILE;
}
uint16_t len = it->second.length();
memcpy(buf, key, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
int ha_foo::index_read(uchar*buf, const uchar*key, uint key_len, enum ha_rkey_function find_flag) {
uint32_t id = uint4korr(key);
std::cout<<" index_read:="" id="<<id<<std::endl;
auto it = data.find(id);
if (it == data.end()) {
return HA_ERR_END_OF_FILE;
}
uint16_t len = it->second.length();
memcpy(buf, key, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
int ha_foo::index_first(uchar*buf, enum ha_rkey_function find_flag) {
if (data.empty()) {
return HA_ERR_END_OF_FILE;
}
auto it = data.begin();
uint16_t len = it->second.length();
memcpy(buf, &it->first, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
int ha_foo::index_next(uchar*buf, enum ha_rkey_function find_flag) {
uint32_t id = uint4korr(buf);
std::cout<<" index_next:="" id="<<id<<std::endl;
auto it = data.find(id);
if (it == data.end()) {
return HA_ERR_END_OF_FILE;
}
++it;
if (it == data.end()) {
return HA_ERR_END_OF_FILE;
}
uint16_t len = it->second.length();
memcpy(buf, &it->first, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
int ha_foo::index_prev(uchar*buf, enum ha_rkey_function find_flag) {
uint32_t id = uint4korr(buf);
std::cout<<" index_prev:="" id="<<id<<std::endl;
auto it = data.find(id);
if (it == data.end()) {
return HA_ERR_END_OF_FILE;
}
if (it == data.begin()) {
return HA_ERR_END_OF_FILE;
}
–it;
uint16_t len = it->second.length();
memcpy(buf, &it->first, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
int ha_foo::index_last(uchar*buf, enum ha_rkey_function find_flag) {
if (data.empty()) {
return HA_ERR_END_OF_FILE;
}
auto it = data.end();
–it;
uint16_t len = it->second.length();
memcpy(buf, &it->first, 4);
memcpy(buf + 4, &len, 2);
memcpy(buf + 6, it->second.c_str(), len);
return 0;
}
const char* ha_foo::table_type() const {
return “>
}
/*
* 定义存储引擎的信息
*/
static struct st_mysql_storage_engine foo_storage_engine = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
“foo”, /* 插件名称 */
NULL, /* 插件属性 */
foo_create_handler, /* handler创建函数 */
NULL, /* 插件初始化函数 */
NULL, /* 插件退出函数 */
NULL, /* 插件状态函数 */
NULL, /* 插件信息函数 */
1, /* 插件 API 版本号 */
STANDARD_MYSQL_EXTENSION_LAYER_BASE, /* 插件基础层次 */
0 /* 插件当前层次 */
};
/*
* 注册存储引擎
*/
mysql_declare_plugin(foo)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&foo_storage_engine,
“foo storage engine plugin”,
“GPL”,
NULL,
NULL,
NULL,
NULL,
NULL
}
mysql_declare_plugin_end;
执行以下命令编译扩展存储引擎:
mkdir -p build
cd build
cmake ../
make
然后将生成的文件复制到/usr/local/mysql/lib/plugin目录下。在MySQL中执行以下命令来加载扩展存储引擎:
```sqlCREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(100)) ENGINE=foo;
INSERT INTO t1 VALUES (1, "foo"), (2, "bar"), (3, "baz");
SELECT * FROM t1 WHERE id = 2;
UPDATE t1 SET name = "bbb" WHERE id = 2;
SELECT * FROM t1;
DELETE FROM t1 WHERE id = 1;
SELECT * FROM t1;
SELECT * FROM t1 WHERE id > 1;
以上命令创建表t1,插入数据,并执行了一些操作。每个操作都会在控制台输出一些信息,以便查看扩展存储引擎的运行情况。