2009年12月31日木曜日

Save MySQL!

バラバラにECにメールを送っても、効果があるのか疑問でしたが、こんなサイトが立ち上がったようです。

http://helpmysql.org/

各国語のページがあり、日本語も一応あるので、『英語はちょっと…』という方も大丈夫。
是非、主旨をご理解の上ご協力できる方は署名をお願いします。

2009年12月18日金曜日

XtraDB 1周年

そういえば、XtraDBのリポジトリにcommitしだしてから先日丁度1周年になりましたので、
XtraDB1周年
ということになりました。「冒険家」の少ない日本では残念ながら効果を実感されているユーザーは少ないかも知れませんが、いつの日か急に吃驚してもらえるように来年も磨き続けていきます。

Plugin-1.0.6 ベースのXtraDBの調整は現在ほぼ終わっていて、テストが済み次第リリースされると思います。お楽しみに!
とはいえ、更新をサボっているうちに紹介すべき小ネタ新機能も溜まってきましたね。。。

2009年11月6日金曜日

XtraBackup Windows版

今回は、速報なので短いです。

「Linuxだけでたまたま動いていた感」のあるXtraBackupですが、私がいろいろ直しているうちに、最新revisionはWindowsでも動くようになったそうです!次のリリースではWindows版も出てくると思います。乞うご期待!!

「そうです」というのは、私はWindowsの開発環境を持っていないし良く分からないので、寄せられたスタックトレースだけを頼りに気合いで直しています。しかし、それで良く動いたものです。。。。

2009年10月9日金曜日

InnoDBの超高負荷更新処理安定性

最近は沢山CPUコアのある高速なサーバーとか高回転数のHDDが沢山付いたRAIDストレージとか、もの凄く更新系の負荷がかかるベンチマーク(「db_STRESS」 by Dimitriさん)とかがあるので、InnoDBの構成の更新系での様々な限界が見えてきています。

まぁ、現実的にそのような限界を突破する必要のあるシステムがあるかどうかは判りませんが、将来のためにも色々アイデアを加えてXtraDBを作成してきました。今、大幅な変更無しに実装できる範囲のオプションが揃ってきたので高負荷更新系処理のチューニングをXtraDBベースで一旦書き出してみます。

今回もサクサクとポイントだけ。
(IOスレッドを増やす とか、他でも語られている既知のものは省略します。)

今回のチューニングの方針は、 「mutexやrw_lockなどの競合をできるだけ避ける」 ということと 「あまり沢山溜めてはイケナイものを溜め込まない」 ということです。

まず、最大スループットを上げるために、更新系で競合を回避するポイントをいくつか。

"rseg->mutex" の競合:
ロールバックセグメントを増やしましょう。XtraDB には、innodb_extra_rsegments というオプションがあり、InnoDBの初期化の時に限り、指定数の追加ロールバックセグメントを作成できます。information_schema の INNODB_RSEG ビューで状況確認可能です。

"index->lock" の競合:
その索引全体に対するロックです。5.1のパーティション機能で分割することにより回避できるかも知れません。表定義時に "PARTITION BY HASH(xxxx) PARTITIONS 16" の様にします。db_STRESSの場合、パーティション化するのは HISTORY 表のみで良いでしょう。

"dict_operation_lock" の競合:
パーティションを利用すると多く発生するようです。tablespaceの空き領域を算出する処理がパーティション分増えてしまうのでしょうか。今回は空き領域表示の正確性よりも性能が大事なので、切ってしまいましょう(ぁ)。XtraDBの次バージョンで innodb_stats_update_need_lock0 を指定しましょう。動的パラメータなので、空き領域を正確に知りたいときは 1 に戻せます。


以上で db_STRESS のRW=1のスループットがかなり上がったと思います(…)。

あ、はい。どうやって競合を確認するか、ですね?
以前何処かでお話ししたかもしれませんが、少々乱暴な判断法ですが、SHOW INNODB STATUS を何回か実行して、SEMAPHORE セクションに沢山出てくる行を見て、ソースと照らし合わせて何の競合か判断します。結構、的を射た結論が得られます。

さて次はそのスループットを維持/安定化することを考えます。

忘れられがちなポイントを3つ挙げます。

古いダーティブロックを溜めすぎない
トランザクションログの許容量ぶんよりも古い更新はflushしないままにはしておけません。なので大量に溜め込んでいると、ある時突然大量のデータブロック書き込みが発生する場合があります。普段からコツコツ書き出して減らしてバランスを取る必要があります。
Plugin-1.0.4 から追加された innodb_adaptive_flushing かそれともこれを無効化して、XtraDB の "innodb_adaptive_checkpoint = estimate" を指定すると適切な量の書き出しをコンスタントにするようになります。どちらのオプションが最適かは、サーバーの性能と処理内容とその他設定のバランスに依存するようですので、試してみてください。
XtraDBだと SHOW INNODB STATUS の出力の LOGセクション に Max checkpoint age と Modified age が表示されるので容易に確認できます。

