实例化:
/*
* String $host:MySQL ip;
* String $port:handlersocket插件的监听端口,它有两个端口可选:一个用于读、一个用于写
*/
$hs = new HandlerSocket($host, $port);
运用例子:
#9998为读取端口 详见上一篇handlersocket的安装
my $args = { host => 'localhost', port => 9998 };
my $hs = new Net::HandlerSocket($args);
打开一个数据表:
*
* Int $index:这个数字相当于文件操作里的句柄,HandlerSocket的所有其他方法都会依据这个数字来操作由这个 openIndex打开的表,
* String $dbname:库名
* String $table:表名
* String $key:表的“主键”(HandlerSocket::PRIMARY)或“索引名”作为搜索关键字段,这就是说表必须有主键或索引
* 个人理解:要被当做where条件的key字段,这样可以认为handlersocket只有一个where条件
* String $column:'column1,column2' 所打开表的字段(以逗号隔开),就是说$table表的其他字段不会被操作
*/
$hs->openIndex($index, $dbname, $table, $key, $column);
运用例子:
my $res = $hs->open_index(0, 'test', 'user', 'PRIMARY', 'user_name,user_email,created');
die $hs->get_error() if $res != 0;
#打开test数据的user表 以主键为key
#这个为查询的列数,这里为三列,分别为:user_name,user_email,created
其中'test'为schema名,'user'为表名,'PRIMARY'为索引名必须要有 为'PRIMARY'或者某个字段名,'user_name,user_email,created'为查询的列名。关于方法的open_index的第一个参数0,用来在每个Net::HandlerSocket对象中唯一标识一个表名。
查询:
/*
* Int $index: openIndex()所用的$index
* String $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '<=', '>',and '<';可以理解为where条件
* Array $value
* Int $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
* Int $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
*/
$retval = $hs->executeSingle($index, $operation, $value, $number, $skip);
运用例子:
my $args = { host => 'localhost', port => 9998 };
my $hs = new Net::HandlerSocket($args);
my $res = $hs->open_index(0, 'test', 'user', 'PRIMARY', 'user_name,user_email,created');
die $hs->get_error() if $res != 0;
$res = $hs->execute_single(0, '>=', [ 1 ], 2, 0); # 此查询语句的意思是:查询主键大于或等于1,数据取2行
die $hs->get_error() if $res->[0] != 0;
shift(@$res);
# 这里我们要注意:execute_single方法的返回值类型为arrayref,其第一个元素为error code:如果为0,则为正常,否则不正常,数组从第
二元素开始即为返回的值,存储格式为 后面一行紧跟前面一行!
#下面为分行打印这个数组的所有值
for (my $row = 0; $row <2 ; ++$row) {
my $user_name= $res->[$row + 0];
my $user_email= $res->[$row+ 1];
my $created= $res->[$row + 2];
if ($user_name || $user_email || $created)
{
print "$user_name\t$user_email\t$created\n";
}
else
{ last;
}
}
$hs->close();
插入(注意:此处的openIndex要用$port_wr,即读写端口):
/*
* Int $index: openIndex()所用的$index
* Array $arr:数字元素数与openIndex的$column相同
*/
$retval = $hs->execute_single(3,'+', [5, 'zhongguo', 'zhogonguo@email.com','2011-01-08 13:51:33' ],1,0);
运用例子:
my $args = { host => 'localhost', port => 9999 };
my $hs = new Net::HandlerSocket($args);
my $res = $hs->open_index(3, 'test', 'user', 'PRIMARY', 'user_id,user_name,user_email,created');
die $hs->get_error() if $res != 0;
$res = $hs->execute_single(3,'+', [5, 'zhongguo', 'zhogonguo@email.com','2011-01-08 13:51:33' ],1,0);
die $hs->get_error() if $res->[0] != 0;
$hs->close();
删除(注意:此处的openIndex要用$port_wr,即读写端口):
/*
* Int $index: openIndex()所用的$index
* String $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '<=', '>',and '<';可以理解为where条件
* Array $value
* Int $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
* Int $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
*/
$retval = $hs->executeDelete($index, $operation, $value, $number, $skip);
运用例子:
my $args = { host => 'localhost', port => 9999 };
my $hs = new Net::HandlerSocket($args);
my $res = $hs->open_index(3, 'test', 'user', 'PRIMARY', 'user_name');
die $hs->get_error() if $res != 0;
$res = $hs->execute_single(3,'=', [4],1,0,'D'); #DELETE user_id=4 的数据
print $res;
die $hs->get_error() if $res != 0;
$hs->close();
更新(注意:此处的openIndex要用$port_wr,即读写端口):
/*
* Int $index: openIndex()所用的$index
* String $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '<=', '>',and '<';可以理解为where条件
* Array $value
* Int $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
* Int $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
*/
$retval = $hs->executeUpdate($index, $operation, $value, $number, $skip);
运用例子:
my $args = { host => 'localhost', port => 9999 };
my $hs = new Net::HandlerSocket($args);
my $res = $hs->open_index(3, 'test', 'user', 'PRIMARY', 'user_name');
die $hs->get_error() if $res != 0;
$res = $hs->execute_single(3,'=', [5],1,0,'U',['woaini']); #当user_id=5,更新'user_name'为woaini
die $hs->get_error() if $res->[0] != 0;
$hs->close();
可以用Multiple operations
可在一次调用中执行多个操作,这样速度更快
my $rarr = $hs->execute_multi([
[ 0, '>=', [ 'foo' ], 5, 0 ],
[ 2, '=', [ 'bar' ], 1, 0 ],
[ 4, '<', [ 'baz' ], 10, 5 ],
]);
for my $res (@$rarr) {
die $hs->get_error() if $res->[0] != 0;
shift(@$res);
# ...
}
execute_single方法的第一个参数需要跟之前open_index方法的第一个参数一致。第二个参数'='指定了检索条件,目前支持'=', '>=', '<=', '>'和'<'。第三个参数[ 'foo' ]为一个arrayref,指定了检索的key,其长度必须小于或者等于对应索引的列数。第四个和第五个参数指定了查询的limit和offset跳过位移。
execute_single方法的返回值类型为arrayref,其第一个元素为error code:
- 0:正常。
- 负数:I/O 错误,对应的Net::HandlerSocket对象需要被丢弃。
- 正数:其它错误,但是与HandlerSocket Plugin的连接仍然正常可用,因此对应的Net::HandlerSocket对象可以继续使用。
参考资料:
http://whitesock.iteye.com/blog/811339
PS:
handlerscoket中有两个 重要的特性;
Write operations do not invalidate the query cache – Exactly what it sounds like, if you performed a write operation via HandlerSocket, you could potentially read stale data from the MySQL interface.
l 写操作并没有淘汰查询缓存 - 如果执行了写操作通过HandlerSocket,由于没有失效查询缓存, 那么你可能从MySQL读到旧的数据。
No support for auto increment – Exactly as it sounds, you couldn’t have auto-incrementing columns get an auto increment value on insert.
l 不支持自动递增 - 插入时无法从自增列上自动获得增量值
今天 我在测试把同一批数据插入一张数据表两次时 发现 插入第一次之后 不能插入第二次了 找了很久原因 看到第二个特性之后才想起 我们每次 openindex的时候都是要用到主键的 如果 这里 你要插入的数据的主键 已经存在数据库中了 就会报 121的错误。