漢(オトコ)のコンピュータ道

ちょっと硬派なコンピュータフリークのBlogです。

2009-11-04

MySQL Clusterが苦手とするJOINを如何にして克服するべきか。

シェアードナッシング型の負荷分散機能を持ち、なおかつ同期レプリケーションによるHA機能まで備えたMySQL Cluster最大の弱点といえば、JOINの遅さであろう。MySQL ClusterのJOINは偽りなく遅い。JOINを多用するアプリケーションでMySQL Clusterを利用するのはある意味マゾヒスティックな行為であると言えよう。何故MySQL ClusterはJOINが遅いのか?それはMySQL Clusterが分散データベースだからである。

ご存じの通り、MySQLにおけるJOINのアルゴリズムにはNested Loopしかない。他のストレージエンジンを利用していればそれでも十分実用に耐えうるぐらい高速なのだが、MySQL Clusterの場合はそうはいかない。JOINでは自ずとストレージエンジンからデータをフェッチする回数が増えるが、MySQL Clusterの場合レコードのフェッチはネットワークを経由しなければいけないのでここがボトルネックになってしまう。

例えば、2つのNDBストレージエンジン(MySQL Cluster)のテーブルをJOINする場合を考えよう。外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要があるとする。その場合、外部表から1回(1回のスキャンオペレーションでデータをフェッチできる)、内部表からM回のフェッチをしなければならない。1回のフェッチにつき、ネットワーク上をパケットが往復するわけであるから、InnoDBやMyISAMのように同一ホストから(特にメモリ上のキャッシュから)データをフェッチする場合と比べてJOINは不利なのである。

ではMySQL ClusterにおいてJOINを高速化するにはどうすればいいだろうか?

単純に「ネットワーク接続を高速化すればいいじゃないか。10GbEのNICを使えば?」などと思うかも知れない。それはある意味正しいが、正しいアプローチではないと思う。確かにJOINの性能は向上するのだが、10GbEとてレイテンシは無視できないので同一ホスト上のメモリからデータをフェッチする場合より遅いのは明らかである。

少し話はそれるが、何かを処理するユニットを増強して(もしくはたくさん並べて)何とかしてしまおうというのは、いかにもBruteなやり方である。確かにハードウェアの性能向上はBruteなやり方でも良いと思うし、Bruteなやり方で成功した事例もたくさんある。例えばグラフィックスチップにたくさんの演算回路(シェーダ)を組み込んだり、ハイエンドサーバにCPUを満載したり、安価なマシンを並べてスケールアウトしたり。しかし、Bruteなアプローチではシステムの性能の限界はハードウェアの性能の限界によって頭打ちしてしまうことになる。だが一方で、ソフトウェアの性能向上を考える場合には、同じ条件のハードウェアで如何に高速化するかということを検討しなければならないと思う。つまり、もっとSmartなやり方でないといけない。ハードウェアはBruteに。ソフトウェアはSmartに。それがシステムを高速化する際のコツだろう。

そんなわけで話は戻るが、つまり単純にネットワーク接続を高速化するのは、一定の効果は上がるがすぐに限界を迎えてしまう可能性が高いのである。

現時点でも実装可能かつスマートなアプローチは、レプリケーションを利用することである。Kaj Arno氏のエントリでも紹介されているが、MySQL Clusterから通常のMySQL Serverへのレプリケーションを行い、JOINを伴う複雑なSELECTに関してはスレーブで実行することにより、複雑なSELECTを高速化するというテクニックが存在する。(詳細はKaj氏のブログエントリの図を参照して頂きたい。)スレーブへのレプリケーションは非同期なので、厳密な最新のデータに対するクエリは実行出来ないが、厳密な最新のデータが必要ない場合この方法は大抵うまくいく。システムの構築がちょっと面倒臭くなる以外弊害もない。複雑なクエリは集計データなどに利用されることが多いので、適用出来るシーンも多いだろう。

この方法で気をつけるべきポイントは、replicate[-wild]-do-tablereplicate[-wild]-ignore-tableオプションを利用して、複製するテーブルを限定することである。そうしないとndb_apply_statusテーブルへの更新が出来ないというエラーに見舞われてしまうことになる。MySQL Clusterテーブルを更新すると、バイナリログは自動的にmysql.ndb_apply_statusテーブルへの更新が含まれてしまう。このテーブルはNDBストレージエンジンで定義されているテーブルでMySQL Cluster同士のレプリケーションに利用されるのだが、MySQL Clusterから通常のMySQL Serverへレプリケーションする場合には不要などころかエラーの元凶になるだけなのできっちりとフィルタリングしておこう。例えば、worldデータベースに存在するテーブルだけを対象にしたい場合は、スレーブのmy.cnfに次のようにreplicate-wild-do-tableを使って記述するといいだろう。

[mysqld]
replicate-wild-do-table=world.%

MySQL ClusterのSQLノード上で新規にテーブルを作成する場合、つまりCREATE TABLE tbl(...) ENGINE NDB;とした場合に、スレーブ側ではデフォルトのストレージエンジンが使用されることになる点にも注意したい。(通常のMySQL ServerにはNDBストレージエンジンは含まれていないからだ。)--storage-engineオプションを好みのもの(InnoDB等)に設定しておこう。

しかし、MySQL Clusterの開発者たちは、JOINが遅いという現状をいつまでも放置しておくつもりはない。

将来的にはMySQL ClusterのJOIN性能は大幅に改善される予定である。まず、近い将来に搭載される機能として挙げられるのがBKA(Batched Key Access)というJOIN最適化手法である。この方法では、これまで1+M回必要だったデータのフェッチが、最も効率的な場合にはたったの2回にまで減少する。2つのNDBテーブルのJOINにおいて外部表からM行フェッチし、外部表の一行につき内部表から平均でN行フェッチする必要がある場合、BKAの動作は次のようになる。
  1. 外部表からM行フェッチ(一回のスキャン)
  2. JOINに利用するキーの値をリストアップする。
  3. リストアップされたキーをNDBストレージエンジンにPush-Downする。
  4. 内部表からN行フェッチ(一回のスキャン)
内部表からレコードをフェッチする際、ICT(Index Condition Pushdown)という機能が利用されるのだが、ICTではストレージエンジンに対してフェッチしたい行を含むキーを一気に送信し、レコードを一気にフェッチするのである。その結果、MySQL Clusterではネットワーク上のパケット往復の回数が劇的に減少し、JOINの性能が向上するというわけだ。従って、BKAが実装された暁には、通常のMySQL Serverへレプリケーションするといった面倒な運用は一切不要になるだろう。少なくとも他のストレージエンジンと同等程度までJOINの性能が改善するはずであるから。

BKAブラボー!!と思うかも知れない。
しかし、そんなところで終わるようなMySQL Cluster開発チームではないのである!!

