5分でMySQLエンジン

バージョン5.1以降、MySQLは動的に接続されたプラグインのサポートを実装しています。 そして、ディストリビューションには-exampleというサンプルコードスケルトンが含まれています。 これは、ベースハンドラーであるハンドラーのインターフェースと構造を記述します。 ハンドラーのコピーは、データベース接続ごとに個別に作成されます。 また、他のハンドラーとの同期に使用されるテーブル記述子TABLE * tableと補助ベクトルTABLE_SHARE * shareへのポインターも受け取ります。 プラグイン開発はモジュール方式で実行でき、そもそも必要な機能のみを実装し、より複雑な操作をスタブで閉じます。

サンプルテンプレートはインターフェイスのみを記述し、操作を実行しないため、この例では、単一リンクリストに基づくCRUD操作の実装を追加します。 これを行うには、4つの関数のみを記述します。





環境の準備
サンプルテンプレートは、MySQLソースコードのstorage / exampleディレクトリの2つのファイルha_example.hおよびha_example.ccにあります。 この例では、 MySQL Community 5.5.35が使用されます。 まず、 をコピーして、名前をsmalldbに変更します



wget http://downloads.mysql.com/archives/get/file/mysql-5.5.35.tar.gz tar -zxvf mysql-5.5.35.tar.gz cd mysql-5.5.35 cp -rf storage/example storage/smalldb cd storage/smalldb sed -e 's/EXAMPLE/SMALLDB/g' -e 's/example/smalldb/g' ha_example.h > ha_smalldb.h sed -e 's/EXAMPLE/SMALLDB/g' -e 's/example/smalldb/g' ha_example.cc > ha_smalldb.cc sed -i 's/EXAMPLE/SMALLDB/g;s/example/smalldb/g' CMakeLists.txt
      
      







まず、単一リンクリストのプリセットと、先頭、現在、前、および次のリスト項目( ha_smalldb.h内 )へのいくつかのポインターを追加することから始めましょう。

 class node{ public: uchar* data; //   node* next; //     node(){ data=NULL; next=NULL; } ~node(){ free(data); } }; node *first, *cur, *prev, *next; int row_count, cur_pos; void append_node(node* n){ if (first==NULL){ first=n; }else{ node* iter=first; while (iter->next!=NULL){iter=iter->next;} iter->next=n; } }
      
      





次に、書き込み操作-write_row(uchar * buf)に進みましょう。 引数としてbufが渡され、追加された文字列の内容が内部表現で含まれます。





予備処理を行わずにデータをメモリに保存するため、文字列の内容全体を単純にコピーできます。 メタデータを含む行の長さは、テーブル記述子table-> s-> reclengthから取得できます。

 int ha_smalldb::write_row(uchar *buf) { DBUG_ENTER("ha_smalldb::write_row"); node* n=new node(); n->data = (uchar*) malloc(sizeof(uchar)*table->s->reclength); memcpy(n->data,buf,table->s->reclength); append_node(n); row_count++; DBUG_RETURN(0); }
      
      





テーブルからデータを読み取るとき、一連のrnd_initrnd_nextを使用した順次スキャンが使用されます。 エンジンがインデックスまたは主キーをサポートしていない場合に使用されます。 まず、 rnd_init()でポインターを準備する必要があります。

 int ha_smalldb::rnd_init(bool scan) { DBUG_ENTER("ha_smalldb::rnd_init"); cur=NULL; prev=NULL; next=first; cur_pos=0; DBUG_RETURN(0); }
      
      





ブール引数スキャンは、テーブルをランダムに(一貫性なく)読み取るデータベースの意図を示します。 無視しても問題ありません。 未実現のrnd_pos()コマンドを呼び出そうとすると、データベースは応答としてHA_ERR_WRONG_COMMANDを受け取り、順番に読む必要があると推測します。

単一のrnd_init()の後、データベースはテーブルの最後(HA_ERR_END_OF_FILE)に達するまでrnd_next()を順番に呼び出します。 各呼び出しの後、 bufのメモリは、内部表現の文字列の内容で満たされる必要があります。

 int ha_smalldb::rnd_next(uchar *buf) { int rc; DBUG_ENTER("ha_smalldb::rnd_next"); MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, TRUE); if (next!=NULL){ prev=cur; cur=next; next=cur->next; memcpy(buf,cur->data,table->s->reclength); cur_pos++; rc=0; }else{ rc= HA_ERR_END_OF_FILE; } MYSQL_READ_ROW_DONE(rc); DBUG_RETURN(rc); }
      
      





最後に、リストから現在のアイテムを削除してdelete_row()を記述します。

 int ha_smalldb::delete_row(const uchar *buf) { DBUG_ENTER("ha_smalldb::delete_row"); if (cur!=first){ free(cur); prev->next=next; }else{ free(cur); cur=NULL; first=next; } row_count--; DBUG_RETURN(0); }
      
      





以上で、ミニエンジンの動作を体験できます。

設置
MySQL 5.5では、コードのビルドにcmakeが使用されます。 インストールするには、.soファイルをコンパイルし、インストールされたバージョンのMySQLのpluginsディレクトリにコピーするだけです。 次のコマンドを使用して認識できます-SHOW VARIABLES LIKE "%plugin_dir%";

MySQL自体がインストールされていないか、 別のバージョンがインストールされている場合 、make installを使用してデータベースを追加インストールする必要があります。



 #   mysql-5.5.35: cmake . cd storage/smalldb make cp ha_smalldb.so /opt/mysql/server-5.5.35/lib/plugin/ #  MySQL: INSTALL PLUGIN smalldb SONAME "ha_smalldb.so"; CREATE DATABASE small; USE small; CREATE TABLE tbl (a VARCHAR(255), b VARCHAR(255)) ENGINE=smalldb; INSERT INTO tbl values ("Hello","Habr"); SELECT * FROM tbl;
      
      









INSERTおよびSELECTに加えて、 LIKEINNER JOINなどの演算子を使用してさらに複雑なSQLクエリを実行できます。これは、SQLクエリの最適化がエンジンに制御を移す前にデータベースカーネルレベルで実装されるためですが、その有効性はもちろんエンジンでサポートされる機能に依存します

この資料が、MySQLプラグインのインターフェースに少し精通していることを願っています。 完全なプロジェクトコードはgithubからダウンロードできます。

MySQLエンジンの内部をより真剣に研究したいが、InnoDBに近づくリスクを冒したくない場合は、CSVまたはHEAP(新しい名前-MEMORY)に注意することをお勧めします。 CSVは、同じ形式でデータをディスクに保存する機能を追加します。 HEAPは、その名前が示すように、データをヒープに編成し、ハッシュインデックスのサポートを実装します。 どちらの場合も、行を削除した後にメモリの空きセクションを解放するという補助的な問題を解決する必要があります。これは、単一リンクリストを使用して回避できました。

独自のエンジンの作成に関する詳細なガイドは、 MySQL Internals Manualの 22章にあります。 第22章カスタムストレージエンジンの作成

PSそして最後に、 ctagsユーティリティに慣れていない人にはctagsユーティリティをお勧めします。 さまざまなファイルに散らばっているコードを調べるのに非常に便利です。たとえば、CTRL +]で関数または変数の定義にジャンプできます。 vim、emacs、およびその他の一般的なエディターのサポートがあります。 ここにクイックガイドがあります。



All Articles