Chinaunix首页 | 论坛 | 博客
  • 博客访问: 100997105
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Mysql/postgreSQL

2008-05-11 22:22:03

16.1. 前言

对于MySQL 5.1MySQL AB公司引入了插件式存储引擎体系结构,这样,就能创建新的存储引擎,并将它们添加到正在运行的MySQL服务器上,而不必重新编译服务器本身。

该体系结构简化了新存储引擎的开发和部署。

本章的意图是作为指南,用于帮助你为新的插件式存储引擎体系结构开发存储引擎。

关于MySQL插件式存储引擎体系结构的更多信息,请参见第14章:插件式存储引擎体系结构

16.2. 概述

MySQL服务器采用了模块化风格。

图16.1:MySQL体系结构

MySQL architecture
存储引擎负责管理数据存储,以及MySQL的索引管理。通过定义的APIMySQL服务器能够与存储引擎进行通信。

每个存储引擎均是1个继承类,每个类实例作为处理程序而被引用。

针对需要与特殊表一起工作的每个线程,处理程序是在1个处理程序的基础上实例化的。例如,如果3个连接全都在相同的表上工作,需要创建3个处理程序实例。

一旦创建了处理程序实例,MySQL服务器将向处理程序发送命令,以便执行数据存储和检索任务,如打开表、操纵行和管理索引等。

能够以累进方式创建定制存储引擎:开发人员能够以只读存储引擎启动,随后添加对INSERTUPDATEDELETE操作的支持,甚至能够增加对索引功能、事务和其他高级操作的支持。

16.3. 创建存储引擎源文件

实施新存储引擎的最简单方法是,通过拷贝和更改EXAMPLE存储引擎开始。在MySQL 5.1源码树的sql/examples/目录下可找到文件ha_example.ccha_example.h。关于如何获得5.1源码树的说明,请参见2.8.3节,“从开发源码树安装”

复制文件时,将名称从ha_example.ccha_example.h更改为与存储引擎相适应的名称,如ha_foo.ccha_foo.h

拷贝并重命名了这些文件后,必须更换所有的EXAMPLE示例,以及具有存储引擎名称的示例。如果你熟悉sed,也能自动完成这些步骤:

sed s/EXAMPLE/FOO/g ha_example.h | sed s/example/foo/g ha_foo.h
sed s/EXAMPLE/FOO/g ha_example.cc | sed s/example/foo/g ha_foo.cc

16.4. 创建handlerton