実装されるのはかなり先になるだろうが、MySQL ClusterのJOINを劇的に高速化することが出来ると予想される機能が実装される見込みである。それはDbspjと呼ばれる機能であり、言うなれば「分散JOIN」とでも呼ぶべきシロモノである。かなり貪欲な性能の追求である。MySQL Clusterは分散型のRDBMSであるから、JOINの処理も分散して行えば良いじゃないかと考えるのが人情というもであるが、一方でそのような機能を実装するのは難しいということもまた事実である。(従って現時点ではそのような機能は実装されていない。)しかし難しいというのを理由にして諦めないのが真の漢。MySQL Cluster開発チームはこの難題にチャレンジしており、既に初期段階のテスト結果が開発者Jonas Oreland氏のブログで公表されている。ぶっちゃけ通常のJOINと比べると格段に速い。MySQL Clusterの正式リリースに搭載されるのはずっと先になるだろうが、楽しみな機能の一つである。

2009-11-02

GPLソフトウェアのパッチをBSDライセンスで提供することの意義

先日の投稿「GPLが適用されているソフトウェア=MySQLのパッチをBSDライセンスでリリースする。では、GPLが適用されているソフトウェアにBSDライセンスのパッチを提供することが出来るということを書いた。ただし、それが出来ることによってどのような意義があるのかということについては触れていなかった。その結果、
単独で動かないパッチに元のと違うライセンスをつける感覚がよくわからない。
という疑問が生じたらしい(ブコメ参照)ので、パッチをBSDライセンスで提供するということはどういうことなのかを説明しようと思う。

まず第一に、パッチ自身はBSDライセンスなので、BSDライセンスに従う限り他のプログラムへ流用することが出来る。
パッチといえども、それが何かの機能を追加する類のものであれば巨大なプログラムになり得るだろう。事実、Googleが提供するMySQLのパッチもかなりデカイ。パッチの規模がでかくなれば、独立して機能する有益なロジックが多々含まれることになるだろう。パッチのライセンスがBSDライセンスであれば、その機能をGPL以外のライセンスのソフトウェア、例えばBSDライセンスのPostgreSQLなどに追加するということも可能である。つまり、パッチをBSDライセンスにすることで、MySQLとPostgreSQLに同じ機能を追加するということが出来るわけだ。

第二に、
MySQLはデュアルライセンスなので、BSDライセンスで提供されたパッチであればGPL版とコマーシャルライセンス版の両方に機能を追加することが出来る。従って、BSDライセンスのパッチはMySQLにとっては都合が良いのである。(MySQLがデュアルライセンスを貫く以上、GPLで提供されたパッチは適用出来ないのである。)

ちなみに、GPLソフトウェアであるMySQL 6.0からforkしたDrizzleも、
全てのContributionはBSDライセンスのもとに行われている。(Drizzleに提供された全てのソースコードはBSDライセンスが適用されている。)従って、Drizzleに追加された全ての機能は、GPL版、コマーシャルライセンス版のいずれのMySQLにも取り込むことが出来るのである。また、DrizzleにContributeされたコードは、PostgreSQLなどの他のライセンスのRDBMSソフトウェアにも取り込むことが出来るので、PostgreSQLerの人は是非Drizzleのソースコードを覗いて見ると良いのではないだろうか。ただし、Drizzleでは積極的に外部のライブラリを取り込んで利用しようという方針があるので、外部のGPLが適用されたライブラリに依存した機能については、BSDライセンスによる利用は出来ない点には注意が必要である。(もちろん元のMySQL 6.0から残っているコードはPostgreSQLに取り込むことは出来ないので注意しよう。)

さて、ここまで書くと「GPLよりBSDライセンスの方が優れている」ということを言い出す人が居るかも知れないので、この点について少し捕捉しておく。
GPLとBSDライセンスを比較するのはハッキリ言って無意味である。確かにBSDライセンスの方が再利用出来るソフトウェアの範囲が広い。(商用、無償、プロプラエタリ、OSSを問わず利用可能である。)しかし一方で、GPLはソフトウェアの利用者に(それをカスタマイズすることを含めて)未来永劫最大限の自由を約束するライセンスであり、GPLを継承することによって再利用可能な場面が限定されることは、その自由を約束するために必要な措置なのである。つまり、GPLとBSDライセンスはそれぞれ異なる属性を持ったライセンス(かたやCopyleft、かたやPermissive)であり、それぞれのライセンスを適切に使い分けるのが重要だということである。ライセンスに対する理解とそれらの使い分けは、オープンソースに生きる人々にとっては最も重要な嗜みと言えるだろう。

2009-10-30

GPLが適用されているソフトウェア=MySQLのパッチをBSDライセンスでリリースする。

Googleがリリースしている有名なMySQL 5.0用パッチは、なんとBSDライセンスで提供されている。MySQLは周知の通りGPLでリリースされているが、GPLソフトウェアはその性質上、改変するとそのソフトウェアもGPLでリリースしなければいけない。だったら何故そのパッチをBSDライセンスで提供することが出来るのか?!ホントにそんなこと出来るのか?!Googleは何か間違ってるんじゃないか?!などと疑問に思われることだろう。

結論から言うと、Googleは何らライセンスの間違いを犯しているわけではなく、GPLソフトウェアにGPL互換のライセンスでパッチを書くことが出来るのは、GPLの条文そのものにしっかりと書いてあるのである。

以下、GPLv2の日本語訳より抜粋。
以上の必要条件は全体としての改変された著作物に適用される。著作物の一部が『プログラム』から派生したものではないと確認でき、それら自身別の独立 した著作物であると合理的に考えられるならば、あなたがそれらを別の著作物として分けて頒布する場合、そういった部分にはこの契約書とその条件は適用されない。しかし、あなたが同じ部分を『プログラム』を基にした著作物全体の一部として頒布するならば、全体としての頒布物は、この契約書が課す条件 に従わなければならない。というのは、この契約書が他の契約者に与える許可は『プログラム』丸ごと全体に及び、誰が書いたかは関係なく各部分のすべてを保護するからである。 よって、すべてあなたによって書かれた著作物に対し、権利を主張したりあなたの権利に異議を申し立てることはこの節の意図するところではない。むしろ、その趣旨は『プログラム』を基にした派生物ないし集合著作物の頒布を管理す る権利を行使するということにある。

つまり、パッチとしてオリジナルのGPLソフトウェアから完全に切り離された部分に関しては、GPLが適用されないわけである。ただし、そのパッチをGPLソフトウェアに適用するためには、そのパッチはGPL互換のライセンス(例えばBSDライセンスなど)でリリースしなければならない。そして、それをオリジナルのGPLソフトウェアと合体した時点でGPLが適用される。つまり、

GPLソフトウェア + BSDLパッチ = 改変されたGPLソフトウェア

という関係が成り立つわけである。従って、件のGoogleパッチがBSDLでリリースされているのは、一切問題はないというわけであり、Googleパッチに含まれるソースコードはBSDライセンスで利用することが可能である。

