MySQL HandlerSocket in Action

來源:互聯網
上載者:User

1 Overview

    最近一篇關於MySQL HandlerSocket的blog吸引了不少人的注意,甚至MySQL Performance Blog上也有關於HandlerSocket的效能評測。該blog中聲稱對於一個CPU bound而非IO bound的MySQL Server(即絕大部分的資料可以從緩衝中取得,例如InnoDB Buffer Pool有接近100%的命中率),使用HandlerSocket可以將查詢效能提升7.5倍。目前HandlerSocket已經被其作者應用到生產環境,效果良好。筆者在昨天抽空安裝並試用了一下HandlerSocket Plugin。

 

2 Installation

    安裝的過程基本順利,不過可能是由於筆者是在MySQL 5.1.42+InnoDB Plugin 1.0.6上編譯安裝HandlerSocket的原因,編譯HandlerSocket的過程中報如下錯誤:

    configure: error: MySQL source version does not match MySQL binary version

    調查一下後發現是configure指令碼沒有能夠找到MySQL source的版本。筆者調整了configure指令碼,跳過了該檢查。編譯安裝後會在MySQL的plugin目錄中產生一個so檔案。然後在MySQL中安裝該plugin即可。

Sql代碼 
  1. mysql> INSTALL PLUGIN handlersocket soname 'handlersocket.so';  
  2. mysql> show plugins;  
  3. +---------------------+----------+--------------------+---------------------+---------+  
  4. | Name                | Status   | Type               | Library             | License |  
  5. +---------------------+----------+--------------------+---------------------+---------+  
  6. | handlersocket       | ACTIVE   | DAEMON             | handlersocket.so    | BSD     |  
  7. 18 rows in set (0.00 sec)  

 

3 Getting Started

    首先建立一個測試用的表。

Sql代碼 
  1. mysql> CREATE TABLE `user` (  
  2.   `user_id` int(10) unsigned NOT NULL,  
  3.   `user_name` varchar(50) DEFAULT NULL,  
  4.   `user_email` varchar(255) DEFAULT NULL,  
  5.   `created` datetime DEFAULT NULL,  
  6.   PRIMARY KEY (`user_id`),  
  7.   KEY `INDEX_01` (`user_name`)  
  8. ) ENGINE=InnoDB  
  9.   
  10. mysql> insert into user values(1, "John", "john@test.com", CURRENT_TIMESTAMP);  
  11. mysql> insert into user values(2, "Kevin", "Kevin@test.com", CURRENT_TIMESTAMP);  
  12. mysql> insert into user values(3, "Dino", "Dino@test.com", CURRENT_TIMESTAMP);  

   

    接下來按照blog中的例子,編寫如下perl指令碼handlersocket.pl。

Perl代碼 
  1. #!/usr/bin/perl  
  2.   
  3. use strict;  
  4. use warnings;  
  5. use Net::HandlerSocket;  
  6.   
  7. #1. establishing a connection  
  8. my $args = { host => 'localhost', port => 9998 };  
  9. my $hs = new Net::HandlerSocket($args);  
  10.   
  11. #2. initializing an index so that we can use in main logics.  
  12. # MySQL tables will be opened here (if not opened)  
  13. my $res = $hs->open_index(0, 'test', 'user', 'INDEX_01', 'user_name,user_email,created');  
  14. die $hs->get_error() if $res != 0;  
  15.   
  16. #3. main logic  
  17. #fetching rows by id  
  18. #execute_single (index id, cond, cond value, max rows, offset)  
  19. $res = $hs->execute_single(0, '=', [ 'kevin' ], 1, 0);  
  20. die $hs->get_error() if $res->[0] != 0;  
  21. shift(@$res);  
  22. for (my $row = 0; $row < 1; ++$row) {  
  23.   my $user_name= $res->[$row + 0];  
  24.   my $user_email= $res->[$row + 1];  
  25.   my $created= $res->[$row + 2];  
  26.   print "$user_name/t$user_email/t$created/n";  
  27. }  
  28.   
  29. #4. closing the connection  
  30. $hs->close();  

 

    最後執行handlersocket.pl,結果如下:

Shell代碼 
  1. perl handlersocket.pl  
  2. Kevin   Kevin@test.com  2010-11-14 22:35:22  

 

4 Philosophy of the HandlerSocket

    通常,MySQL Server可以被看成兩層架構:即SQL Layer和Storage Engine Layer,它們之間通過Handler API進行互動。MySQL Server在接收到用戶端的Query請求後,通常需要在SQL layer中進行詞法分析,文法分析,最佳化等過程,最終產生一個樹型的查詢計劃,交由執行引擎執行。執行引擎根據查詢計劃,跟相應的儲存引擎通訊,得到查詢結果。

 

    HandlerSocket的作者認為,對於CPU bound的MySQL server來說,SQL layer消耗了過多的資源,以致總體效能不佳。HandlerSocket則繞過了MySQL Server的SQL layer,直接跟儲存引擎互動,從而帶來了大幅的效能提升。預設情況下HandlerSocket Plugin監聽9998和9999兩個連接埠,其中9998隻支援讀操作,9999支援讀寫操作,但是效能跟9998連接埠相比稍慢。

 

    HandlerSocket的作者在其blog中列出了一系列HandlerSocket的優點,以下是筆者認為其中比較重要的:

  • Can handle lots of concurrent connections
  • Extremely high performance
  • No duplicate cache
  • No data inconsistency
  • Independent from storage engines
  • Supporting lots of query patterns
  • No need to modify/rebuild MySQL
  • All operational benefits from MySQL

      其中No duplicate cache和No data inconsistency這兩條,筆者感觸頗深。關於MySQL的NoSQL擴充,可能很多項目都在使用memcached,或者自己實現的cache等。這種獨立緩衝的實現方式有個重要的局限,即如何保證MySQL和cache之間的資料一致性,儘管Memcached Functions for MySQL(基於Trigger和MySQL UDF)從某種程度上提供了一種解決方案。

     此外,關於Independent from storage engines和Supporting lots of query patterns。理論上通過Handler API可以和任何儲存引擎互動,但是目前HandlerSocket只是在InnoDB Plugin上進行了測試。此外,HandlerSocket的作者在其blog上指出,通過HandlerSocket,不僅可以通過主鍵查詢,也可以通過普通索引,甚至不使用索引進行查詢(包括範圍查詢),甚至還可以進行insert/update/delete等寫操作。

    關於All operational benefits from MySQL,正如在其blog中提到的,可以比較方便地通過MySQL的既存功能對HandlerSocket進行監控,例如以下幾個監控指標:

Sql代碼 
  1. mysql> show global status like 'handler_read%';  
  2. mysql> show global status like 'Com_select%';  
  3. mysql> show global status like 'InnoDB_rows_read';  

 

5 Client API

    遺憾的是到目前為止,HandlerSocket只有C和Perl的用戶端API,Java和Python等版本的用戶端API貌似在開發中。在這裡簡單分析一下Perl版本的用戶端API。

 

5.1 Connection

    與HandlerSocket Plugin建立串連的方式如下:

Perl代碼 
  1. use Net::HandlerSocket;  
  2. my $args = { host => 'localhost', port => 9998 };  
  3. my $hs = new Net::HandlerSocket($args);  

    其中Net::HandlerSocket模組存放於HandlerSocket的分發tar包的perl-Net-HandlerSocket目錄中,編譯安裝方式如下:

Shell代碼 
  1. cd perl-Net-HandlerSocket/  
  2. perl Makefile.PL  
  3. make  
  4. make install  

 

5.2 Opening index

    在進行操作之前,首先需要開啟一個索引,如下:

Perl代碼 
  1. my $err = $hs->open_index(3, 'database1', 'table1', 'PRIMARY', 'f1,f2');  
  2. die $hs->get_error() if $res->[0] != 0;  

    其中'database1'為schema名,'table1'為表名,'PRIMARY'為索引名,'f1,f2'為查詢的列名。關於方法的open_index的第一個參數3,用來在每個Net::HandlerSocket對象中唯一標識一個表名。

 

5.3 Query

    通過execute_single方法進行查詢,例如:

Perl代碼 
  1. my $res = $hs->execute_single(3, '=', [ 'foo' ], 1, 0);  
  2. die $hs->get_error() if $res->[0] != 0;  
  3. 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對象可以繼續使用。

    第一個元素之後的其它元素即查詢結果,如果返回的row數大於1,那麼也是存放在這個一維數組中。假設查詢結果共5行,每行三列,那麼對應的代碼如下:

Perl代碼 
  1. die $hs->get_error() if $res->[0] != 0;  
  2. shift(@$res);  
  3. for (my $row = 0; $row < 5; ++$row) {  
  4.   for (my $col = 0; $col < 3; ++$col) {  
  5.     my $value = $res->[$row * 5 + $col];  
  6.     # ...  
  7.   }  
  8. }  

 

5.4 Insert records

    execute_single方法也可以用來插入記錄,例如:

Perl代碼 
  1. my $args = { host => 'localhost', port => 9999 };  
  2. my $hs = new Net::HandlerSocket($args);  
  3.   
  4. my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]);  
  5. die $hs->get_error() if $res->[0] != 0;  
  6. my $num_inserted_rows = $res->[1];  

    需要注意的是,此時串連的是9999連接埠,因為9998連接埠只支援讀操作。

 

5.5 Update or delete records

    對於更新和刪除操作,同樣使用execute_single方法,例如:

Perl代碼 
  1. my $args = { host => 'localhost', port => 9999 };  
  2. my $hs = new Net::HandlerSocket($args);  
  3.   
  4. my $res = $hs->execute_single(3, '=', [ 'bar' ], 1, 0, 'U', [ 'fubar', 'hoge' ]);  
  5. die $hs->get_error() if $res->[0] != 0;  
  6. my $num_updated_rows = $res->[1];  
  7.   
  8. my $res = $hs->execute_single(3, '=', [ 'baz' ], 1, 0, 'D');  
  9. die $hs->get_error() if $res->[0] != 0;  
  10. my $num_deleted_rows = $res->[1];  

    execute_single方法的第六個參數指定的操作類型,目前支援'U'和'D'。對於'U'操作,execute_single方法的第七個參數指定了更新後的值;對於'D'操作,第七個參數被忽略。

 

5.6 Multiple operations

    可在一次調用中執行多個操作,這樣速度更快,例如:

Perl代碼 
  1. my $rarr = $hs->execute_multi([  
  2.   [ 0, '>=', [ 'foo' ], 5, 0 ],  
  3.   [ 2, '=', [ 'bar' ], 1, 0 ],  
  4.   [ 4, '<', [ 'baz' ], 10, 5 ],  
  5. ]);  
  6. for my $res (@$rarr) {  
  7.   die $hs->get_error() if $res->[0] != 0;  
  8.   shift(@$res);  
  9.   # ...  
  10. }  

 

6 Reference

    http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html (翻)

    http://www.mysqlperformanceblog.com/2010/11/02/handlersocket-on-ssd/

 

原文地址:http://whitesock.iteye.com/blog/811339

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.