insert bufferを溜めすぎない:
InnoDBは主キー以外の索引列に対する変更は、insert bufferに挿入して整合性を取りながら、後で実際の変更を実施します。しかし、InnoDBは insert buffer が buffer pool の半分の大きさまで肥大化しないと本気で処理しないようです。XtraDB のオプション innodb_ibuf_active_contract = 1 でいつも本気で insert buffer を減らそうとします。

history listを溜めすぎない:
これが起こるのは相当更新の激しい処理です。ロールバックセグメントの中身に対する後処理が新しくエントリを発生するスピードに追いつかずに肥大化した状態かと思われます。ロールバックセグメントが巨大化してしまうと、処理が重くなります。
そのpurgeと言う後処理を専任で実行するスレッドをつくると言うアイデアもありますが、db_STRESS は1CPUのpurge threadではその他CPU全ての更新処理は受け止めきれないようです。
XtraDBの次のバージョンでは、このpurge threadにさらに子分のスレッドをつけて"purge力"を上げることができます。例えば innodb_use_purge_thread = 4 の様な感じで 親分1+子分3 の構成でpurgeするようになります。(この設定で16コアのマシン上の32セッションの並列処理に対応できました。)
苦し紛れの innodb_max_purge_lag 指定はもう必要無くなるのではないでしょうか?


以上です。
最後のpurge threadの効果を中心とした実際のデータは、近いうちに mysqlperformanceblog で見ることができると思います。

では、MySQLマニアの皆さんも快適なベンチマークライフを!
(検証用に急に良いマシンを借りれてしまったときに失敗せぬように!)

2009年9月9日水曜日

【注意】PowerPCのマルチプロセッサとInnoDB

多分、関係ある人にはクリティカルな内容なので、急いで報告します。

ここ2週間くらい、とある案件で頭を悩ませていました。
POWER5 の 8コア構成の IBM のサーバ(Linux)でMySQL(InnoDB)を利用すると、どのバージョンでも(ビルトインInnoDBでも、InnoDB Pluginでも、GCC atomic builtin を使わなくても)しばらくするとハングアップ/クラッシュするそうなのです。

紆余曲折ありましたが、どうも自分の仮説が正しそう(作ったパッチが効果ある模様)なので、先ほどバグレポートを報告しました。

All InnoDB (builtin and plugin) is unstable at PowerPC SMP server

簡単に言うと、InnoDBのコードはIntel CPUのSMPの仕様に依存した作りになっています。Intel系CPUのSMPでは、メモリへの書き込みは他のCPUのキャッシュにも自動的に影響して一貫性を保つのですが、PowerPCではCPU間のキャッシュの一貫性確保を明示的に行う必要があるのです。

結論から言うと、残念ながら、PowerPCのマルチプロセッサ構成でInnoDBを利用するのは危険。ということになります。

もう引き下がれない人や、既にハングアップに悩まされている人は、とりあえず当該レポートにアップロードしておいたパッチで InnoDB Plugin 1.0.3 を使ってみてください。ハングアップの可能性はかなり減る筈です。

-------
(2009/10/9 追記)
大幅に改善したものの、ハングアップの可能性がまだあるようです。
うーむ、__sync_synchronize() は sync になるようだが、store に対する memory barrier にはなってないのかも。
該当個所を asm volatile ("isync") に書き換えてみるか…(独り言)

-------
(2009/10/20 追記)
現在のパッチを同じバグレポートにアップロードしておきました。
動作は今のところ大丈夫そうです。

2009年8月9日日曜日

InnoDBの性能改善版

しばらく間があいてしまいました。

今回は、地味な話で少し遅れてしまった話題ですが、InnoDBの性能改善についてです。2009.4のMySQL UCの時点では「MySQL5.4よりも遅いんじゃないか?」と言われていた、XtraDB、5.0-highperf ですが、色々世界の皆様のパッチを参考に(いいとこ取り)して、且つ自分のパッチ(split_buf_pool_mutex)はXtraDBベースのlatching orderでちゃんと行儀良く(デバッグモードもちゃんと動作させる)書き直してデバッグして、環境(とチューニング[大事])によっては5.4よりも多少良い性能が出るようになっているはずです。(例 Performance improvements in Percona 5.0.83 and XtraDB : CPUコア数、RAIDの並列性能、データ量、処理内容、チューニング等々で性能差は全く変わるとは思います。)

さて、一部の方から「某Googleのv4パッチは移植しないのか?」の質問を偶にいただくのですが、個人的にはGoogleパッチはInnoDBを書き換え過ぎと思っています。また多分同じ目的で違うアプローチのもっと単純なパッチはある程度含めているのでv4まで見る必要はないかなと思っています。(v3以前からは、IOスレッドのハンドリングと、log_sys->mutex競合対策は採用させていただいています。)先日、初めて(!)googleパッチをビルドして動かしてみたのですが、そのままではビルドできないし、パラメータも外から変えられない(他にもパッチが必要なのか?)し、新オプションを有効にしたらかえって重くなるしで、かなり疑問を感じています。。。一般的にベンチマークの結果は実施法やデータ整理の仕方、見せ方で人によって大きく結果が違ってしまいます。難しいモノですね。。。というわけで、当面はv4パッチの変更点(多分ibufのcontractやmodified blockのflush周り)については採用する予定は個人的にはありません。納得のいかない方は「v4パッチのどの部分のInnoDBのどんな部分に対する何の変更はどう?」という形でご意見をいただけると幸いです。:-)