なぜ上記のような条項がGPLに盛り込まれているのか?と疑問を持たれることだろう。もし上記の条項がなければ、全ての変更はGPLを適用したソフトウェアで行わなければならず、従って他のライセンスでリリースされた優秀なソフトウェアやライブラリをGPLソフトウェアと組み合わせて利用することが出来ないという事態になってしまう。例えそれがFSFが作成した他のライセンス、例えばLGPLなどを適用したソフトウェアであっても!である。上記の条項があれば、ライセンス上は安全に他のGPL互換のライセンス(BSDライセンスなど)のソフトウェアとGPLライセンスのソフトウェアを組み合わせて別のソフトウェアを開発することが可能になる。

まったくもってややこしい話であるが、オープンソースソフトウェアに携わる人間としてライセンスの組み合わせは避けて通ることが出来ない問題であり、数あるオープンソースライセンスの中でも最もシェアが多いのはGPLなので、GPLの互換性に関する知識は身につけておく必要があるだろう。GPLが嫌いな人は「GPL汚染」などと揶揄してとかくGPLソフトウェアに対して脊髄反射的な嫌悪を示すことが多いのだが、それはきっと未知なるものに畏怖の念を抱くのは人間の性だからであり、しっかりライセンスを読んでよく理解すれば何も恐れる必要はないのである。

2009-10-28

MySQLerのTwitterアカウントまとめ。

松信氏の、

MyISAMとInnoDBのどちらを使うべきか
Twitterで話題になってたので簡単にまとめました。

というエントリが人気を博しているが、松信氏が言うように最近はTwitterでMySQL関連の話題も結構増えてきているように思う。Twitterの流行の勢いは凄まじく、今は右を向いても左を向いてもTwitter、寝ても覚めてもTwitter、猫も杓子もTwitterという雰囲気である。従ってMySQLもTwitterで盛り上がるのは当然の成り行きというもであるし、Twitterを活用しない手はない。

しかしMySQL関連の話で盛り上がると言っても「じゃあ誰をフォローすれば話に入れるんだよ?!」と多くの皆さんは疑問に思われることだろう。そこで、今日はMySQL関連のTwitterアカウントを独断と偏見と愛と勇気と努力をもって紹介する。MySQLの情報が欲しい人、もしくは話題の輪に入ってみたい人はぜひフォローして頂きたい。

まずはオフィシャルなアカウント関係から。オフィシャルなアカウントメッセージを一方的に発信するだけなので、話題に入るのではなく、情報源として、つまりRT(Re−Tweet)の対象として活用して頂きたい。

@mysql

基本中の基本。新しいリリースやWebinarの告知などが行われる。特にバージョンアップによる新機能の追加は、話のネタには持ってこいなのでMySQLerは必ずフォローしよう。

@mysql_jp

MySQL公式日本語アカウント。国内で行われるイベントやセミナーの告知とかがされる模様。2009年11月13日オープン!

@planetmysql_jp

こちらもMySQLerフォロー必須のアカウントである。コレはPlanet MySQL日本語版のフィードを呟くボットアカウントで、Planet MySQL日本語版に登録されているブログに記事が投稿される度にフィードを読み取って呟いてくれる。ブログ記事にツッコミを入れたりコメントしたり友人に広めたりするのに持ってこいだろう。

なお、MySQL関連のブログを書いている人は是非Planet MySQLに登録しよう。ブログは見る人が居てナンボであるが、Planet MySQLに登録することでより多くの人に見て貰える機会が増えるからである。MySQLブロガーがPlanet MySQLに登録し、MySQLer全員がそのRSSを購読したり@planetmysql_jpをフォローすれば品質の高い情報交換が出来るようになるだろう。

関連リンク

@planetmysql

こちらはPlanet MySQL英語版のボットアカウントである。英語が堪能なら是非こちらのアカウントもフォローしよう。英語圏におけるMySQLブログ記事の投稿数は相当なものであり、非常に質の高い情報が飛び交っている。英語の練習にもどうぞ。

関連リンク

では続いて日本人MySQLerのアカウントを紹介しよう。友好的な人が多いので、気軽にフォローして突っ込んでみて頂きたい。

@tmtms

言わずと知れたとみた まさひろ氏。MyNAの会長にして日本最古参MySQLerのひとり。MySQL徹底入門の著者、MySQLにおける日本語文字コードの初期実装、なおかつ超^128重要なモジュールであるMySQL/Rubyの開発者としても知られる偉人である。(しかし本人は奇策・・・もとい気さくなひと)Rubykaigi 2009では「MySQL/Ruby終了のお知らせ」という楽しいプレゼンをして話題を呼んだ。これからはPure-Ruby実装であるRuby/MySQLを継続されるそうなので頑張って頂きたい。


関連リンク

@sakaik

MyNAのMLでおなじみの坂井氏。MySQL 徹底入門 第2版や、その他数多くのMySQL関連書籍の共著者として知られる。

関連リンク

@ikdttr

MySQLにおいて日本語フルテキストインデックスを使った検索を可能とする「Sennaストレージエンジン」の開発者である池田氏。最近はMySQL 5.1対応版の開発に忙しいらしい。早くでないかと心待ちにする毎日である。池田氏をフォローしたら「リリースマダー?」と呟くのを忘れてはならない。

関連リンク

@hirohama

日本におけるMySQL Clusterの第一人者にして実力者の廣濱氏。カメラ好き、ガジェット好き、女好き^H^H^H^H。MySQL Clusterについて語ることの出来る貴重な人材である。

関連リンク

@kazuho

天才エンジニアとして国際的な評価も高いサイボウズ・ラボの奥一穂氏。Q4Mストレージエンジン、Pacificドライバなど秀逸なソフトウェアを世に送り出している。ツッコミも的確で示唆的である。しかしそれでいて茶目っ気を忘れないというのが心憎い。

関連リンク

@yonekawa

サイボウズ株式会社の米川氏。サイボウズはMySQLを利用するプロプラエタリソフトウェアの代表格である。

関連リンク

@sh2nd

OracleおよびInnoDBのエキスパート平塚氏。ブログでは度々気合いの入ったベンチマークなどをしてくれるのでwktk度高し。Rethink DBを真っ先に試すなど、人柱としても秀逸である。

関連リンク

@kentokushiba

スパイダーマンこと斯波氏。SPIDERストレージエンジンの開発者として有名である。最近はVertical Partitioningエンジン(カラムごとにパーティショニングをするタイプのストレージエンジン)の開発も精力的に行っている。

関連リンク

@kazeburo

大規模分散野郎Aチーム。Mixiの長野氏。Mixiのインフラを支える職人的DBAである。

関連リンク

@tmaesaka

Mixiの前坂氏。Drizzleやmemcachedなどのプロジェクトにおいて精力的に活動している。長きにわたりニュージーランドに在住しているため英語はペラペラである。最近はTokyo Cabinetにデータを格納するDrizzle用ストレージエンジンであるBlitzDBの開発に勤しんでいる。

関連リンク

@stanaka

とあるはてな社員こと田中氏。はてなを果てしなくスケーリング(注:ダジャレではありません。)

関連リンク

@tokuhirom

えとらぼ松野氏。だまってコードを書く人。

関連リンク

@hirose31

えとらぼのひろせまさあき氏。ブログのネタはいつも秀逸。

関連リンク

@ichii386