handlerton(“单个处理程序”的简称定义了存储引擎,并包含指向函数的函数指针,它以整体方式作用在引擎上,而函数工作在单独的处理程序实例中。在这类函数的一些示例中,包含用于处理注释和回滚的事务函数。

下面给出了一个来自EXAMPLE存储引擎的示例:

handlerton example_hton= {
  "EXAMPLE",
  SHOW_OPTION_YES,
  "Example storage engine", 
  DB_TYPE_EXAMPLE_DB,
  NULL,    /* Initialize */
  0,       /* slot */
  0,       /* savepoint size. */
  NULL,    /* close_connection */
  NULL,    /* savepoint */
  NULL,    /* rollback to savepoint */
  NULL,    /* release savepoint */
  NULL,    /* commit */
  NULL,    /* rollback */
  NULL,    /* prepare */
  NULL,    /* recover */
  NULL,    /* commit_by_xid */
  NULL,    /* rollback_by_xid */
  NULL,    /* create_cursor_read_view */
  NULL,    /* set_cursor_read_view */
  NULL,    /* close_cursor_read_view */
  example_create_handler,    /* Create a new handler */
  NULL,    /* Drop a database */
  NULL,    /* Panic call */
  NULL,    /* Release temporary latches */
  NULL,    /* Update Statistics */
  NULL,    /* Start Consistent Snapshot */
  NULL,    /* Flush logs */
  NULL,    /* Show status */
  NULL,    /* Replication Report Sent Binlog */
  HTON_CAN_RECREATE
};

下面给出了来自handler.hhandlerton定义:

typedef struct
  {
    const char *name;
    SHOW_COMP_OPTION state;
    const char *comment;
    enum db_type db_type;
    bool (*init)();
    uint slot;
    uint savepoint_offset;
    int  (*close_connection)(THD *thd);
    int  (*savepoint_set)(THD *thd, void *sv);
    int  (*savepoint_rollback)(THD *thd, void *sv);
    int  (*savepoint_release)(THD *thd, void *sv);
    int  (*commit)(THD *thd, bool all);
    int  (*rollback)(THD *thd, bool all);
    int  (*prepare)(THD *thd, bool all);
    int  (*recover)(XID *xid_list, uint len);
    int  (*commit_by_xid)(XID *xid);
    int  (*rollback_by_xid)(XID *xid);
    void *(*create_cursor_read_view)();
    void (*set_cursor_read_view)(void *);
    void (*close_cursor_read_view)(void *);
    handler *(*create)(TABLE *table);
    void (*drop_database)(char* path);
    int (*panic)(enum ha_panic_function flag);
    int (*release_temporary_latches)(THD *thd);
    int (*update_statistics)();
    int (*start_consistent_snapshot)(THD *thd);
    bool (*flush_logs)();
    bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
    int (*repl_report_sent_binlog)(THD *thd, char *log_file_name, my_off_t end_offset);
    uint32 flags;                                
  } handlerton;  

共有30handlerton元素,但只有少量元素是强制性的(明确地讲是前4个元素和第21个元素)。

1.    存储引擎的名称。这是创建表时将使用的名称(CREATE TABLE ... ENGINE = FOO;)。

2.    确定使用SHOW STORAGE ENGINES命令时是否列出存储引擎。

3.    存储引擎注释,对使用SHOW STORAGE ENGINES命令时显示的存储引擎的描述。

4.    MySQL服务器内唯一识别存储引擎的整数。内置存储引擎使用的常数定义在handler.h文件中。作为创建常数的可选方法,可使用大于25的整数。

5.    指向存储引擎初始化程序的指针。仅当启动服务器时才调用该函数,以便在实例化处理程序之前,存储引擎类能执行必要的内务操作。

6.    插槽。保存每连接的信息时,每个存储引擎在thd中有自己的内存区域(实际上为指针)。它是作为thd->ha_data[foo_hton.slot]访问的。插槽编号在调用foo_init()MySQL初始化。

7.    保存点偏移。为了保存每个savepoint数据,为存储引擎提供了请求的大小(典型情况下为0)。

必须以静态方式初始化savepoint偏移,使其具有所有的内存大小,以便保存每个savepoint的信息。在foo_init之后,它被更改为savepoint存储区域的偏移,存储引擎不需要使用它。

8.    由事务性存储引擎使用,清理其存储段内分配的内存,和/或回滚任何未完成的事务。

9.    由事务性存储引擎选择性使用,创建savepoint(保存点),并将其保存到提供的内存中。

10.指向处理程序rollback_to_savepoint()函数的函数指针。它用于在事务期间返回savepoint。仅对支持保存点的存储引擎才会填充它。

11.指向处理程序release_savepoint()函数的函数指针。它用于在事务期间释放保存点的资源。仅对支持保存点的存储引擎才会填充它。

12.指向处理程序commit()函数的函数指针。它用于提交事务。仅对支持事务的存储引擎才会填充它。

13.指向处理程序rollback()函数的函数指针。它用于回滚交易。仅对支持事务的存储引擎才会填充它。

14.XA事务性存储引擎所需。为提交操作准备事务。将XID与事务关联起来。

15.XA事务性存储引擎所需。恢复由XID标识的事务。

16.XA事务性存储引擎所需。提交由XID标识的事务。

17.XA事务性存储引擎所需。回滚由XID标识的事务。

18.与服务器端光标一起使用,尚未实施。

19.与服务器端光标一起使用,尚未实施。

20.与服务器端光标一起使用,尚未实施。

21.MANDATORY:构造并返回处理程序实例。

22.撤销方案时,如果存储引擎需要执行特殊步骤时使用(如在使用表空间的存储引擎中使用)。

23.清理在服务器关闭和崩溃时调用的函数。

24.InnoDB特殊函数。

25.在启动SHOW STATUS时调用InnoDB特殊函数

26.调用InnoDB特殊函数以开始连续读取。

27.调用它,指明应将日志刷新为可靠的存储。

28.在存储引擎上提供可被人员读取的状态信息。

29.InnoDB特殊函数用于复制。

30.Handlerton标志,通常与ALTER TABLE相关。可能的值定义于sql/handler.h文件中,并在此列出;

31.       #define HTON_NO_FLAGS                 0
32.       #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0)
33.       #define HTON_ALTER_NOT_SUPPORTED     (1 << 1)
34.       #define HTON_CAN_RECREATE            (1 << 2)
35.       #define HTON_FLUSH_AFTER_RENAME      (1 << 3)
36.       #define HTON_NOT_USER_SELECTABLE     (1 << 4)

HTON_ALTER_NOT_SUPPORTEDFEDERATED存储引擎使用,用以指明存储引擎不接受AFTER TABLE语句。

HTON_FLUSH_AFTER_RENAME指明,重命名表后 ,必须调用FLUSH LOGS

HTON_NOT_USER_SELECTABLE指明存储引擎不能由用户选择,而是用作系统存储引擎,如用于二进制日志的伪存储引擎。

16.5. 对处理程序进行实例化处理

调用存储引擎的第1个方法是调用新的处理程序实例。

在存储引擎源文件中定义handlerton之前,必须定义用于函数实例化的函数题头。下面给出了1个来自CSV引擎的示例:

static handler* tina_create_handler(TABLE *table);

正如你所见到的那样,函数接受指向处理程序准备管理的表的指针,并返回处理程序对象。

定义了函数题头后,用第21handlerton元素中的函数指针命名函数,指明函数负责生成新的处理程序实例。

下面给出了MyISAM存储引擎的实例化函数示例:

static handler *myisam_create_handler(TABLE *table)
  {
    return new ha_myisam(table);
  }

该调用随后与存储引擎的构造程序一起工作。下面给出了来自FEDERATED存储引擎的1个示例:

ha_federated::ha_federated(TABLE *table_arg)
  :handler(&federated_hton, table_arg),
  mysql(0), stored_result(0), scan_flag(0),
  ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
  {}

下面给出了来自EXAMPLE存储引擎的另一个示例:

ha_example::ha_example(TABLE *table_arg)
  :handler(&example_hton, table_arg)
  {}  

FEDERATED示例中的附加元素是处理程序的额外初始化要素。所要求的最低实施是EXAMPLE示例中显示的handler()初始化。

16.6. 定义表扩展

就给定的表、数据和索引,要求存储引擎为MySQL服务器提供存储引擎所使用的扩展列表。

扩展应采用以Null终结的字符串数组形式。下面给出了CSV引擎使用的数组:

static const char *ha_tina_exts[] = {
  ".CSV",
  NullS
};

调用bas_ext()函数时返回该数组。

const char **ha_tina::bas_ext() const
{
  return ha_tina_exts;
}

通过提供扩展信息,你还能忽略DROP TABLE功能的实施,这是因为,通过关闭表并用你指定的扩展删除所有文件,MySQL服务器能实现该功能。

16.7. 创建表

一旦实例化了处理程序,所需的第1个操作很可能是创建表。

你的存储引擎必须实现create()虚拟函数:

virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;

该函数应创建所有必须的文件,然后关闭表。MySQL服务器将调用随后需打开的表。

*name参数是表的名称。*form参数是st_table结构,该结构定义了表并与MySQL服务器已创建的tablename.frm文件的内容匹配。在大多数情况下,存储引擎不需要更改tablename.frm文件,也没有支持该操作的预置功能。

*info参数是包含CREATE TABLE语句用于创建表所需信息的结构。该结构定义于handler.h文件中,并为了便于参考列于下面:

typedef struct st_ha_create_information
  {
    CHARSET_INFO *table_charset, *default_table_charset;
    LEX_STRING connect_string;
    const char *comment,*password;
    const char *data_file_name, *index_file_name;
    const char *alias;
    ulonglong max_rows,min_rows;
    ulonglong auto_increment_value;
    ulong table_options;
    ulong avg_row_length;
    ulong raid_chunksize;
    ulong used_fields;
    SQL_LIST merge_list;
    enum db_type db_type;
    enum row_type row_type;
    uint null_bits;                       /* NULL bits at start of record */
    uint options;                                               /* OR of HA_CREATE_ options */
    uint raid_type,raid_chunks;
    uint merge_insert_method;
    uint extra_size;                      /* length of extra data segment */
    bool table_existed;                                     /* 1 in create if table existed */
    bool frm_only;                        /* 1 if no ha_create_table() */
    bool varchar;                         /* 1 if table has a VARCHAR */
  } HA_CREATE_INFO;

基本的存储引擎能忽略*form*info的内容,这是因为,真正所需的是创建存储引擎所使用的数据文件,以及对数据文件的可能初始化操作(假定存储文件是基于文件的)。

下面给出了来自CSV存储引擎的实施示例:

int ha_tina::create(const char *name, TABLE *table_arg,
  HA_CREATE_INFO *create_info)
  {
    char name_buff[FN_REFLEN];
    File create_file;
    DBUG_ENTER("ha_tina::create");
  
    if ((create_file= my_create(fn_format(name_buff, name, "", ".CSV",
          MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
          O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
    DBUG_RETURN(-1);
  
    my_close(create_file,MYF(0));
 
    DBUG_RETURN(0);
  }

在前面的例子中,CSV引擎未引用*table_arg*create_info参数,而是简单地创建了所需的数据文件,关闭它们,并返回。

my_createmy_close函数是定义于src/include/my_sys.h文件中的助手函数。

阅读(575) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~