読者です 読者をやめる 読者になる 読者になる

MySQL 5.6 で動くストレージエンジン・テンプレート

MySQL 5.6 で動く Skeleton Engine, Yet Another Skeleton Engine を Github で公開してます.
https://github.com/laysakura/mysql-YetAnotherSkeletonEngine

Skeleton Engine は MySQL のストレージエンジンを作成するためのテンプレートです.
オリジナルのものは
http://www.sourcefiles.org/Databases/Utilities/
の skeleton_engine-0.7.tar.gz でダウンロード可能でした(2013/02/10 現在)が,古いバージョンの MySQL を前提としており,MySQL 5.6 にオリジナルのままの Skeleton Engine を組込むことはできません.
# オリジナルのものが MySQL 5.6 で使えない理由は最後の節に記載します.

そこで Yet Another Skeleton Engine と名付けまして,MySQL 5.6 で動くストレージエンジンのテンプレートを公開しました.
本エントリでは,まず Yet Another Skeleton Engine の使い方を記し,次にメモ程度にリポジトリ作成作業のログを記します.

追記: 2013/02/17

Yet Another Skeleton Engine を使用中にクラッシュするバグを修正しました.
MySQL 5.6 本体の Example Storage Engine と同じコンパイルオプションを付けることでクラッシュはなくなった模様です.
https://github.com/laysakura/mysql-YetAnotherSkeletonEngine/commit/8b4f3c8d83b47c4e63d9257c92ea71051501841f

クラッシュの再現コードを本エントリの最後に付しておきます.

Yet Another Skeleton Engine の入手から使用まで

入手
git clone git://github.com/laysakura/mysql-YetAnotherSkeletonEngine.git
cd mysql-YetAnotherSkeletonEngine
ビルド・インストール
./configure  --with-mysql=[ビルド済みMySQLのソースディレクトリ]  --libdir=[MySQLのインストールディレクトリ]/lib/plugin
make
sudo make install
使用
sudo /etc/init.d/mysqld restart
mysql -u root -p

ここからは MySQL のシェルでインストール&確認です.

mysql> INSTALL PLUGIN YA_SKELETON SONAME 'libskeleton_engine.so';
Query OK, 0 rows affected (0.00 sec)

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| EXAMPLE            | YES     | Example storage engine                                         | NO           | NO   | NO         |
| YA_SKELETON        | YES     | Yet Another Skeleton Storage Engine                            | NO           | NO   | NO         |
...

YA_SKELETON というのが今回インストールした Yet Another Skeleton Engine です.
中身は EXAMPLE ストレージエンジンと全く同じなので,
http://dev.mysql.com/doc/refman/5.6/en/example-storage-engine.html
のように動作確認してみて下さい.

リポジトリ作成作業のログ

ディレクトリ作成
mkdir mysql-YetAnotherSkeletonEngine
cd mysql-YetAnotherSkeletonEngine/
必要ファイルをコピー

次のようなディレクトリ構成とする.

  • ~/src/skeleton_engine-0.7/ :: オリジナルの Skeleton Engine.
  • /usr/share/libtool/config/ :: ltmain.sh があるところ.
  • ~/src/mysql-5.6.10/ :: MySQL のソースディレクトリ.
cp ~/src/skeleton_engine-0.7/AUTHORS .
cp ~/src/skeleton_engine-0.7/COPYING .
cp ~/src/skeleton_engine-0.7/ChangeLog .
cp ~/src/skeleton_engine-0.7/INSTALL .
cp ~/src/skeleton_engine-0.7/Makefile.am .
cp ~/src/skeleton_engine-0.7/NEWS .
cp ~/src/skeleton_engine-0.7/README .
cp ~/src/skeleton_engine-0.7/README.windows .
cp ~/src/skeleton_engine-0.7/configure.in .

mkdir config
cp ~/src/skeleton_engine-0.7/config/ac_mysql.m4 config/
cp ~/src/skeleton_engine-0.7/config/dtrace.m4 config/
cp /usr/share/libtool/config/ltmain.sh config/  # ltmain.sh は何故か automake で作られなかったので・・・

mkdir src
cp ~/src/skeleton_engine-0.7/src/Makefile.am src/
cp ~/src/skeleton_engine-0.7/src/skeleton_probes.d src/
cp ~/src/skeleton_engine-0.7/src/skeleton_probes.h src/
cp ~/src/skeleton_engine-0.7/src/skeleton_config.h.in src/

# MySQL から example storage engine をコピー
cp ~/src/mysql-5.6.10/storage/example/ha_example.cc src/ha_skeleton.cc
cp ~/src/mysql-5.6.10/storage/example/ha_example.h src/ha_skeleton.h
いくつかのファイルの編集