GREEの一井氏。InnoDBラブなMySQLerが多い中で異色のMyISAMラヴ!!な逸材。一井氏曰く、分析計の処理にはMyISAMの取り回しの手軽さが便利とのこと。


関連リンク



お次はMySQLの中の人。まずは日本人から。

@matsunobu

言わずと知れたMySQLのコンサルタント松信氏。数多くの書籍を執筆し、印税でウハウハしているMySQLの普及に大きく貢献している。最近受けたOkyuu.comのインタビュー記事では、「夢はエンジニアに強い影響を与える本を書くこと」と述べているのは感心する志である。この調子でこれからも頑張って頂きたい。

関連リンク


@rkajiyama

トレーナーから技術支援まで幅広くこなすタフガイ梶山氏。日本語の(Webを含む)セミナーやイベントではまず梶山氏が登場するので、ご存じの方も多いのではないだろうか。APAC地域担当であるため、かなりの期間を海外で過ごしている。

@meijik

同じMySQLサポートエンジニアにしてキムラデービー代表の木村氏。カレーが大好きで、ランチはカレー率が非常に高い。ブログにもカレーの記事が満載である。たまにDB Magazine等の雑誌に記事を投稿している。また、OSS RDBMSとしてはMySQLだけでなくFirebird関連の活動も活発に行っている。現在Firebird(徹底)入門書籍執筆中。

関連リンク


@nippondanji

いわゆる。フォロー歓迎。


続いて英語圏の中の人たち。英語が堪能ならぜひフォローを。

@brianaker

OSSの申し子Brian Aker氏。MySQLの各種ストレージエンジン(FEDERATED、ARCHIVE、Blackhole)、memcached、Drizzle、Gearmanなど、様々な実績を残している天才プログラマである。使用しているエディタはvim。MySQLに入社する条件として「絶対にノベルティのTシャツは着ない」というものを提示した頑固者。彼の語り口は非常にマイルドで、それでいて常に論理的である。Aker氏は尊子Richard Stallmanとディベートを行ったのだが、尊子よりも主張が論理的ですらあるように感じてしまうから驚きである。俺は二人とも大好きだ!

関連リンク

@stewartsmith

元MySQL Clusterの開発者にして、Drizzleの開発者Stewart Smith氏。写真ではオッサンっぽく見える場合もあるが実は結構若い。もちろん技術的にはエキスパートであり、彼のブログでは度々参考になる情報が掲載されているから見逃せない。

関連リンク

@kajarno

MySQLコミュニティ担当副社長のKaj Arno氏。MySQLのスポークスパーソン的存在。MySQL ABがコミュニティと良好な関係を保ってこられたのは彼の功績によるところが大きい。Bad Newsを魔法のようにGood Newsに変えるともっぱらの噂である。

関連リンク

@datacharmer

MySQLコミュニティ担当のGiuseppe Maxia氏。Datacharmerというのは彼のニックネーム。ジュゼッペ氏はMySQL::Sandboxの作者としても知られる。MySQL::Sandboxは相当便利なので使うべし!

関連リンク

@LenzGr

同じくMySQLコミュニティ担当のLenz Grimmer氏。Planet MySQLを管理しているのは彼である。


さらに中の人を紹介するが、以下はサポートチームの面々である。詳しい説明は省略する。

@maximuscub

俺の上司のLachlan。若くてマッチョなオーストラリア人。

@adamtdixon

APAC地区でMySQL Clusterを担当しているAdam。

@geertjanvdk

EMEA地区でMySQL Clusterを担当しているGeert。

@lathiat

見たまんまギークなTrent。かなりの早口なので、脳をオーバークロックしている疑いが持たれている。

@garypendergast

長期休暇取得中のGary。今はイタリアを放浪しているらしい。しかし仕事はチョッパ。


以下はその他の英語圏のMySQL関連アカウント。

@jzawodn

誉れ高き名著「High Performance MySQL」の著者、Jeremy Zawodny氏。元米Yahoo!のDBA。MySQLのレプリケーションで参照系の負荷を分散できる!ということを、実際のシステムで証明して見せたのは彼が最初ではないだろうか。

関連リンク

@martenmickos

元MySQL ABのCEO、Marten Mickos氏。MySQLは技術者集団だが、Mickos氏は経営のプロ。惜しい人物を放出したものである。

@launchpad_net

MySQLの公開リポジトリをホスティングしているLaunchpadの公式アカウント。

関連リンク

@Kickfire

MySQLを用いたDWHアプライアンスを販売している米Kickfire社の公式アカウント。KickfireはDWH用のストレージエンジンであるが、興味深いのは「SQLチップ」なるものを用いた専用のハードウェアで動作するるところ。汎用CPUでは達成できない性能を叩き出す。

関連リンク

@webyog

MySQLのGUIを販売するWebyog社のアカウント。

関連リンク

@Percona

MySQL Performance Blogでお馴染みのPercona社のアカウント。InnoDBの達人である木下氏が所属する会社でもある。(木下氏はPercona社にてXtraDBやXtraBackupの開発に勤しんでいる。オトコ的には木下氏にも呟いて貰いたいところである。)

関連リンク

というわけで、思いつくままにMySQLerなTwitterアカウントを並べてみたが、是非皆さんも彼らをフォローしてみて頂きたい。データベースを開発や運用でどう上手に使いこなすかということは、システム屋ないしはWeb系のエンジニアにとって非常に重要な課題である。Twitterを活用して情報を仕入れたりディスカッションに参加したりして、ぜひスキルアップに役立てて貰いたいものである。ここに挙げたアカウントはほんの一部であることを断っておく。実際にはまだまだこんなものではなくもっと大勢の優秀なMySQLerが存在する。もし、「この人が抜けてるだろ!」とか「俺も載せろ!」という方がいらっしゃったら、Twitterで@nippondanjiへこっそりとダイレクトメッセージを送って頂きたい。

一家に一冊。あのオプションなんだっけ?と思った時のために備えて。- #書評_ - MySQL全機能バイブル

MySQL全機能バイブル ~現場で役立つAtoZ~著者鈴木啓修様より献本御礼。(←一度言ってみたかったw)

本書は鈴木氏の前著である「MySQL全機能リファレンス」からのアップデートであるが、この度は最新バージョンであるMySQL 5.1対応になっての登場である。

今の時代、一家に一台テレビがあるように、はたまたパソコンがあるように、いやいや冷蔵庫があるように、一家に一冊本書があってもいいのではなかろうか。MySQLがオフィシャルに提供しているリファレンスマニュアルを除いて、MySQLをここまで網羅的に解説している書籍を私は知らない。その網羅性は目次だけで13ページも費やしていることからも、容易に想像出来ることだろう。

もくじを見ただけでもその網羅性がよく分かるだろう。このもくじを書いただけで既に腕がつりそうである。

