• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
DTraceによるMySQL解析ことはじめ
 

DTraceによるMySQL解析ことはじめ

on

  • 6,921 views

Webなどで人気の高いMySQLデータベースサーバーにおいて、DTraceを使った解析手法を紹介します。MySQLの構造的について簡単にお話しし、それをどのよ...

Webなどで人気の高いMySQLデータベースサーバーにおいて、DTraceを使った解析手法を紹介します。MySQLの構造的について簡単にお話しし、それをどのようにDTraceで追いかけるかについて説明します。

Statistics

Views

Total Views
6,921
Views on SlideShare
6,898
Embed Views
23

Actions

Likes
5
Downloads
81
Comments
0

2 Embeds 23

http://www.slideshare.net 19
http://www.linkedin.com 4

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    DTraceによるMySQL解析ことはじめ DTraceによるMySQL解析ことはじめ Presentation Transcript

    • DTrace で MySQL を斬る! 〜 DTrace による MySQL 解析ことはじめ 〜 奥野 幹也 @nippondanji mikiya (dot) okuno (at) gmail (dot) com
    • 自己紹介 ● 今日は個人として来ています。 – http://nippondanji.blogspot.com/ – http://www.google.com/profiles/mikiya.okuno ● 現職は MySQL サポートエンジニア。 – 2000 年にサン・マイクロシステムズ入社 – 2007 年に MySQL KK へ転職 – 気付くとまたサン・マイクロシステムズに – オラクル・コーポレーションに・・・
    • MySQL について ● オープンソースのリレーショナル・データベー ス・マネージメント・システム ● MySQL AB => Sun Microsystems => Oracle に よって開発。 ● Web 開発においては圧倒的なシェア – PHP/Perl/Java/Ruby/C/C++/ODBC... ● 使い易く、安定して、高速に動作するのがウリ
    • MySQL は永久に不滅です! © Brian Aker http://krow.livejournal.com/687521.html
    • MySQL の特徴 ● ANSI SQL 標準に準拠(一部の文法を除 ● UNION く。) ● ビュー ● 種々のプラットフォームをサポート ● サブクエリ ( Windows 、 Linux 、 Mac 、各種 UNIX 系 ● INFORMATION_SCHEMA OS ) ● SSL による通信 ● ストレージエンジンによりデータを格納す ● Unicode をはじめとした各種文字コードの るレイヤーを仮想化 サポート ● ACID 準拠のトランザクション ● 全文検索 ● XA トランザクション ● タイムゾーンのサポート ● 非同期 Master/Slave 型レプリケーション ● 多種多様な開発言語のサポート( C 、 C+ ● 水平パーティショニング + 、 Java 、 Perl 、 PHP 、 Python 、 Ruby ( Range 、 List 、 Hash 、 Key ) など) ● ストアドプロシージャ、ストアドファンク ● ODBC による接続のサポート ション、トリガ
    • MySQL 構造の特徴 ● モノリシックカーネル ● シングルプロセス・マルチスレッド ● 1 セッション= 1 スレッド ● ストレージエンジン API による仮想化 ● プラグイン API ● GNU Bison による Lexical Scanner ● ソースコードは C/C++ 混在( 100 万行程度)
    • MySQL の仕組み クライアント クライアント クライアント Java PHP ODBC コネクション コネクション コネクション スレッド スレッド スレッド SQL の解析と最 適化は共通 パーサー・オプティマイザ・アクセス管理 等 ストレージエンジン API データの格納や MyISAM InnoDB MySQL アクセス方法は Cluster ストレージエン テーブル table_name.MYI スペース ジンごとに違う table_name.MYD NDB ログファイル API MySQL サーバ データノード データノード データノード データノード
    • MySQL の構造を知る! ● Web ページ – http://forge.mysql.com/wiki/MySQL_Internals ● 書籍 – 詳解 MySQL ( Understanding MySQL Internals ) – Expert MySQL – MySQL データベース構築バイブル ● ソースコード!!
    • ソースコードを入手! ● http://dev.mysql.com/downloads/ ● bzr branch lp:mysql-server/5.1 mysql-5.1 ● sql/mysqld.cc ... main() 関数があるよ! ● sql/sql_parse.cc ... リクエストの入り口 ● sql/sql_yacc.yy ... SQL パーサー この辺りから ● sql/handler.cc ... ストレージエンジン API 覗いてみよう! ● sql/log.cc ... ログ関係 ● sql/log_event.cc ... バイナリログ ● sql/sql_show.cc ... SHOW コマンドと I_S ● sql/slave.cc ... レプリケーションスレーブ ● sql/item*cc ... データ型と関数 ● sql/sql_base.cc, sql/sql_class.cc ... 基本的なデータ型等 ● storage/innodb ... InnoDB の実装 ● storage/myisam ... MyISAM の実装 ●mysys/* ... MySQL Core API
    • DTrace!! ● Solaris 10 で搭載された機能。 – Solaris/Mac OS X/FreeBSD で利用可能 ● カーネル / ユーザープロセスをトレース。 ● プローブと呼ばれる観測点を対象のプログラム に動的に埋め込む。 ● プローブの種類に応じたプロバイダ。 ● D 言語と呼ばれるプログラムで操作。 – 参考: D 言語基本文法最速マスター( DTrace のほう) – http://nippondanji.blogspot.com/2010/02/ddtrace.html
    • DTrace 動作イメージ プロバイダに指示を出したり ユーザープロセス 情報を表示したり ( mysqld など) dtrace コマンド プロ ーブ ユーザー空間 各種情報 カーネル空間 Fire 有効化 DTrace モジュール プロバイダ プロ ーブ モジュール
    • プロバイダの種類 Provider名 Probeの場所 Providerのシンボル FBT - function カーネル内における関数の fbt boundary tracing 呼び出しとリターン。 Systrace システムコールの呼び出し syscall とリターン。 SDT - statically ソースコードにおいて指定さ sdtまたはコンパイル時に指 defined tracing れた任意の場所。(カーネ 定 ル内) PID ユーザープロセスにおける pid{pid} 関数の呼び出しとリターン。 (pid1234のように指定する) Fasttrap ソースコードにおいて指定さ コンパイル時に指定 れた任意の場所。(ユー ザープロセス内) dtrace トレースの開始と終了、およ BEGIN/END/ERROR び例外発生時。 profiling 一定期間ごと。 profile-n/tick-n (nはインターバル)
    • D 言語の書式 プローブ記述子 / 述語 / { これを必要な回数 列挙するだけ。 アクション ループなし、分岐なし。 }
    • プローブの書式 ● プロバイダ名 : モジュール名 : 関数名 : プロー ブ名 – pid プロバイダの場合、 pid{ プロセス ID} とい う書式になる。例 ) pid123 – C++ の関数名を指定するにはワイルドカード ( * )が便利。
    • mysqld 内に設置可能なプローブ ● pid – 関数の entry C++ の関数名に注意 It's mangled!! – 関数の return – 関数オフセット – 書式 ) pid123 ● Fasttrap – MySQL 5.4 で追加!! – 書式 ) mysql123
    • 述語の書式 ● 評価出来る式なら何でも OK – 例 ) execname == "mysqld" ● 条件分岐がない代わりに述語で Fire するかどう かをコントロール。
    • アクション ● 情報の出力や変数への代入。 ● セミコロン区切りで必要な数を列挙。 ● 情報の出力例。 – trace( 式 ) – tracemem(address, size); – printf(" フォーマット ", arg1, arg2, ...); – ustack(); jstack(); stack(); etc
    • 変数の種類 ● スカラー変数… argname – グローバルなスコープを持つ ● スレッドローカル変数… self->argname – 同一スレッドだけからアクセス可能 ● 節固有変数… this->argname – プローブが Fire している間だけ利用可能 ● 組み込み変数…後述 ユーザープロセス ● 外部変数… `argname には使えない。
    • 組み込み変数 ● arg0 ... arg9 ・・・プローブに対する引数の最初の 10 個(数値型で取得) ● cwd ・・・カレントワーキングディレクトリ ● errno ・・・直前のシステムコールによって返されたエラーの値 ● execname ・・・実行プログラム名 ● uid ・・・実行中のプロセスの実効ユーザー ID ● gid ・・・実行中のプロセスの実効グループ ID ● pid ・・・実行中のプロセス ID ● ppid ・・・実行中のプロセスの親プロセス ID ● tid ・・・現在のスレッドのスレッド ID 大切な情報源!! ● probeprov ・・・プロバイダ名 ● probemod ・・・モジュール名 ● probefunc ・・・関数名 ● probename ・・・プローブ名 ● timestamp ・・・タイムスタンプ ● walltimestamp ・・・ 1970 年 1 月 1 日 UTC からの経過時間。単位はナノ秒。
    • MySQL 5.4 で追加されたプローブ ● include/probes_mysql.d を見よ! Fasttrap! connection-start(unsigned long conn_id, char *user, char *host); connection-done(int status, unsigned long conn_id); command-start(unsigned long conn_id, int command, char *user, char *host); command-done(int status); query-start(char *query, unsigned long connid, char *db_name, char *user, char *host, int exec_type); query-done(int status); query-parse-start(char *query); query-parse-done(int status); query-cache-hit(char *query, unsigned long rows); query-cache-miss(char *query); query-exec-start(char *query, unsigned long connid, char *db_name, char *user, char *host, int exec_type); query-exec-done(int status); insert-row-start(char *db, char *table); insert-row-done(int status); update-row-start(char *db, char *table); : :
    • プローブを設置し易い関数 ● DTrace の制約として、外部変数はユーザープ ロセスをサポートしていない。 – 引数が重要な情報源! – mysql_parse() 関数 ... 第 2 引数が SQL 文 ● エラー発生時に Fire する。 – vprint_msg_to_log() ... エラーログへの書 き込み – my_error() ... クライアントへエラー送信 – my_print_error() ... シンタックスエラー
    • 例 1) SQL 文を抽出 pid$target::*mysql_parse*:entry { trace(copyinstr(arg1)); }
    • 例 2) メモリ不足の原因 pid$target::*mysql_parse*:entry { self->q = 1; self->qstr = copyinstr(arg1); } pid$target::*mysql_parse*:entry / self->q / { self->q = 0; self->qstr = 0; } pid$target::malloc:return / errno == ENOMEM / { printf("=== Memory allocation error at %Y ===n", walltimestamp); ustack(); } pid$target::malloc:return / errno == ENOMEM && self->q / { printf("QUERY: %sn", self->qstr); }
    • 例 3) エラーメッセージを追跡 pid$target::*mysql_parse*:entry { self->q = 1; self->qstr = copyinstr(arg1); } pid$target::*mysql_parse*:return / self->q / { self->q = 0; self->qstr = copyinstr(arg1); } pid$target::*my_error:entry / self->q / { printf("Query generated an error (errno = %d): %sn", arg0, self->qstr); ustack(); } pid$target::*my_printf_error:entry / self->q / { printf("Syntax error: %sn", self->qstr); }
    • 例 4) クエリキャッシュのヒット率 mysql$target:::query-cache-hit { hit++; @qhit["rows per query when qcache hit"] = quantize(arg1); } mysql$target:::query-cache-miss { miss++; @qmiss[copyinstr(arg0)] = count(); } tick-5sec / hit != 0 || miss != 0 / { printf("ratio: %u (%u / %u)", 100 * hit / (hit+miss), hit, hit+miss); } tick-5sec / hit == 0 && miss == 0 / { printf("ratio: NULL"); } tick-5sec { total_hit += hit; total_miss += miss; hit = miss = 0; }
    • 例 5) 1000 行以上のソートを検出 #!/usr/sbin/dtrace -s BEGIN { printf("Hit Ctrl+C to exit.n"); } mysql$target:::filesort-start { self->sorting = 1; self->db = arg0 == 0 ? "NULL" : copyinstr(arg0); self->table = copyinstr(arg1); } mysql$target:::filesort-done /self->sorting && arg1 > 1000/ { self->sorting=0; printf("DB: %s, Table: %s, Rows: %u", self->db, self->table, arg1); }
    • 例 5) 1000 行以上のソートを検出 #!/usr/sbin/dtrace -s BEGIN { printf("Hit Ctrl+C to exit.n"); } mysql$target:::filesort-start { self->sorting = 1; self->db = arg0 == 0 ? "NULL" : copyinstr(arg0); self->table = copyinstr(arg1); } mysql$target:::filesort-done /self->sorting && arg1 > 1000/ { self->sorting=0; printf("DB: %s, Table: %s, Rows: %u", self->db, self->table, arg1); }
    • 例 6) テーブルごとのソート統計 mysql$target:::filesort-start { self->sorting = 1; self->db = arg0 == 0 ? "NULL" : copyinstr(arg0); self->table = copyinstr(arg1); } mysql$target:::filesort-done /self->sorting/ { self->sorting=0; @sorts[self->db, self->table] = sum(arg1); }
    • 例 7) ソート中断の原因 #!/usr/sbin/dtrace -s pid$target::*mysql_parse*:entry { self->q = 1; self->qstr = copyinstr(arg1); } pid$target::*mysql_parse*:return / self->q / { self->q = 0; self->qstr = 0; } mysql$target:::filesort-done / self->q && arg0 / { printf("nnABORTED QUERY: %sn", self->qstr); ustack(); }
    • DTrace Toolkit ● DTrace を使ったユーティリティ群 – http://hub.opensolaris.org/bin/view/Community+ Group+dtrace/dtracetoolkit – http://nippondanji.blogspot.com/2007/07/dtrace. html ● DTrace を知らなくても利用可能 ● Mac OS X ではデフォルトでインストール – grep -I -m 1 dtrace /usr/bin/*
    • DTrace Toolkit つづき ● dappprof ... ユーザープロセスをプロファイリングします。 ● dapptrace ... ユーザープロセスの関数呼び出しを追跡。 ● dtruss ... ユーザープロセスのシステムコール呼び出しを追跡。 ● errinfo ... システムコール呼び出しにおいてエラーの発生を追跡。 ● execsnoop ... プロセスの実行開始を追跡。意図しないプログラムが実行さ れていないかどうかを確認することが可能。 ● iotop ... システム全体で、 I/O 帯域をたくさん消費しているプロセスをリス トアップ。 IO の帯域を消費しているプロセス特定に便利。 ● kill.d ... プロセスにシグナルが送られた時にその送り主と送り先に関する情 報を記録。 ● opensnoop ... ファイルが open された際に情報を出力。
    • デモで利用したもの ● Random Query Generator – http://forge.mysql.com/wiki/Random_Query_Ge nerator ● Example DBs – http://dev.mysql.com/doc/index-other.html ● MySQL Sand Box – http://mysqlsandbox.net/
    • 宣伝!! ● 著書: MySQL エキスパートトラブルシュー ティングガイド(仮)/技術評論社 – 様々な角度から MySQL のトラブルを解析するのに役立つ書 籍です。ぜひ安心な DBA 生活のお供に一冊どうぞ。 – 第一章: MySQL の概要 – 第二章:開発時における問題 – 第三章: MySQL の状態を見る。 – 第四章: DTrace – 第五章:運用中に起きる諸問題。 – 第六章:堅牢な運用を実現するために – 第七章:ソースコードのビルド
    • Q&A