MySQL的handler接口

是比较偏的部分,可能是因为不是标准SQL,生产环境或者线上很少看到有人使用。本文以‘小白’视角,记录下如何使用HANDLER,以及相关的代码简单介绍。

本文的源码部分基于5.7.5,从5.7开始也支持对分区表的HANDLER操作了。

1.使用

具体的参考官方文档:http://dev.mysql.com/doc/refman/5.7/en/handler.html

我们以一个简单的测试表为例:

create table t1 (c1 int primary key, c2 int, c3 int, key (c2,c3));

insert into t1 values (1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7),(6,9,10),(7,8,10);

mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`c1` int(11) NOT NULL,
`c2` int(11) DEFAULT NULL,
`c3` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `c2` (`c2`,`c3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

打开表

语法:HANDLER tbl_name OPEN [ [AS] alias]

HANDLER…OPEN语句用于打开一张表,这样就可以随后通过HANDLER…READ语法来读取记录,表对象存储在session中,不与别的线程共享。

mysql> handler t1 open;
Query OK, 0 rows affected (0.00 sec)

然后就可以从表上读取数据了:

HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT … ]

HANDLER t1 READ 操作一直在session里保持读到的索引位置,READ FIRST 会重置到第一条记录,READ NEXT会依次读取下一条记录,顺序是按照指定的索引顺序,你也可以指定where条件来进行过滤,注意如果不指定LIMIT那就只会返回一条记录。

举几个例子:

mysql> handler t1 read first;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  1 |    2 |    3 |
+—-+——+——+
1 row in set (0.00 sec)mysql> handler t1 read next;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  2 |    3 |    4 |
+—-+——+——+
1 row in set (0.00 sec)

mysql> handler t1 read first where c2 > 3 limit 3;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  3 |    4 |    5 |
|  4 |    5 |    6 |
|  5 |    6 |    7 |
+—-+——+——+
3 rows in set (0.00 sec)

指定索引读数据

语法:HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT … ]

mysql> handler t1 read c2 first;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  1 |    2 |    3 |
+—-+——+——+
1 row in set (0.00 sec)mysql> handler t1 read c2 first where c2 >7;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  7 |    8 |   10 |
+—-+——+——+
1 row in set (0.00 sec)

指定二级索引数据读取条件:

语法:HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,…) [ WHERE where_condition ] [LIMIT … ]

使用主键读

mysql> handler t1 read `PRIMARY` = (3);
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  3 |    4 |    5 |
+—-+——+——+
1 row in set (0.00 sec)

mysql> handler t1 read c2 first where c2 > 7 limit 10;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  7 |    8 |   10 |
|  6 |    9 |   10 |
+—-+——+——+
2 rows in set (0.00 sec)使用二级索引读

mysql> handler t1 read c2 first where c2 =7 limit 2;
Empty set (0.00 sec)mysql> handler t1 read c2 first where c2 =8;
+—-+——+——+
| c1 | c2   | c3   |
+—-+——+——+
|  7 |    8 |   10 |
+—-+——+——+
1 row in set (0.00 sec)

如果二级索引有多个列的话,也可以指定少于列数的索引键值。

关闭HANDLER

HANDLER tbl_name CLOSE

总的来说,操作还是比较简单的,HANDLER接口提供了一种直达引擎层读取数据的方法。不过HANDLER接口只提供了读取数据的接口,并没有提供DML接口。

如果OPEN了一个表,对这张表做DDL就会被阻塞住,直到显式执行HANDLER..CLOSE掉才能执行。

另外从语法定义来看,只能返回全行,而不能选择返回特定的列值。

根据文档描述,HANDLER接口相对SQL接口,其优点在于更少的语法解析,SQL检查和优化器开销,只需要显式打开一次表;对于Innodb, HANDLER接口总是不加Innodb表锁,可以读取UNCOMMIT的数据。

2.代码实现

从上面的描述可以知道,HANDLER无非就对应三种操作:OPEN, READ, CLOSE,而在内部实现中,也对应三个类接口:

Sql_cmd_handler_open

Sql_cmd_handler_read

Sql_cmd_handler_close

相关的代码实现都集中在sql_handler.cc文件中。

我们依次展开介绍

a.打开表

主函数:Sql_cmd_handler_open::execute

在语法解析时,就实例了一个Sql_cmd_handler_open对象,执行阶段调用Sql_cmd_handler_open::execute函数

每通过HANDLER打开一张表,都存储在thd->handler_tables_hash 哈希中,键值为表名,值为TABLE_LIST。

首先尝试打开同名的临时表(open_temporary_tables),如果没有的话,则检查权限并打开实体表(mysql_ha_open_table),打开的表的MDL锁类型为MDL_EXPLICIT,表示需要显式释放(这里通过HANDLER..CLOSE)。

b.读取数据

主函数:Sql_cmd_handler_read::execute

从表上读取数据的实现也比较简单,从thd->handler_tables_hash中拿到已经打开的表对象,加上MDL_TRANSACTION类型的MDL_SHARED_READ MDL锁

总是读取整行记录:

     hash_tables->table->read_set= &hash_tables->table->s->all_set

设置where条件,检查指定的索引是否存在,设置返回结果集的Meta,随后调用引擎的接口函数做初始化工作。

对应Innodb的函数为:ha_innobase::init_table_handle_for_HANDLER, 主要工作包括:1.开启一个只读事务;2.分配Readview;3. 注册XA(innobase_register_trx,感觉有点多余)

随后根据命令类型HANDLER…READ FIRST/NEXT/PREV/LAST 调用引擎接口来获取数据。

这坨代码可以帮助很好的理解引擎层和Server层如何进行数据检索。非常值得一读

c.关闭HANDLER

主函数:Sql_cmd_handler_close::execute

关闭已经打开的表(mysql_ha_close_table),释放MDL,并从thd->handler_tables_hash中移除

时间: 2024-09-20 16:56:17

MySQL的handler接口的相关文章

mysql error handler 例

错误控制 DECLARE { exit|continue } HANDLER FOR {SQLSTATE [VALUE] | condition_name  | SQLWARNING  | NOT FOUND  | SQLEXCEPTION  | mysql_error_code} SQLWARNING    是对所有以01开头的SQLSTATE代码的速记. NOT FOUND     是对所有以02开头的SQLSTATE代码的速记. SQLEXCEPTION  是对所有没有被SQLWARNIN

python 为 mysql 实现 restful 接口的详细步骤代码

最近在做游戏服务分层的时候,一直想把mysql的访问独立成一个单独的服务DBGate,原因如下:     请求收拢到DBGate,可以使DBGate变为无状态的,方便横向扩展     当请求量或者存储量变大时,mysql需要做分库分表,DBGate可以内部直接处理,外界无感知     通过restful限制对数据请求的形式,仅支持简单的get/post/patch/put 进行增删改查,并不支持复杂查询.这个也是和游戏业务的特性有关,如果网站等需要复杂查询的业务,对此并不适合     DBGat

在Python的框架中为MySQL实现restful接口的教程_python

最近在做游戏服务分层的时候,一直想把mysql的访问独立成一个单独的服务DBGate,原因如下:     请求收拢到DBGate,可以使DBGate变为无状态的,方便横向扩展     当请求量或者存储量变大时,mysql需要做分库分表,DBGate可以内部直接处理,外界无感知     通过restful限制对数据请求的形式,仅支持简单的get/post/patch/put 进行增删改查,并不支持复杂查询.这个也是和游戏业务的特性有关,如果网站等需要复杂查询的业务,对此并不适合     DBGat

MySQL数据库及其ODBC接口的介绍(3) (转载)

mysql|odbc|数据|数据库 发信人: engineer (剑胆琴心~还是得走,sigh...), 信区: Linux 标  题: MySQL数据库及其ODBC接口的介绍(3) (转载) 发信站: BBS 水木清华站 (Mon Aug  9 18:03:32 1999)   [ 以下文字转载自 Database 讨论区 ] [ 原文由 engineer 所发表 ]                 第二部分                iODBC   一.iODBC简介          

采用ODBC接口访问MySQL指南

mysql|odbc|访问 采用ODBC接口访问MySQL指南 当前作者: 王猛 ( HeartIcy@163.com )创建日期: 2003年1月15日修订版本: 1.1 MySQL的好与坏我想来想去自己始终认为这不是一个程序员或者系统设计师所应该深究的.假如有权利选择,程序员或者系统设计师应该做的是为项目选择最经济也最合适的解决方案.MySQL只是众多解决方案中的一种,真的不应该深究. MySQL的ODBC接口实现是通过安装MyODBC驱动,这个驱动程序是跨平台的.如果在Linux等unix

如何采用ODBC接口访问MySQL数据库

MySQL的ODBC接口实现是通过安装MyODBC驱动,这个驱动程序是跨平台的.如果在Linux等unix体系操作系统下使用,需要先安装iodbc这些第三方ODBC标准支援平台. 简单的ASP示例代码: dim sql,mysqlset sql = server.createobject("adodb.connection")mysql="driver={mysql odbc 3.51 driver};database=库;server=主机;uid=用户;password=

MySQL的C语言API接口_C 语言

1.首先当然是连接数据库,函数原型如下: MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); 第一个参数 MYSQL是 C api中一个非常重要的变量,里面内存非常丰富

asp采用ODBC接口访问MySQL的方法_Mysql

MySQL的ODBC接口实现是通过安装MyODBC驱动,这个驱动程序是跨平台的.如果在Linux等unix体系操作系统下使用,需要先安装iodbc这些第三方ODBC标准支援平台.  简单的ASP示例代码:  <%  dim sql,mysql  set sql = server.createobject("adodb.connection")  mysql="driver={mysql odbc 3.51 driver};database=库;server=主机;uid

MySQL · 引擎特性 · InnoDB 事务子系统介绍

前言 在前面几期关于 InnoDB Redo 和 Undo 实现的铺垫后,本节我们从上层的角度来阐述 InnoDB 的事务子系统是如何实现的,涉及的内容包括:InnoDB的事务相关模块.如何实现MVCC及ACID.如何进行事务的并发控制.事务系统如何进行管理等相关知识.本文的目的是让读者对事务系统有一个较全面的理解. 由于不同版本对事务系统都有改变,本文的所有分析基于当前GA的最新版本MySQL5.7.9,但也会在阐述的过程中,顺带描述之前版本的一些内容.本文也会介绍5.7版本对事务系统的一些优