Chapter 01 イントロダクション
■■ 概要
1-01 MySQL™とは
1-02 MySQLの概要
1-03 データベースシステムの構造
1-04 ストレージエンジン
Chapter 02 MySQLの内部構造
■■ プロセスとメモリ構造
2-01 プロセス構造
2-02 メモリ構造
■■ 問い合わせ処理
2-03 問い合わせ処理
2-04 プランナ
2-05 MyISAMのエクゼキュータ処理
■■ データベースディレクトリの構造
2-06 データベースディレクトリの構造
■■ テーブルの構造
2-07 MyISAM型
2-08 InnoDB型
■■ トランザクションの隔離レベル
2-09 トランザクションの隔離レベル
■■ INSERT DELAYED文
2-10 INSERT DELAYED文
■■ クエリキャッシュ(Query Cache)
2-11 クエリキャッシュ(Query Cache)
Chapter 03 MySQLのインストール
3-01 インストール準備
3-02 インストール
Chapter 04 MySQLサーバ管理
■■ イントロダクション
4-01 MySQLサーバ管理
■■ 初期設定
4-02 初期設定
■■ サーバの起動/停止
4-03 MySQLサーバの起動と停止
4-04 MySQLサーバの起動
4-05 MySQLサーバの停止
4-06 MySQLサーバをデーモンとして起動する
■■ データベースユーザ管理
4-07 MySQLにおけるデータベースユーザの概念
4-08 データベースユーザの管理
■■ システム変数の設定
4-09 システム変数の設定
4-10 サーバの動作に関するシステム変数
4-11 通信関連のシステム変数
4-12 問い合わせ処理に関するシステム変数
4-13 ストレージエンジン関連のシステム変数
4-14 ログ関連のシステム変数
4-15 表示や文字コードに関連するシステム変数
4-16 SQL_MODE
4-17 レプリケーション関連のシステム変数
4-18 その他のシステム変数
■■ ストレージエンジン
4-19 MyISAM型
4-20 InnoDB型
4-21 MEMORY型(旧 HEAP型)
4-22 パーティション
■■ ログ
4-23 ログファイル
4-24 バイナリログ(binary log)
4-25 スロークエリのログ(slow query log)
4-26 一般クエリログ(general query log)
■■ データベースのダンプ/リストア
4-27 データベースのダンプ/リストア(再構築)
4-28 ファイル群のコピーによるダンプ/リストア
4-29 mysqldumpによるダンプ/リストア
■■ 管理ツール
4-30 mysqladminとは
4-31 データベースの作成/削除
4-32 サーバの情報表示
4-33 FLOSH/RELOAD
4-34 パスワードの変更
4-35 スレーブ機能の開始/停止
4-36 mysqlcheck
■■ 文字コード
4-37 MySQLのサポートする文字コード
4-38 文字コードの設定と確認
■■ レプリケーション
4-39 レプリケーションとは
4-40 MySQLにおけるレプリケーションの仕組み
4-41 レプリケーションの設定
4-42 運用/管理
■■ クエリキャッシュ
4-43 クエリキャッシュ(Query Cache)
Chapter 05 mysqlの使い方
■■ mysqlの使い方
5-01 mysqlの使い方
■■ mysqlの起動オプション
5-02 MySQLサーバとの接続と切断
5-03 表示と結果出力
5-04 バッチ処理とSQL文の実行
5-05 実行制御
■■ mysqlのメタコマンド
5-06 再接続と切断
5-07 表示の制御
5-08 バッチファイルの処理,および結果のファイル出力
5-09 SQL文の編集と表示
5-10 プロンプト
5-11 接続中のセッション情報を表示
Chapter 06 SQL
■■ SQL
6-01 SQL文一覧
6-02 語彙
■■ データベースの作成/削除/接続
6-03 データベースの作成 CREATE DATABASE
6-04 データベースの削除 DROP DATABASE
6-05 データベースの属性変更 ALTER DATABASE
6-06 データベースの一覧表示 SHOW DATABASES
6-07 データベースへの接続 USE
■■ テーブルの作成/削除
6-08 テーブルの作成 CREATE TABLE
6-09 テーブルの削除 DROP TABLE
■■ テーブルの情報表示
6-10 テーブル定義(テーブルスキーマ)の表示 SHOW CREATE TABLE
6-11 列の属性を表示 SHOW COLUMNS FROM/SHOW FIELDS FROM/DESCRIBE/DESC
6-12 テーブルの一覧表示 SHOW TABLES
6-13 テーブルの情報表示 SHOW TALBE STATUS
■■ テーブルの属性変更
6-14 テーブル属性の変更 ALTER TABLE
6-15 列の追加と削除 ALTER TABLE ADD COLUMN/ALTER TABLE DROP COLUMN
6-16 インデックスの追加と削除 ALTER TABLE ADD INDEX|CREATE INDEX/ALTER TABLE DROP INDEX|DROP INDEX
6-17 主キーの追加と削除 ALTER TABLE ADD PRIMARY KEY/ALTER TABLE DROP PRIMARY KEY
6-18 一意性制約の追加 ALTER TABLE ADD UNIQUE
6-19 外部キー制約の追加と削除 ALTER TABLE ADD FOREIGN KEY/ALTER TABLE DROP FOREIGN KEY
6-20 デフォルト値の設定と削除 ALTER TABLE ALTER SET DEFAULT/ALTER TABLE ALTER DROP DEFAULT
6-21 列定義、列名の変更 ALTER TABLE MODIFY COLUMN/ALTER TABLE CHANGE COLUMN
6-22 テーブル名の変更 ALTER TABLE RENAME
6-23 テーブル名の変更 RENAME TABLE
■■ データベースユーザの作成と削除
6-24 データベースユーザの作成と削除 CREATE USER/DROP USER
■■ データベースユーザの管理
6-25 データベースユーザの権限設定と削除 GRANT/REVOKE
6-26 データベースユーザの権限表示 SHOW GRANTS
■■ データの挿入
6-27 データの挿入 INSERT
6-28 データの挿入 REPLACE
■■ SELECT
6-29 データの検索 SELECT
6-30 重複する行を削除 DISTINCT
6-31 FROM句
6-32 テーブル結合 CROSS JOIN/INNER JOIN/OUTER JOIN
6-33 WHERE句
6-34 グループ化 GROUP BY, HAVING
6-35 検索結果の並び替え ORDER BY
6-36 検索結果の出力範囲を指定 LIMIT, OFFSET
6-37 排他的六句と共有ロック FOR UPDATE/LOCK IN SHARE MODE
6-38 問い合わせの結合 UNION
6-39 副問い合わせ
■■ データの更新
6-40 データの更新 UPDATE
■■ データの削除
6-41 データの削除 DELETE
6-42 全データの削除 TRUNCATE
■■ 式や関数の実行
6-43 式や関数の実行 DO
■■ プリペアードステートメント
6-44 プリペアードステートメントの準備、実行、削除 PREPARE/EXECUTE/DEALLOCATE PREPARE
■■ 問い合わせ計画の表示
6-45 問い合わせ計画の表示 EXPLAIN
■■ ストアドプロシージャ・ストアドファンクション
6-46 ストアドプロシージャ・ストアドファンクションの定義表示 SHOW CREATE PROCEDURE/SHOW CREATE FUNCTION
6-47 ストアドプロシージャ・ストアドファンクションの状態表示 SHOW PROCEDURE STATUS/SHOW FUNCTION STATUS
■■ インデックスの表示
6-48 インデックスの表示 SHOW INDEX/SHOW KEYS
■■ インデックス情報の更新
6-49 インデックス情報の更新 ANALYZE TABLE
■■ ビュー
6-50 ビューの作成、変更、削除 CREATE VIEW/ALTER VIEW/DROP VIEW
6-51 ビューの定義表示 SHOW CREATE VIEW
■■ トリガ
6-52 トリガの定義、変更、削除 CREATE TRIGGER/ALTER TRIGGER/DROP TRIGGER
6-53 トリガの定義表示 SHOW TRIGGERS
■■ テーブルの最適化
6-54 テーブルの最適化 OPTIMIZE TABLE
■■ テーブルの検査と修復
6-55 テーブルの検査 CHECK TABLE
6-56 テーブルの修復 REPAIR TABLE
■■ トランザクション
6-57 トランザクション BEGIN|START TRANSACTION/COMMIT/ROLLBACK
6-58 セーブポイントの設定とロールバック SAVEPOINT/ROLLBACK TO SAVEPOINT
6-59 トランザクションの分離レベル設定 SET TRANSACTION ISOLATION LEVEL
■■ ロック
6-60 テーブルのロックと解除 LOCK TABLES/UNLOCK TABLES
■■ テーブルデータのインポートとエクスポート
6-61 テーブルデータのインポート LOAD DATA INFILE
6-62 テーブルデータのエクスポート SELECT INTO OUTFILE/SELECT INTO DUMPFILE
■■ テーブルのバックアップとリストア
6-63 テーブルのバックアップ BACKUP TABLE
6-64 テーブルのリストア RESTORE TABLE
■■ ログの管理
6-65 ログの切り換え FLUSH LOGS
6-66 バイナリログ一覧表示 SHOW BINARY LOGS/SHOW MASTER LOGS
6-67 バイナリログの内容表示 SHOW BINLOG EVENTS
6-68 バイナリログの全削除 RESET MASTER
6-69 バイナリログの削除 PURGE MASTER LOGS
■■ サーバの制御と状態表示
6-70 スレッドの情報表示とKILL SHOW PROCESSLIST/KILL
6-71 システム変数の変更 SET|SET OPTION
6-72 システム変数の表示 SHOW VARIABLES
6-73 データベースサーバの状態表示 SHOW STATUS
6-74 各種情報やログのリセット FLUSH
6-75 権限テーブルの再読込み FLUSH PRIVILEGES
6-76 クエリキャッシュの出フラグメント FLUSH QUERY CACHE
6-77 テーブルのクローズ FLUSH TABLES|FLUSH TABLE/FLUSH TABLES WITH READ LOCK
6-78 ステータス情報のリセット FLUSH STATUS
6-79 問い合わせ実行回数のリセット FLUSH USER_RESOURCES
■■ レプリケーション
6-80 レプリケーションに関するスレッドの状態表示 SHOW PROCESSLIST
6-81 マスターサーバの状態表示 SHOW MASTER STATUS
6-82 接続しているスレーブの一覧表示 SHOW SLAVE HOSTS
6-83 スレーブ機能の起動と停止 START SLAVE (SLAVE START) / STOP SLAVE (SLAVE STOP)
6-84 スレーブの状態表示 SHOW SLAVE STATUS
6-85 スレーブ機能のリセット RESET SLAVE
6-86 マスターサーバの変更 CHANGE MASTER
Chapter 07 データ型、演算子と関数
■■ データ型
7-01 MySQLがサポートするデータ型
7-02 数値データ型
7-03 文字データ型
7-04 ENUM型、SET型
7-05 BLOB(BINARY LARGE OBJECT)型
7-06 日付/時刻データ型
7-07 ビット型
■■ 演算子
7-08 MySQLのサポートする演算子
7-09 論理演算子
7-10 比較演算子
7-11 算術演算子
7-12 日付/時刻演算子
7-13 COLUMNパターンマッチング
■■ 関数
7-14 MySQLがサポートする関数
7-15 算術関数
7-16 集約関数
7-17 文字列関数
7-18 日付/時刻関数
7-19 型変換関数
7-20 その他の関数
Chapter 08 ストアドプロシージャ・ストアドファンクション
■■ 概要
8-01 ストアドプロシージャ・ストアドファンクションとは
8-02 ストアドプロシージャ・ストアドファンクションの定義と実行、削除
■■ プログラミングの基本
8-03 ローカル変数宣言と値の代入
8-04 SELECT INTO文
■■ 制御構造
8-05 条件分岐と場合分け
8-06 ループ処理
8-07 ハンドラー
■■ カーソル
8-08 カーソル
8-09 カーソル変数の宣言とオープン、クローズ DECLARE CURSOR FOR/OPEN/CLOSE
8-10 FETCH文によるカーソル行の取得 FETCH
8-11 カーソルを使った例