さて、試していただくには勿論最新のバイナリを利用していただいてもいいのですが(XtraDB 1.0.3-65.0.83-percona)、常にバグフィクスをしている(つもり)ので、できればソースからビルドしてもらえれば多分間違いは少ないかと思います。また今、ごく一部で話題のクラッシュリカバリが速くなるオプション(近日日本語で詳細に紹介(英語は不得意なので。。))も今時点でのバイナリには入っていません。
最新のソースを得るためにはBazaarが必要です。(本家MySQLでも利用しているので説明は省略(!))

(XtraDB)
> bzr branch lp:~percona-dev/percona-xtradb/extensions-1.0

(5.0.84-percona)
> bzr branch lp:~percona-dev/percona-patches/5.0.84

とすれば最新のパッチファイルが得られます。新しい本家バージョンに対するbranchがある場合は古い方のメンテナンスは止まっているので注意してください。

パッチの適用の仕方ですが、それぞれのディレクトリ直下には「series」というファイルがあってパッチの適用する順番が書かれています。([!]:XtraDBのseriesファイルの最後に「xtradb-dir.patch」という行がありますがこのパッチはビルトインのInnoDBとXtraDBを共存させようとするモノですが、まだ怪しい(し、私はまだ関知していないパッチ)のでこの行は削除してください

パッチは手で1個1個適用しても良いのですが、seriesファイルを利用して

(XtraDB)
innodb_plugin-1.0.3の場所で> (cd パッチの場所/extensions-1.0; cat `cat series`) | patch -p1
("xtradb-dir.patch" は series ファイルから削除しておくこと)

(5.0.84-percona)
mysql-5.0.84の場所で> (cd パッチの場所/5.0.84; cat `cat series`) | patch -p1


とすれば簡単かと。(MySQL-5.0のビルドの説明は省略。innodb-pluginのビルドの説明は、、、この辺でお願いします。。。)

では、この辺(XtraDBで追加されるオプション)を見て興味のあるところを試してみてください。サーバーにCPUが16個以上ある人やRAIDに数百万以上かけている方にはきっと特にご満足頂けると思います。。。

これら追加パラメータのチューニングについて一回全部「日本語で」触れた方がいいかも知れないですね。(いつか。。)

2009年5月30日土曜日

任意のテーブルの IMPORT TABLESPACE

MySQL の ALTER TABLE コマンドには、IMPORT TABLESPACE というコマンドがあります。InnoDBでは、innodb_file_per_table オプションを有効にしている場合に"クリーンな" .ibd ファイルのバックアップに差し替えることが出来ます。でもこれは色々制限があるので、利用していらっしゃる方は数少ないと思います。内部の構造/ID等が全く同じでなくてはいけないのでバックアップしたファイルをIMPORTできるようにするためには、ALTER TABLE コマンドによる内部的な表の再作成等もしてはいけないのです。

そこで、任意の表をIMPORTできるようにXtraDBを拡張してみました(innodb_expand_import)。(現在branchは https://code.launchpad.net/~percona-dev/percona-xtradb/expand-import です)
まだ、メインのbranchにはまだマージされていませんが、次のリリースには組み込まれるはずです。

さて、リンク先を見ていただければわかるのですが、まだ制限があります。 .ibd ファイルと元のCREATE TABLE文だけでは表と成すための情報が不足しているのです。『索引名と索引IDの対応』と『索引のroot page の場所』です。InnoDBは表、索引等を管理するための内部表を持っていてこれらの情報は SYS_INDEXES内部表に格納されているのでそれも元のInnoDBから抜き出してIMPORT時に利用する必要があります。

というわけで、このEXPORTにあたる対となる機能はXtraBackupに追加してみました(--exportオプション)。コピーしたトランザクションログとデータファイルを使ってリカバリーを行って利用可能なバックアップに変換する--prepareオプションと一緒に指定すると、insert buffer をちゃんと空にした"クリーンな" .ibd ファイルを索引情報を含んだ .exp ファイルも一緒に生成してくれます。

あとは、IMPORT先(要innodb_expand_import)で全く同じCREATE TABLE文で表を作成し、ALTER TABLE ... DISCARD TABLESPACEして、上記で生成された .ibd & .exp ファイルをその表の .frm ファイルと同じところに(アクセス権限に注意)置いて、ALTER TABLE ... IMPORT TABLESPACE するだけです。space_id, index_id, root page 位置の再登録などなど自動で変換してくれます。興味のある猛者はお試しください!

というわけで、興味の赴くままに書いていきますので、話の前提関係が多少滅茶苦茶ですが
(XtraDBって?XtraBackupって?などなど…)、書き続けていくうちに解決するでしょう。。。

ご挨拶

昨年末くらいからInnoDBの改造で生計を立てている者です。
流石に日本語で触れていないネタが溜まってきたので、まったり紹介していけたらと思っています。
よろしくです。