MySQLハッキングの 手 引 き 松 信 嘉 範 (MATSUNOBU Yoshinori) 日 本 MySQLユーザー 会 http://opendatabaselife.blogspot.com http://twitter.com/matsunobu 1
今 日 のテーマ MySQLのアーキテクチャ ソースコードの 入 手 とビルド 方 法 デバッグ 方 法 プラグイン 開 発 の 方 法 本 体 拡 張 の 方 法 本 家 へのコントリビュートの 方 法 2
自 己 紹 介 本 業 は MySQLコンサルタント パフォーマンスチューニング HA 等 たまにMySQL 開 発 案 件 を 行 なう 書 籍 / 連 載 現 場 で 使 えるMySQL 2006.3 Javaデータアクセス 実 践 講 座 2008.2 Linux-DBに 関 する 本 2009.9( 予 定 ) 新 連 載 Real World MySQL DBマガジン 10 月 くらいから そろそろ RDBMS 自 作 入 門 のような 本 に 挑 戦 しようかと 3
MySQLとは オープンソースのリレーショナルデータベース C/C++ 一 部 アセンブラで 実 装 現 在 提 供 されているバージョン 5.4 パフォーマンス 改 善 版 MySQL beta 5.1 最 新 の 安 定 版 (5.2/5.3は 欠 番 ) 5.0 安 定 版 4.1 安 定 版 4.0 安 定 版 (サポート 切 れ) マイナーリリースが 数 ヶ 月 程 度 のサイクルで 登 場 ソースコード およびプラットフォームごとのバイナリが 提 供 4
MySQLのアーキテクチャ 接 続 / 操 作 監 査 ログ (プラグイン) リスナー ( 固 定 ) 認 証 ロジック ( 固 定 ) login_connection() UDF (プラグイン) Information Schema (プラグイン) パーサ ( 固 定 ) オプティマイザ ( 固 定 ) mysql_parse() JOIN::optimize() 全 文 検 索 パーサ (プラグイン) 全 文 検 索 Index ( 固 定 ) レプリケーション /バイナリログ ( 固 定 ) テーブルアクセス/ジョイン ( 固 定 ) ストレージエンジン (プラグイン) JOIN::exec() Storage Engine API 5
さまざまな 特 徴 (1) 外 部 ライブラリには 極 力 依 存 しない 作 り STLとかboostとかも 使 っていない プラットフォーム 依 存 性 を 減 らすため OS 依 存 の 命 令 は my_xxxというラッパー 関 数 で 吸 収 Drizzleでは 方 針 が 逆 転 している STL ProtocolBuffer Gearman etc.. デバッグ 用 の 機 能 malloc/free pthread_*などはラッパーを 用 意 して 二 重 ロックや 不 正 アクセス 等 を 検 知 しやすくしている 主 要 関 数 へのIN/OUT 時 にトレースを 出 すようにしている Production 用 では 無 効 化 するように マクロで 制 御 している MySQL5.4 以 降 では Dtraceプローブが 埋 め 込 まれている 6
さまざまな 特 徴 (2) エンディアンフリー 基 本 的 にリトルエンディアンに 統 一 1 の2バイト 表 現 は0x01 00 通 信 プロトコルもエンディアンフリー 関 数 ポインタ サブクラスを 多 用 し 汎 用 性 を 上 げる オブジェクト 指 向 の 定 石 でもある ストレージエンジンAPIなどプラグインを 実 現 するために 重 要 SQL 関 数 ごとにサブクラス 1レコードの 処 理 ハンドラ 用 に 関 数 ポ インタ 等 実 行 速 度 重 視 のビルド 標 準 ビルドではRTTIを 無 効 化 この 影 響 で 実 行 時 にPASSWORD() 関 数 の 場 合 にはこうして という 特 殊 な 処 理 が 難 しい 7
MySQLを 拡 張 する MySQLハッキングのパターンは 大 きく 分 けて2 種 類 MySQL 本 体 に 手 を 入 れる MySQLの プラグイン を 開 発 する プラグインは 共 有 ライブラリ (*.so, *.dll) MySQL 本 体 の 改 変 が 不 要 標 準 バイナリにインストール 可 能 プラグインインターフェイスの 範 囲 内 で 好 きなように 実 装 可 能 要 件 によっては 実 装 できない( 本 体 の 改 変 が 必 須 な) 場 合 がある 例 :ファイル 内 static 変 数 には 外 部 からアクセスできない 例 : 監 査 ログインターフェイスはデバッグ 目 的 では 使 えない (SQL 文 の 実 行 後 に 呼 ばれるため 実 行 時 にクラッシュしても 呼 ばれない) MySQL 本 体 を 改 変 すれば 何 でもできる 標 準 バイナリは 当 然 ながら 使 えなくなる 有 用 なものはMySQL 本 家 にコントリビュートすることも 可 能 8
MySQLのソースコード 入 手 方 法 MySQL 本 家 サイトから 入 手 http://dev.mysql.com/downloads/mysql/5.1.html tar.gz 形 式 マイナーリリースごとに 公 開 MySQLソースコードツリーから 入 手 MySQLはソースコード 管 理 に bzr を 使 用 Launchpad 上 でホストしている https://code.launchpad.net/mysql-server shell> bzr branch lp:mysql-server/5.4 mysql-5.4 最 新 のものがほしい 場 合 はこちらから 9
開 発 の 流 れ 改 変 したいバージョンのソースコードをダウンロード 初 期 ビルド 改 変 デバッグビルド テスト 改 変 cd /path/to/mysql-top BUILD/autorun.sh./configure -- 多 数 のオプション make make install プラグイン 開 発 の 場 合 も デバッグビルドしたMySQLを 使 う プラグイン/MySQL 本 体 ともにデバッグビルドで 開 発 ビルド デバッグ 手 段 Linux/その 他 : gcc, gdb, ddd, Eclipse/NetBeans, etc Windows: Visual Studio 10
Configureオプション BUILD/ 以 下 にテンプレートがある バージョンによってconfigureオプションが 違 うので 注 意 --prefix.. インストール 先 のディレクトリ --with-debug.. デバッグビルドか 通 常 ビルドか --with-comment.. 接 続 時 に 表 示 される 文 字 列 --with-plugins= partitions パーティション 機 能 をサポートする innobase InnoDBストレージエンジンを 入 れる archive Archiveストレージエンジンを 入 れる --with-extra-charsets=complex.. 日 本 語 等 の 対 応 --with-fast-mutexes --enable-thread-safe-client --enable-local-infile --with-pic. 11
Visual Studio DOSプロンプトからwin configure.js を 実 行 引 数 にWITH_PARTITION_STORAGE_ENGINE WITH_INNOBASE_STORAGE_ENGINE などをつける DOSプロンプトからwin build-v8.batを 実 行 Visual Studioを 起 動 ビルド ボタンを 押 す (sql_locale.ccなどは UTF-8N (BOMなし) で 保 存 し なおす 必 要 がある) mysqldプロジェクトを スタートアップ プロジェクト に 指 定 右 クリック プロパティ デバッグ コマンド 引 数 に 起 動 オプションを 指 定 mysqlデータベースをデータディレクトリに 配 置 MySQLを 起 動 12
デモ(1) デバッグ / トレース MySQLに 手 を 入 れる 予 定 が 無 くても デバッグスキルを 持 つことには 意 味 がある クラッシュの 原 因 分 析 のため 動 作 原 理 を 知 るため プロトコルの 動 作 原 理 クエリの 実 行 の 流 れ Visual Studioから 起 動 したMySQLサーバに 対 し MySQLクライアントから 接 続 を 行 い どのように 処 理 が 流 れていくかを 紹 介 13
プラグイン 化 の 流 れ 本 体 への 機 能 改 変 やコントリビュートで 起 こる 問 題 そもそも 本 体 の 改 変 は 難 易 度 が 高 い 投 稿 したパッチがいつまでもマージされない 本 体 はQAの 観 点 からもパッチの 取 り 入 れには 保 守 的 プラグインは 本 体 を 改 変 せずに 使 うことができる MySQL 本 体 でパッチが 取 り 込 まれるのを 待 つ 必 要 が 無 い 本 体 側 の 改 変 が 必 要 な 場 合 は バグレポートやWork Logが 必 要 全 体 的 にはプラグイン 化 を 推 し 進 める 流 れ プラグイン 化 の 流 れをさらに 推 し 進 めたのがDrizzle MySQLでプラグインになっているもの ユーザ 定 義 関 数 (4.0 -) ストレージエンジン (5.1 -) Information Schemaプラグイン (5.1 -) 全 文 検 索 用 パーサ (5.1 -) 監 査 証 跡 (5.4 次 -) セミ 同 期 レプリケーション (5.4 次 -) 14
デモ (2) プラグイン 開 発 Information Schemaプラグイン cat /proc/meminfoの 結 果 を 返 してみる UDF ストレージエンジンAPIを 呼 んで テーブルに 直 接 アクセスしてみる Key Value Storeを 使 うような 感 覚 友 人 100 人 の 最 新 の 投 稿 メッセージIDを 取 得 する クエリを 考 えてみ る SELECT id FROM message WHERE user_id=? ORDER BY id DESC LIMIT 1; これをuser_idを 変 えて100 回 繰 り 返 す (user_id IN ( )だとMySQLではフルインデックススキャンになってしま う) ストアド 化 すると 高 速 化 が 期 待 できる UDFをストアドのかわりに 使 うという 例 15
プラグイン 開 発 の 一 般 的 な 注 意 事 項 MySQL 本 体 をクラッシュさせてしまう 危 険 がある プラグインを 実 行 するプロセスはmysqld プラグイン 内 部 の 不 正 メモリアクセスでも mysqldがsigsegvで 落 ちる 悪 意 あるユーザがバグつきプラグインをINSTALLしてクラッシュさせるこ とも 可 能 一 般 ユーザに 権 限 付 与 しないこと セキュリティホールになりうるので 権 限 管 理 に 注 意 mysqldをroot 権 限 で 動 かさないこと プラグインはOSコマンドを 実 行 できる 実 行 者 はmysqldの 権 限 になる プラグインの 中 身 によっては バージョン 依 存 性 が 高 くなる MySQL 本 体 で 使 っているマクロの 一 部 は 展 開 のされ 方 がデバッグ 版 と 通 常 版 configureオプションなどによって 変 わる そのマクロをプラグインから 使 う 場 合 には 当 然 依 存 性 が 出 る 16
次 世 代 のRDBMSアーキテクチャ? 接 続 / 操 作 リスナー 多 様 なプラグイン (レプリケーション Information Schema 監 査 ログ UDF 認 証 etc) パーサ オプティマイザ テーブルアクセス/ジョイン Storage Engine API クエリ 書 き 換 え ストレージエンジン 17
MySQL 本 体 に 手 を 入 れる 自 分 で 使 うだけなら ソース 改 変 ビルド テストで 良 い MySQL 本 家 に 反 映 してもらうには レビュー のプロセスが 必 要 多 くの 場 合 互 換 性 の 確 保 が 大 きな 壁 になる WorkLogに 登 録 http://forge.mysql.com/worklog/ 新 機 能 の 場 合 はこちらが 良 い またはバグレポートに 投 稿 単 なるバグの 場 合 はこちらが 良 い 18
デモ(3) MySQL 本 体 拡 張 レコードの 最 大 サイズ(TEXT/BLOB 除 く)を64KBから 拡 張 バイナリログの 追 記 上 書 き への 変 更 インデックスへのコメント 記 述 機 能 レコードサイズ 拡 張 CREATE TABLE t1 (c1 VARCHAR(50000), c2 VARCHAR(50000)); を 作 れるようにする max_row_lengthは2バイトで.frm 上 で 管 理 されている.frmのフォーマット 変 更 が 必 要 バージョン 互 換 への 配 慮 が 必 要 19
ソースコードレベルの 議 論 技 術 的 な 議 論 internals@lists.mysql.com バグレポート http://bugs.mysql.com パッチの 投 稿 も 可 能 パッチの 投 稿 レビュー 議 論 commits@lists.mysql.com コミットメールをここに 投 稿 する レビューおよびその 後 の 議 論 は すべてこれをCCに 入 れて 行 なう 20
WorkLogとは MySQLの 新 機 能 の 開 発 計 画 を 管 理 http://forge.mysql.com/worklog/ 流 れ WorkLogに 新 規 エントリを 投 稿 SunのMySQL 開 発 者 がレビュー 担 当 になる Sun Contributor Agreement (SCA)を 締 結 パッチをコミット パッチをレビュー レビュー 結 果 を 踏 まえてパッチをコミット レビュー 完 了 本 家 にマージ 21
パッチのレビュー コーディング 規 約 に 準 拠 していること テストケースが 用 意 されていること mysql-testテストケース その 他 常 識 的 なコードであること スレッドセーフである 効 率 的 な 実 装 になっている 変 数 名 が 自 然 コメントが 読 みやすい 22
コーディング 規 約 ( 抜 粋 ) http://forge.mysql.com/wiki/mysql_internals_coding_guideline s インデント/スペース/ 行 管 理 インデントには 半 角 スペース2 個 タブは 使 用 禁 止 改 行 は nを 使 用 CR+LF( r n)は 禁 止 1 行 は 最 大 80バイト 1つの 関 数 内 に 連 続 した2 行 以 上 の 空 白 行 を 入 れてはいけない 関 数 と 関 数 の 区 切 りには2 行 の 改 行 を 入 れる 変 数 の 代 入 条 件 分 岐 x= 1; のように 変 数 名 と 演 算 子 の 間 にスペースを 入 れない 演 算 子 の 後 にはスペースを1 個 入 れる ifと(の 間 には 半 角 スペースを1 個 入 れる If { ではなく ifと{の 間 には 改 行 を 入 れる などなど 多 数 23
テスト mysql-testという 単 体 テストツールを 走 らせる http://dev.mysql.com/doc/mysqltest/en/index.html 単 体 テストツール mysql-test-run perl mysql-test-run.pl ストレステストツール mysql-stress-test.pl 回 帰 テスト 用 に 使 う 1つの 機 能 追 加 にあたり 最 低 でも1 個 の 妥 当 な テストケースを 追 加 24
WorkLogの 例 監 査 プラグイン http://forge.mysql.com/worklog/task.php?id=3771 セミ 同 期 レプリケーション http://forge.mysql.com/worklog/task.php?id=1720 Preallocating Binlog http://forge.mysql.com/worklog/task.php?id=4925 25
バイナリログの 追 記 上 書 きへの 変 更 パッチ (1) 耐 障 害 性 のため コミット 時 に 同 期 書 き 込 みするニーズ がある sync-binlog=1 大 半 のファイルシステムで 追 記 同 期 書 き 込 みは 上 書 き 同 期 書 き 込 みに 比 べて 圧 倒 的 に 遅 い 10,000+ fsync/s vs 3,000 fsync/sくらいの 違 いはある ファイルサイズを 増 やすための 領 域 確 保 のオーバーヘッドが 大 きい バイナリログは 追 記 で 書 き 込 みのたびにファイルサイズ が 増 える 最 初 から 上 書 きしておけば 速 くなるはず 26
バイナリログの 追 記 上 書 きへの 変 更 パッチ (2) 技 術 的 課 題 最 初 にサイズを 割 り 当 てるが そのコストをゼロにしたい 専 用 コマンドを 用 意 して 割 り 当 てておく( 手 動 ) posix_fallocate() 使 用 ( 自 動 ) レプリケーション mysqlbinlog SHOW BINLOG EVENTS 等 既 存 のすべてのコマンドが 正 常 動 作 する 必 要 がある バイナリログを 転 送 しきったら 次 のイベントが 来 るまで 待 つという 動 作 転 送 しきったかどうかはEOFで 判 定 これは 上 書 き 確 保 した 場 合 にはできない ファイルサイズを 内 部 的 に 管 理 しておく 必 要 がある ファイルサイズが 都 度 更 新 されるので スレッドセーフになるように ファイルサイズを 管 理 する 必 要 がある 今 は すでに 存 在 しているバイナリログの 最 大 番 号 +1 を 新 規 作 成 して 使 用 する これでは 手 動 で 割 り 当 てたバイナリログが 使 われない 27
バグレポートの 投 稿 バグレポートの 投 稿 http://bugs.mysql.com/report.php アカウント 登 録 が 必 要 Synopsis: 現 象 を1 行 程 度 で 登 録 Category Severity Version OS Description How to repeat パッチをここで 投 稿 することもできる 28
バグレポートから 本 体 マージの 例 UPPER()/LOWER() 関 数 がシフトJIS 環 境 で 正 しく 動 作 しない http://bugs.mysql.com/bug.php?id=44352 4 月 18 日 に 立 岡 さんよりパッチ 含 めて 投 稿 5 月 4 日 に 修 正 版 パッチのレビューが 開 始 5 月 28 日 にMySQL5.1.36 本 体 への 反 映 簡 単 なものでも 数 ヶ 月 かかるものもあるし 1 年 以 上 放 置 される 場 合 もありますorz 29
参 考 文 献 基 本 はオンライン 上 で 英 語 (Web メーリングリスト IRC) http://forge.mysql.com internals@lists.mysql.com #mysql-dev 書 籍 の 情 報 はどれも 古 いので 参 考 程 度 に Expert MySQL UDF ストレージエンジンを 自 作 する 方 法 など Understanding MySQL Internals ( 翻 訳 本 : 詳 解 MySQL オライリー) THDやTABLEなど 主 要 なデータ 構 造 MySQL 構 築 バイブル ( 毎 日 コミュニケーションズ) 通 信 プロトコル 関 数 の 自 作 など 超 極 める MySQL ( 翔 泳 社 ) ひろせさんのUDF 解 説 記 事 30
ありがとうございました Q & A 31