この本は、とても簡潔な(悪い言い方をすると淡々とした)文体で書き進められている。リファレンスなので淡々としているのは当然と言えば当然なのであるが、それでいて説明が明快なのは感心するところである。しかし本書の真の価値は文章ではないと断言する!本書を手にとって少しめくればすぐに気付くであろう。その図表の多さに。

そう、この本の真の価値は図表にある。文章による説明は必要最低限であるのだが、その代わり豊富な図表が補って余りあるぐらい雄弁にMySQLの各種機能を説明してくれるのである。文章をいちいち読むのではなく、図表で素早く内容を理解できるというのは、リファレンス本にとって至上命題の一つであろう。また、図表以外に目をひくのがコマンドやSQL文の実行例の多さである。各種機能の説明には必ずと言って良いほどSQLやコマンドの実行結果が掲載されている。説明を読んだだけではちょっとピンと来ないな・・・と思うような機能であっても、実行例を見れば一目瞭然という寸法である。

本書の内容を改めて見てみると、MySQLには膨大な機能があるんだなということに気付く。もちろん本書ではカバーされていない機能もあるが、それにしても膨大な機能である。(MySQLは高速だが機能が少ないと言う定説を疑いたくなるぐらいである。)その膨大な機能の説明を成し遂げた鈴木氏の努力は、並大抵のものではないと言えよう。

ちなみに、本書の最後には「参考書籍」が紹介されているのだが、その中には私(つまりこのブログの筆者)が執筆した出版予定の書籍(仮題:MySQLエキスパートトラブルシューティングガイド)が紹介されている。まだ出版されていない(鈴木氏に原稿を見せたということもない)書籍を「参考書籍」として紹介するというのは前代未聞の所業ではないだろうかと思うのだが、鈴木氏曰く「参考にした書籍ではなく、参考になる書籍という意味で掲載するからOK!」ということらしい。
※この点については鈴木氏本人より「誤解を招く表現」との指摘があったので修正させて頂く。この文面からすると鈴木氏は架空の内容を参考にしたように読み取れるがそうではない。鈴木氏は次の2点を見て「この書籍なら参考にするに値する」と判断して下さったそう。
オモシロおかしく書いたつもりが、思わぬ茶々になってしまって面目ないです>鈴木氏
MySQLエキスパートトラブルシューティングガイド(仮題)では、本書で取り上げられていない機能、例えばSHOW INNODB STATUSの見方やINFORMATION_SCHEMA、プロファイリング、トレースファイル、DTraceプローブなども解説するので乞うご期待。