(2013/02/13 - libmysqlservices を静的リンクしていた部分を動的リンクに変更)

# config/ac_mysql.m4 を編集
diff config/ac_mysql.m4.old config/ac_mysql.m4
10,12c10
<     if test -d "$withval/sql"; then
<       MYSQL_SRC="$i/mysql_config"
<     fi
---
>     MYSQL_SRC="$withval"

# configure.in を編集
diff configure.in.old configure.in
5c5
< AM_INIT_AUTOMAKE("skeleton_engine", 0.7)
---
> AM_INIT_AUTOMAKE("ya_skeleton_engine", 0.1)
20a21
> AC_SUBST(MYSQL_SRC)

# src/Makefile.am を編集
diff src/Makefile.am.old src/Makefile.am
16c16
< libskeleton_engine_la_LIBADD =
---
> libskeleton_engine_la_LIBADD = -lmysqlservices
22c22
< libskeleton_engine_la_LDFLAGS =       -module
---
> libskeleton_engine_la_LDFLAGS =       -module -L$(MYSQL_SRC)/libservices/

# ha_skeleton.cc を編集
diff src/ha_skeleton.cc.old src/ha_skeleton.cc
92c92
< #include "ha_example.h"
---
> #include "ha_skeleton.h"
980,982c980,982
<   "EXAMPLE",
<   "Brian Aker, MySQL AB",
<   "Example storage engine",
---
>   "YA_SKELETON",
>   "Sho Nakatani",
>   "Yet Another Skeleton Storage Engine",
configure を作る
# aclocal
aclocal

# .h.in から .h を作る
autoheader

# automake で config/* や Makefile.in を作る
automake --add-missing --copy
configure.in:11: installing `config/config.guess'
configure.in:11: installing `config/config.sub'
configure.in:5: installing `config/install-sh'
configure.in:5: installing `config/missing'
src/Makefile.am: installing `config/depcomp'

# autoconf で configure を作る
autoconf

オリジナルの Skeleton Engine が MySQL 5.6 で使えない理由

ha_skeleton.* は古いバージョンの MySQL に対応して書かれており,インクルードしている一部ヘッダが MySQL 5.6 とは対応していません.

また,MySQL 5.6 のストレージエンジン開発では,libmysqlservices.so というライブラリのリンクが必要です.これを忘れると,いざ作成したライブラリを使おうとすると次のようにエラーになります.

mysql> INSTALL PLUGIN YOUR_NEW_ENGINE SONAME 'libskeleton_engine.so';
ERROR 1126 (HY000): Can't open shared library '/usr/local/mysql/lib/plugin/libskeleton_engine.so' (errno: 2 /usr/local/mysql/lib/plugin/libskeleton_engine.so: undefined symbol: my_snprintf_service)

参考: http://dev.mysql.com/doc/refman/5.6/en/compiling-plugin-libraries.html

おまけ: 2013/02/17 クラッシュバグ再現テスト

https://github.com/laysakura/mysql-YetAnotherSkeletonEngine/commit/8b4f3c8d83b47c4e63d9257c92ea71051501841f
の修正前に発生していたクラッシュバグを再現する Perl のテストコードを載せておきます.

#!/usr/bin/perl
 
use strict;
use warnings;
 
use DBI;
 
my $TEST_ROWS;
BEGIN {
    $TEST_ROWS = $ENV{TEST_ROWS} || 1024;
};
 
use Test::More tests => $TEST_ROWS * 4 + 2;
 
use File::Basename;
use Cwd 'realpath';
my $testdir = realpath(dirname(__FILE__));
 
my $dbh = DBI->connect(
    $ENV{DBI} || 'dbi:mysql:database=test;host=localhost',
    $ENV{DBI_USER} || 'root',
    $ENV{DBI_PASSWORD} || '',
) or die 'connection failed:';
 
 
## Crash bug repro                                                                                                                                                                                                                  
ok($dbh->do("drop table if exists t_example"));
ok($dbh->do("create table t_example (a INT) engine = ya_skeleton"));
 
for (my $i = 0; $i < $TEST_ROWS; $i++) {
    ok($dbh->do("insert into t_example values (777),(333),(888)"));
}
for (my $i = 0; $i < $TEST_ROWS; $i++) {
    ok($dbh->do("select * from t_example"));
}
for (my $i = 0; $i < $TEST_ROWS; $i++) {
    ok($dbh->do("insert into t_example values (777),(333),(888)"));
    ok($dbh->do("select * from t_example"));
}