そんなわけで、本書は網羅的で図表や実行例を駆使してとても分かり易いMySQLのリファレンスであり、初心者から上級者まで幅広い方々におすすめである。

2009-10-26

Snow Leopardにしてから困っていたこと=ファンクションキーが効かなくなる問題・・・が解決!

既に知って居るひともたくさん居るだろうが、自分がSnow Leopardを利用し始めてから困っていたことが解決したのでこのブログでも紹介しておこう。OSをLeopardからSnow Leopardにアップグレードしてから、「作業中に突然ファンクションキーが効かなくなる」という事態が度々発生して困っていた。何しろSpacesやExpose、Dash Boardはファンクションキーで呼び出すようにしているので、突然それらが使えなくなると不便で仕方がない。OSを再起動すると直っていたので度々OSを再起動する羽目になっていたから最悪である。(何故かブラウザをFirefoxやChromeからSafariにすると発生頻度が下がっていたのでSafariを利用するという回避策をとっていたのだが、これからはそれも不要である!アップルの陰謀かと思ったけど違うようだった。疑って悪かったよ>アップル)

で、その回避策とはズバリDockを再起動することだ。

どうやらショートカットキーの類はDock.appが一括して仕切っているようなので、Dock.appだけを再起動してやればOSごと再起動しなくても済むわけである。ちなみに、Dockを再起動しても他の作業に影響は出ない。なので、とりあえずファンクションキーの動作がおかしくなったら次のコマンドでDock.appを再起動してみるといいだろう。

shell> killall Dock

MySQL Clusterソースコード探検隊!

これまで「MySQL Clusterの進化とその構造について」および「NDBカーネルブロックの種類」について説明した。今日はその続きとしてMySQL Clusterのソースコードについて紹介しようと思う。シグナルを交換し合うマルチプルステートマシンは間違いなくこれからの時代にフィットするアーキテクチャなので、MySQL Clusterに興味を持たれた方が「膨大なMySQL Clusterのソースコードを探検する場合にどの入り口から入ればいいのか」ということを判断する一助になればと思う。とりとめなく書いてるのであんまりまとまってないかも知れないが、その点は容赦して頂きたい。

まず、ソースコードの入手方法であるが、これは最新のソースツリーをBazaarで入手する方法と、MySQLのWebページからダウンロードする方法の2つがある。Bazaarで入手するには、次のコマンドを実行すれば良い。(Bazaarを事前にインストールしておこう。)

shell> bzr branch lp:~mysql/mysql-server/mysql-cluster-7.0

するとカレントディレクトリ以下にソースコードがコピーされる。結構時間がかかるので注意しよう。

MySQLのWebページからダウンロードするには、次のページをブラウザでアクセスしよう。

http://dev.mysql.com/downloads/cluster.html

するとプラットフォームの選択メニューが出てくるので、ZIP形式のソースコードが欲しければWindowsを、TAR形式のものが欲しければLinuxを選択しよう。一番小さいファイルがソースコードである。ソースコードのファイルはmysql-cluster-gpl-VERSION.tar.gzというような名前になっている。

MySQL Clusterのソースコードが含まれる場所は次の2つである。

  • src-top-dir/storage/ndb
  • src-top-dir/sql

src-top-dirはソースコードのトップディレクトリ、つまりZIPまたはTARファイルを展開したときに作成されるディレクトリ(mysql-cluster-gpl-VERSIONというような名前のディレクトリ)のことである。

storage/ndbにはndbdやndb_mgmdといったコマンドのソースコードが収められている。つまりSQLノードを除く全てのコマンドのソースコードはここにある。一方、sqlディレクトリにはSQLノードのソースコードが格納されている。ファイル名はha_ndbcluster*。(*はワイルドカード。)ここは元々mysqldのソースコードが収められているディレクトリなので、そこに居候しているのである。(将来的にはstorage/ndbへ移動したいらしいが、タスクの優先順位は低くなかなかそうならない。)肝心のNDBカーネルのソースコードはstorage/ndb以下にあるのでこちらを中心に説明する。ha_ndbcluster*には、ストレージエンジンとしてMySQL Clusterへアクセスする際に必要なソースコード、つまりmysqldがNDB APIを通じてNDBにアクセスするためのロジックが記述されているので、ストレージエンジンAPIおよびNDB API興味のある人は覗いて見るといいだろう。

ここからは、NDBカーネルのソースコードを見る際のポイントについて列挙しよう。

  • NDBカーネルのソースコードの位置は、storage/ndb/src/kernelである。main()関数を含むmain.cppはこのディレクトリである。ndbdの初期化プロセスについて知りたい場合には、main.cppを見よう。
  • ヘッダファイル類はstorage/ndb/include/kernel配下に収められている。C++のヘッダファイルはstorage/ndb/src/kernel以下にも含まれているが、共通のヘッダファイルはこちらのディレクトリに含まれているので注意しよう。
  • storage/ndb/src/kernel/vmには、PLEX仮想実行環境のソースコードが含まれている。最も重要なのはSimulatedBlock.[c|h]ppで、ここで定義されているSimulatedBLockクラスはこれらは全てのブロックの親クラスとなる。つまり、NDBDカーネル内の各ブロックは、SimulatedBlockクラスを継承しているのである。また、SimulatedBlockが交換するメッセージは、VMSignal.[c|h]ppで定義されている。(シグナルを表すクラスはSignalである。)面白いことに、SimulatedBlockは他のあらゆるカーネルブロックへ、sendSignal()関数を通じてシグナルを送信することが出来る。同じプロセス内のブロックであろうが、他のホストで動作しているブロックであろうが、同じ方法(関数)でシグナルを送信することが出来るのである。
  • storage/ndb/src/kernel/blocksには各ブロックのソースコードが含まれている。ブロックごとにサブディレクトリに分かれているので見易いだろう。ここで定義されている各カーネルブロックは、上記の通りSimulatedBlockクラスを継承している。各カーネルブロックの動作を定義しているこのディレクトリは、NDBのソースコードの心臓部と言っていいだろう。
  • storage/ndb/include/kernel/BlockNumbers.hには、各カーネルブロックのIDが定義されている。ブロック番号は16ビット符号無し整数なのだが、同じく16ビット符号無し整数であるノードIDと組み合わせることで、32ビットの符号無し整数としてクラスタ全体を通じたID(BlockReference)を合成することが出来る。storage/ndb/include/kernel/RefConvert.hppにはノードIDとブロック番号からBlockReferenceへ変換するロジックおよびその逆が定義されている。(ただのビット演算だけどね!)
  • storage/ndb/src/kernel/SimBlockList.cppには、作成したカーネルブロックのインスタンス化と、そのインスタンスへのポインタをリストにして保管しておくためのロジックが記述されている。ただし、NDBカーネルの各ブロックはインスタンス化された段階ではまだ初期化されず、その後STTORシグナルを受け取った時点で初期化が始まる点には注意したい。
  • storage/ndb/include/kernel/GlobalSignalNumbers.hでは、各シグナルにつけられた番号が記述されている。実に700種類以上のシグナルが定義されている!(2009年10月現在)
  • storage/ndb/include/kernel/signaldataディレクトリには、シグナルにおいて送信されるデータ(ペイロード)を定義するクラスのソースコードが格納されている。シグナルが送信するデータはフリーフォーマット(単なるワード列)なので、頻繁に利用されるデータについてはその構造が定義されているのである。
  • storage/ndb/src/common/transporterディレクトリには、トランスポーターに関するソースコードが格納されている。トランスポーターとは、MySQL Clusterの各ノード同士が通信し合うための仮想的なインターフェイスである。これにより、通信する実際のプロトコル(TCP/IPなのかSCIなのか)に因らないロジックの記述が可能になる。
  • storage/ndb/src/mgmsrvディレクトリには、管理ノードのソースコードが格納されている。特に重要なのはstorage/ndb/src/mgmsrv/ConfigInfo.cppで、このファイルには各種設定パラメーターとそのデフォルト値に関する記述がなされている。また、storage/ndb/src/mgmclientにはndb_mgmコマンドのソースコードが、storage/ndb/src/mgmapiにはNDB MGM API(設定情報をやり取りするためのAPI)のソースコードが格納されている。
  • storage/ndb/src/ndbapiディレクトリには、NDB APIに関するソースコードが格納されている。
そんなわけでMySQL Clusterのソースコードのレイアウトについてとりとめもなく紹介してみた。「よし、ソースコードを見るか!」と思った時に参考にして頂けると幸いである。

2009-10-23

MySQL Clusterカーネルの中身を覗いてみよう。

MySQL Clusterのデータノードであるndbd(もしくはndbmtd)プロセスは、内部的にはマルチプルステートマシン(ブロック)がシグナル(もしくはメッセージ)を交換するという構造になっており、高い同時実行性を実現しているということについては前回述べた通りである。今日は、ndbd内部にどのようなカーネルブロックが存在するかということについて大まかに説明しよう。前回の話を踏まえて読んで頂ければ、何となくイメージだけでも掴めるのではないかと思う。まずは次の絵を見て頂きたい。これは俺の脳内から引っ張り出したndbdの構造のイメージ図である。




矢印はブロック同士の相関関係(シグナルの送受信など)を示すのだが、この絵に描かれているものは非常に省略されたものであり、実際にはもっと複雑に絡み合っているのだということを覚えておいて欲しい。例えばQMGRやDBDICTといったブロックは、他のブロック全てとシグナル交換をするのだが、それを全て描くと何が何だか分からなくなるので省いているわけである。もし全てを描いたなら、思わず「それ何てスパゲティ?」と叫んでしまうこと請け合いである。

というわけで、以下淡々と各ブロックについて簡単に説明しよう。MySQL Clusterの各ブロックは、いくつかのカテゴリに分類することが出来るので、以下ではそのカテゴリごとに説明している。

NDBカーネルを管理するブロック
  • CMVMI・・・Cluster Manager Virtual Machine Interfaceの略。OSへのリクエストを処理したり、ndb_mgmd(管理ノード)と通信をしてndbdの構成を決定する。
  • NDBCNTR・・・NDB CordiNaToRの略。NDBコントローラーか?と思ってしまいがちだが、コーディネーターの意味。役割はndbd起動時の初期化とシャットダウン。
  • QMGR・・・クラスタマネージャブロック。ハートビートを通じて各ブロックの状態を管理している。NDBカーネルの親玉的存在。
  • NDBFS・・・ファイルシステムへのI/Oを一手に引き受けるブロック。このブロックのおかげでファイルへの非同期I/Oが容易に実装できている。
ローカルノード(自ノード)のデータを管理するブロック。
  • DBLQH・・・ローカル・クエリ・ハンドラ。自ノードに対するトランザクションを処理する。MySQL Clusterのndbmtdでマルチスレッド化されたのはこのブロック。図を見れば分かると思うが、このブロックの負荷はかなり高い。(次いで負荷が高いのはDBTC)
  • DBACC・・・自ノードの主キーを管理するブロック。ACCはアクセスの意味。
  • DBTUP・・・データを管理するブロック。TUPはタプルの意味。
  • DBTUX・・・TUple indeXの略。OrderedIndexを管理する。
  • DBUTIL・・・トランザクション管理やデータ管理のための便利な機能が詰まったユーティリティブロック。
並列分散処理のためのブロック
  • DBDICT・・・ディクショナリブロック。テーブルやテーブルスペース、ログファイルのメタデータの管理を一手に引き受ける。SQLノードが直接アクセス出来るブロックである。
  • DBTC・・・Transaction Cordinatorの略。SQLノードからリクエストされたトランザクションの面倒を始まりから終わりまで面倒を見るブロックである。該当するデータが自ノードの担当でなければ、別のデータノードへ要求を送ったりする。
  • DBDIH・・・DIstribution Handlerの略。レプリカを管理し、どのフラグメント(パーティション)がどのノードに格納されているかについて責任を持つ。また、LCPGCPといった処理を行うのもこのノードである。
  • TRIX・・・TRansactions and IndeXesの略。このブロックは内部的なトリガとユニークインデックスを管理する。MySQL Clusterはデータが複数のノードに分散しているので、行の一意性を保証するのにはどうしても分割の対象となる主キーが必要となるため、サポートテーブルという別の内部テーブルが作成される。実テーブルと内部テーブルは、トリガによって同期されるというわけである。
ディスク型テーブル用のブロック
  • PGMAN・・・バッファページを管理するブロック。名前の由来はPaGe MANagerである。
  • TSMAN・・・テーブルスペースを管理するブロック。名前の由来はTableSpace MANagerである。
  • LGMAN・・・ログファイルグループを管理するブロック。名前の由来はLogfile Group MANagerである。
バックアップ関係
  • BACKUP・・・オンラインバックアップの実行。
  • RESTORE・・・取得したバックアップのリストア。ndb_restoreコマンドからデータを受け取ってリストアする。ndb_restoreコマンドは、一種のSQLノードとして動作する。
  • SUMA・・・SUbscription MAnager。MySQL Server(mysqld)へバイナリログの元になるデータを送信する。
以上がNDBカーネルブロックの概要である。

ブロック同士がシグナルを交換して実現しているのは「データベース管理システム」である。各カーネルブロックは、データベース管理システムに必要な機能の要素ひとつひとつを具現化したものであると考えられるので、どのようなブロックが存在するかということはデータベースエンジニアにとって興味深いものとなっているのではないだろうか。また、MySQL Clusterのログにはブロック名がたくさん登場するので、ブロックの役割について知っていればログを見る際に役立つはずである。次回は、MySQL Clusterのソースコードのレイアウトについて説明する予定である。