More Related Content Similar to MySQLトラブル解析入門 (20) More from Mikiya Okuno (20) MySQLトラブル解析入門3. 自己紹介
● MySQL サポートエンジニア
– 日々のしごと
● トラブルシューティング全般
● Q&A回答
● パフォーマンスチューニング
など
● ライフワーク
– 自由なソフトウェアの普及
● オープンソースではない
● ブログ
今日は個人として
参加しています。
– 漢のコンピュータ道
– http://nippondanji.blogspot.com/
6. アジェンダ
● MySQL でよくある問題の傾向と対策
– SQL の結果がおかしい
– 文字化け
– レプリケーションの諸問題
– クラッシュ
– データ破壊
– デッドロック
etc
● ツールを使いこなす!!
– SHOW コマンド、INFORMATION_SCHEMA
– ログ
etc
8. SQL がエラーになる
● プログラムのソースコードを見ただけでは分からないことが
多い。
– 一般クエリログやlong_query_time=0 にしたスローク
エリログがクエリの特定に役立つ
– 理想的には、SQL を実行してエラーになったときアプリ
ケーションがログを取るようにしておく。
– 実際にエラーになったSQL を実行してみる。
● エラーの原因と対処は千差万別
9. 一般クエリログ
● MySQL サーバーに対して投げられたリクエストを全て記録
する。
● 実際に実行されたクエリを見ることができるので、アプリ
ケーションのデバッグに役立つ。
– SQL がエラーになろうがなるまいが記録される。
● 動的に有効・無効を切り替え可能。
– SET GLOBAL general_log=ON;
● 出力先はファイルまたはテーブル。
10. 期待通りの結果が返らない
● MySQL のバグの可能性
– 別のストレージエンジンを使って試してみる
– EXPLAIN で実行計画を見る
● インデックスヒントを使って実行計画を変更してみる
● 最適化オプションのON/OFF
– 問題が起きる最小のデータとクエリを突き止める
● バグ登録
● そもそもそのSQL は正しいか?
– 複雑なSQL はシンプルなパーツに分けてみる
– リレーショナルモデルに沿って考える
● いつから問題が起きているか?
– テーブルのメンテナンスやアップグレードはおこなったか
– アプリケーションの改修をしたか
12. MySQL サーバー内の文字コード変換
テーブルセッションクライアント
MySQLサーバー
①送信する
SQL文に対する
文字コード
③クエリの
実行結果に対する
文字コード
②クエリの実行
に利用する
文字コード
④データを
蓄える際の
文字コード
⑤テーブル名や
カラム名に対する
文字コード
⑥ファイル名を
解決する際の
文字コード
ファイルシステム出展:エキスパートのための MySQL
[運用+管理]トラブルシューティングガイド
13. 文字コードを確認する
● SHOW [GLOBAL] STATUS LIKE 'char%';
– character_set_client
– character_set_connection
– character_set_results
– character_set_server/character_set_database
– character_set_system
– character_set_filesystem
● アプリケーションから実行してみる
– ドライバの設定(接続プロパティ)に問題はないか
14. 文字化けの原因と対策
● 接続用の文字コードは問題ないか?
– アプリケーションが期待している文字コードとドライバの文
字コードは同じか?
● 端末の文字コードは問題ないか?
– chcp (Windows ) /locale ( UNIX系OS )
– MySQL 標準クライアントの場合は—defaultcharacterset
を指定。ただしskipcharactersetclienthandshake
がサーバで設定されていると無効。
(要注意!)
– charset utf8
● テーブル内のデータは問題ないか?
– latin1 でマルチバイト文字を格納してしまった。
● 正しい文字コードを指定して取り出すと化ける。
– いったんbinary としてバックアップ。
15. テーブルの文字コード
● カラムごとに文字コードを指定可能
– SHOW CREATE TABLE で確認
● INFORMATION_SCHEMA を利用すると一括で調べられ
る
– SELECT * FROM COLUMNS
WHERE CHARACTER_SET_NAME != 'utf8';
16. Connector/J の留意点
● 文字コードはcharacterEncoding プロパティで指定
● 文字コードの指定がない場合には接続先サーバーの
character_set_server により決定。接続後SET NAMES
をドライバが実行。
● skipcharactersetclienthandshake
は効かない
● characterEncoding が何であれ、Java内部で文字列
のエンコーディングはucs2 に変換される。
17. LOAD DATA INFILE
● LOAD DATA INFILE
– ファイルの文字コードがcharacter_set_database に
なっていることを期待している
– SET character_set_database = cp932;
– テーブルの文字コードと同じ場合にはbinary を指定する
と変換が生じないので高速
– LOAD DATA INFILE ではなくmysqlimport を使う手も
ある
● SELECT … INTO OUTFILE
– デフォルトでは文字コード変換しない
● LOAD DATA で読むときはbinary を指定すると良い
– LOAD DATA で読む段階のことまで考えておく
● SELECT … INTO OUTOFILE 'file_name'
CHARACTER SET charset_name …
20. バイナリログ
● 全ての更新を記録するためのログ
– 元々はSQL 文を直接記録しておくものだった
● バイナリ(テキストではない)のヘッダ+ SQL文
– MySQL 5.1 からSQL を実行した結果(行)を記録するこ
とが可能に
● インデックスファイル
– バイナリログファイル名を記録
● msyqlbin.
index
● バイナリログファイル
– 連番のついたファイル
● mysqlbin.
000001
– 中身はマジックナンバー+イベント
21. バイナリログの種類
ステートメントベース
● SQL 文を直接記録する
● データサイズの効率が良い
● 非決定性のステートメントは含める
ことができない
● 従来からある実装
行ベース
● データそのものを記録する
● クエリの種類を問わず対応可能
● 行ベースしか対応していないスト
レージエンジンもある
● 5.1 から利用可能
MIXED
● ステートメントベースと行ベースを状況に応じて使い分ける
● 通常はSBR 、非決定性のステートメントはRBR
22. SQL スレッドの停止
● スレーブ上のテーブルを更新してしまった。
– マスターのデータからリストア
● スレーブのクラッシュでポジションが巻き戻ってしまった
– マシンがクラッシュした場合に起こりがち
– 重複キーエラーに
– マスターのデータからリストア
● バイナリログ欠損
– マスター上で失われた情報はどこにもない!!
– 全て再セットアップ
● 一時的なエラーなら
– mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = N;
– mysql> START SLAVE;
23. I/O スレッドの停止
● ネットワークのエラー。
● マスターがダウンした。
● max_allowed_packet が足りない。
● ユーザがログイン出来ない。
– ユーザのパスワードを変更してしまった?
– エラーログを調査。
24. SHOW SLVAE STATUS
● Slave_IO_Running: I/O スレッドが動作中かどうか
● Slave_IO_State: I/O スレッドのステータス
● Slave_SQL_Running: SQL スレッドが動作中かどうか
● Master_Log_File: I/O スレッドのバイナリログファイル名
● Read_Master_Log_Pos: I/O スレッドのポジション
● Relay_Master_Log_File: SQL スレッドのバイナリログファイル名
● Exec_Master_Log_Pos: SQL スレッドのポジション
● Seconds_Behind_Master: 遅延(後述)
● Last_Error: 最後に発生したエラー
● Last_Errno: 最後に発生したエラーの番号
● Skip_Counter: エラーを無視する回数
● Replicate_*: フィルタ
25. SHOW MASTER STATUS
● バイナリログに関する情報を表示する
– File: 現在更新中のバイナリログファイル名
● デフォルトでは hostname.000001 から始まる連番の
ファイル名
– Position: 現在のバイナリログポジション
– Binlog_Do/Ignore_DB: フィルタ
– Executed_Gtid_Set: これまでに実行したGTID
● マスターとスレーブのバイナリログポジションを見比べる
26. レプリケーションの遅延
● Seconds_Behind_Master とは
– I/O スレッドによる遅延+SQL スレッドによる遅延+ ズレ
– レプリケーション開始時に時計のズレを検出
– ネットワークが停止するとI/O スレッドの遅延は分からな
い
● 後から急激な時差を検出する場合がある
● レプリケーションハートビート
– あくまでも近似値!!
● I/O スレッドの遅延
– ネットワークの問題
– リレーログの書き込みを同期( sync_relay_log )
● SQL スレッドの遅延
– SQL の実行に時間がかかる
– 更新/削除するデータがキャッシュに存在しない
27. クラッシュセーフなスレーブ
● MySQL 5.6 からスレーブがクラッシュしてもレプリケーション
の再開に支障を来すことがなくなった。
InnoDB
クラッシュセーフ
レプリケーション情報
=
relay_log_info ファイル
クラッシュセーフではない
InnoDB
レプリケーション情報
=
mysql.slave_relay_log_info
テーブル
クラッシュセーフ
MySQL 5.5以前MySQL 5.6
28. レプリケーションによるHA
● 利点
– 共有ディスク型のHA と違ってリカバリ不要!
● 超高速フェイルオーバー
– レプリケーションはデフォルトで使える機能
● 課題
– 非同期だから最後に更新したデータを一部失う覚悟が必
要。
● 準同期レプリケーション
– 1:N 構成では昇格に工夫が必要。
● GTID
29. 準同期レプリケーション
クライアント
クライアントへ応答が返った時点で
スレーブへバイナリログの転送は完了している。
マスタースレーブ
マスター
スレッド
スレーブI/O
スレッド
スレーブ
SQL スレッド
9. send_ok
8. ack
2.更新内容
を記録
4.読み込み
5.転送
6.記録
7-2.
更新の
適用
1. COMMIT
接続スレッド
3.更新
7-1. ack
テーブルバイナリログリレーログテーブル
30. Global Transaction ID
● トランザクションを一意に識別することができるID
– UUID: トランザクションID の形式で表現される
● 例) 095E0FF818AF11E29E7C5C260A2AA986:
123456
– バイナリログ内に記録
● スレーブでもバイナリログを有効化
● log_slave_updates = 1
● トランザクションID はシーケンス
– 1:N 環境で、どのスレーブが最も進んでいるか一目瞭然!
● 昇格の手順は簡単
– 最も進んでいるスレーブを新しいマスターに
– CHANGE MASTER TO … MASTER_AUTO_POSITION = 1
31. msyqlfailover
● 1:N のレプリケーションで使うツール
– サーバーの死活監視
– マスターがFail したときに新たにスレーブを自動で昇格
● 最も進んだスレーブを検出
● CHANGE MASTER TO … MASTER_AUTO_POSITION = 1
● MySQL Utilities に付属
– Python製
32. レプリケーション安定化計画
● ステートメントベースはリスクがある
– テンポラリテーブルは使わない。
● テンポラリテーブル作成後にSQL スレッドが停止する
と、再セットアップが必要になる。
– Nondeterministic
なSQL でエラーになる。
● マスターだけを豪華にし過ぎない
– マスターとスレーブは同じ量の更新が発生する。
– ハードウェア、バッファは同じ程度に設定しておく。
33. レプリケーション安定化計画(つづき)
● マスタークラッシュ時
– バイナリログの欠損を防ぐ。
● MySQL 5.6 + sync_binlog=1
● 1:N構成では準同期+GTID で昇格を自動化
– MySQL 5.6
– mysqlfailover で自動的に昇格
● クラッシュセーフなスレーブを利用する
– MySQL 5.6
35. クラッシュを誘発するシグナルの種類
● SIGSEGV
– プログラムが無効な(セグメント境界を超えた)メモリアド
レスへアクセスした。
– バグやデータ破壊の可能性。
● SIGABRT
– プログラムがabort(3) を呼び出した。
– アサーション失敗。バグやデータ破壊の可能性。
● SIGBUS
– 無効な物理メモリアドレスへアクセスした。
– メモリアライメントの問題やハードウェアの故障など。
● メモリアライメントに問題があるのはバグ
● メモリアライメントが必要かどうかはCPU次第( SPARC
など)
36. エラーログ
● クラッシュ時にはスタックトレースなどの情報がエラーログ
に記録される
– デフォルトではコアファイルが生成されないので、エラーロ
グが唯一の手がかりに。
– シグナルの種類が判別可能。
– クラッシュ後にリカバリが行われているかの判定も重要。
● エラーログは超重要
– クラッシュ時以外にも何か問題が起きたらまず見る。
– 実は標準出力をリダイレクトしたもの。
– /path/to/datadir/hostname.err
● /var/log 配下にあることも。
– サポートへ送るときは編集せずに!!
37. コア解析
● GDB などのデバッグツールを使って行う
● コア解析はいわば検死解剖
– 直接の死因は分かるがそれがどのように引き起こされた
かまでは分からないことが多い
● データ破壊によるクラッシュが起きた場合、なぜデータ
は壊れたのか?という原因はコア解析では分からないこ
とが多い。
● ソースコードの理解が不可欠
– サポートへ依頼して頂きたい。
39. データ破壊の概要
● 特にクラッシュ時によく起きる
– ファイルシステムキャッシュにデータが残っている間にOS
ごとダウンした場合などは危険
● データ保護の実装はストレージエンジン次第
– トランザクション対応のストレージエンジンはクラッシュリカ
バリあり
● InnoDB
● MySQL Cluster
– トランザクション非対応のストレージエンジンはクラッシュリ
カバリなし
● MyISAM
● ARCHIVE
40. MyISAM
● OS やMySQL サーバーのクラッシュ時にデータが壊れるか
も知れないのは仕様です。
– トランザクションに対応していないため。
– OLTP系の処理には不向き。
● 対策
– バックアップやレプリケーションなどでデータを複製してお
く。
– データロストが発生するのは諦める。
– REPAIR TABLE コマンドで復旧を試みる。
● ただし、確実に直るという保証はない。
41. InnoDB
● 原因
– クラッシュなどによって簡単には壊れない
● ログ(WAL )とダブルライトバッファ
– ハードウェアのエラーには耐えられない
● ディスク交換後にリストア
– バグ
– オペミス
● 復旧方法
– innodb_force_recovery=4 または 6
– 問題のテーブルまたは全体をmysqldump ( 6 の場合は全体)
– テーブルをDROP またはデータディレクトリ初期化
– innodb_fource_recovery オプションを解除して再起動。
– リストア
● 対策
– バックアップやレプリケーションで鉄壁の防御を!
43. mysqldがメモリ不足で停止する
● 32bit バージョンのプログラムはもう使わない!!
– 論理アドレス枯渇によるOut Of Memory がよく起こる。
– RSS が1GB程度でも起こる。
● 割り当て/解放の繰り返しによりフラグメンテーションが
発生するからVSIZE が大きくなってしまう。
– Linux では3GB まで、Windows では2GB まで。
● ulimit
● バッファの割り当てすぎ。
– 特にセッションごとのバッファが大きすぎる場合が多
い。tmp_table_size=64M など。
● カーネルの設定など
– FreeBSD … kern.maxdsiz
– HPUX
… maxdsiz_64bit
44. OOM Killer
● Linux上でメモリが足りなくなった時にプロセスを終了させ
る。
● エラーメッセージがなく突然mysqld が終了している場合
に疑ってみるべし。
– OOM Killer が発動したことはsyslog に記録が残る
– 夜間バッチなどでmysqld またはそれ以外のプロセスが
大量にメモリを消費していないか?
● echo 17
> /proc/pid/oom_score_adj
47. デッドロック対策
● デッドロックは起きるもの。根絶することはできない。
– トランザクションが保証しているのは、実行した結果が
Commit かAbort になるということ。失敗する( Abort )
可能性はゼロにできない。
● InnoDB はデッドロック検出機能あり
– 片方のトランザクションを強制的にロールバック
● リトライ処理
– 発生したら黙ってリトライ。リトライのロジックは必須
– 他の例外処理とまとめて実装すると良い。
● 行へアクセスする順序を工夫する
– 主キーの順でアクセスするなど
– デッドロックが頻発するケースではテーブルロックも有用
48. Lock wait timeout
● ロックを長時間獲得出来なかった時に生じる現象
– デッドロックではない
– UPDATE やDELETE に時間がかかり、ロックを待っていた
他のトランザクションがタイムアウトする
– InnoDB のデッドロック検出機能は100% ではない
– NDB にはデッドロック検出機能はないので必ずLockwaittimeout
になる。(見極めが難しい)
● 対策
– リトライ!!
– 大量のレコードを一度に更新する処理を改める
● バッチ系の処理はこまめに分けて更新する
● テーブルロックをかけてから実行する
– Lock wait timeout は発生しないが処理が待たされる
50. クエリが遅い
● 適切なインデックスが使われていない
– テーブルスキャンが発生している
– 複合インデックスが必要なのに作成されていない
● クエリの効率がよくない
– サブクエリではなくJOIN を
– クエリが複雑になるのはテーブル設計がよくない兆候かも?
● 同時実行数が多すぎる
– >CPU コア数
● バッファプールが足りない
51. スロークエリログ
● 実行に時間がかかったクエリを記録する
– long_query_time で閾値を指定
– long_query_time=0 で全てのクエリを記録
– log_queries_not_using_indexes でインデックスを使っ
ていないクエリを全て記録
● 出力先はログまたはテーブル
– log_output=TABLE
● ログファイルはmysqldumpslow コマンドで解析
52. Too many connections
● ボトルネックが原因でクエリが処理できない
– 処理の完了待ちの接続が増加
– max_connections へ到達
– Too many connections!!
● ボトルネックの特定が重要
– テーブルロックの競合(MyISAM )
– 行ロックの競合( InnoDB )
– 更新が多い場合のログへの書き込み
– クエリの効率が悪すぎる
– CPU リソースの枯渇
– バッファが足りない
etc
53. クエリのチューニング
● EXPLAIN から実行計画を読み取る
– クエリの構造、インデックス、レコードアクセスタイプ、行数
● インデックスを付け替える
● オプティマイザの挙動を理解する
– アルゴリズム: NLJ 、BNLJ 、BKAJ 、ICP 、ECP など
– ヒント:使用するインデックスの指定、JOIN の順序固定
55. SHOW コマンド
● 設定値
– SHOW GLOBAL VARIABLES
● 統計情報
– SHOW GLOBAL STATUS
● レプリケーション情報
– SHOW SLAVE STATUS
– SHOW MASTER STATUS
● InnoDB の情報
– SHOW ENGINE INNODB STATUS
●
● テーブル定義
– SHOW CREATE TABLE
etc...
56. INFORMATION_SCHEMA
● SHOW コマンドをも凌駕する情報量
– バージョンを追うごとに内容が充実
– SHOW コマンドでは得られない情報多数
● SELECT でアクセス可能
– 必要な情報を得るため柔軟に絞り込みが可能
– JOIN 、サブクエリを利用可能
– GROUP BY による統計
– CASE 句による柔軟な出力
● よく使うSELECT にビューを定義可能
– 作業の効率化
57. PERFORMANCE_SCHEMA
● パフォーマンス統計用のカウンタの集合体
– かなり細かいデータまで取れる
– バージョンを追うごとに拡充
– メモリ消費大なので注意
● ストレージエンジンとして実装されている
– 設定用のテーブルもある( UPDATE で設定)
● ps_helper
– PERFORMANCE_SCHEMA を活用するためのビュー集
– http://www.markleith.co.uk/ps_helper/
● MySQL Workbench
– GUI からps_helper を利用
58. ログ
● エラーログ
– 問題が起きたらまず見るべき
– クライアントへ返されたエラーは記録されない
● クライアント側でログを持っておくと便利
● 一般クエリログ
– MySQL サーバーへ送られたリクエストが記録される
– アプリケーションのデバッグ用
● スロークエリログ
– 時間がかかったクエリが記録される
● バイナリログ
– レプリケーションやPIT リカバリに利用される
59. デバッグ版
● デバッグ版の入手方法
– バイナリ版ならmysqlddebug
● ソースコード
– — 5.1 configure … withdebug
– 5.5 — cmake … DWITH_
DEBUG
● DBUG パッケージによるトレースが可能
– my.cnf にてdubug オプションを記述
– mysqld のコードパスが一目瞭然
● アサーションが通常版よりも多い
60. OS の情報を見る
● 統計情報( UNIX系OS )
– mpstat 、vmstat 、iostat 、top
● 最近話題のdstat
– /proc ファイルシステム
● システムの情報を一括で取得
– Windows
● アクセサリ>システム>システム情報
● systeminfo コマンド
– OSX
● system_profiler
– Oracle Solaris
● Oracle Explorer Data Collector
– Linux
● sosreport
61. MySQL Enterprise Monitor
● MySQL専用の商用監視ツール
– 200 を超えるアドバイザルールが総合的にヘルスチェック
– メール、SNMP による通知
– システムリソースや使用状況をグラフで表示
– パフォーマンス解析の強い味方
● 最強のモニタリング機能
– レプリケーションモニター
– クエリアナライザ
http://wwwjp.
mysql.com/products/enterprise/monitor.html
62. 商用サポート
● 解析のプロが責任をもってお答えします!!
– 自ら解析できる場合でも時間の節約に
● 商用ツールが利用可能( Enterprise Edition )
– MySQL Enterprise Monitor
– MySQL Enterprise Backup
– ThreadPool プラグイン
– 認証プラグイン
● 24時間365 日のサポート
– ただし日本語は平日9時—5時のみ(緊急時は英語で
問い合わせ)
64. 運用のベストプラクティス
一、 バックアップはしっかり計画的に!
二、 本番投入前に必ずアプリケーションのテストを。
● 負荷に見合ったハードウェアを選定。
三、 要件に合致した高可用性構成をチョイス。
● スタンドアロン? HA ?レプリケーション? MySQL Cluster ?
● ディザスタリカバリは必要か?
四、 もしもの時の保険=サポート
五、 セキュリティは万全に。
六、 監視は抜かりなく。
● トラブル、キャパシティ、性能
● 全部まとめてMySQL Enterprise Monitor はいかが?
七、 メンテナンスは無理のない計画+周到な準備を。
67. メンテナンスの種類
● テーブルのメンテナンス
– インデックスやカラムの追加・削除
– データ型変更
– 古いデータの破棄
– テーブルの破損
● アップグレード
– バグ修正
– 新しいバージョンの新機能を使いたい
● システム構成の変更
– オプションの変更
– ディスクやCPU 、メモリの強化
68. テーブルのメンテナンス
● テーブル定義変更
– MySQL 5.6 からInnoDB はオンラインDDL対応
● インデックスの追加・削除等がオンライン( Inplace )
● コピーが必要なケースは従来の動作
– ALTER TABLE は更新がブロックされる
– データを古いテーブルから新しい型のテーブルにコピー
– InnoDB Plugin/MySQL 5.5 のInnoDB ではインデック
ス部分だけを再構築( Fast Index Creation )
– MySQL Cluster はオンラインスキーマ変更に対応
● 古いデータの破棄
– RANGE パーティショニング
– DELETE を使う場合はこまめにCOMMIT
● OPTIMIZE 、ANALYZE etc
69. アップグレード
● 失敗しないためには周到な準備を!
– アップグレード後の動作確認
– 作業時間の見積もり
● 本番環境と同じデータを使って手順を確認
● レプリケーションの活用でダウンタイム縮小
– スレーブのバージョン > マスターのバージョン
– メジャーバージョンの差はひとつまで
– 手順
● スレーブをひとつずつアップグレード後、スレーブのひと
つをマスターに昇格
● 旧マスターを構成から切り離してアップグレード
● 必要があれば旧マスターへ切り戻し
71. トラブルシューティングのポイント
● 何が起きているのかを見極める。
– 仕様を理解する。
● 何が正常で何が異常なのか?
– OS に詳しくなる。
● 問題がOS からやってくることも多い。
– 自分でやってみる。
● 再現が出来ればこちらのもの!
● 的確に対策をする。
– 仕組みから何故対策が有効なのかを説明できる。
● トラブルに備える。
– トラブルに強い設定。
– トラブルが起きてもダメージが少ないようにする。
73. 宣伝2:新書籍の紹介
● リレーショナルデータベース実践入門(仮)
– リレーショナルモデル、SQL 、そしてDB 設計が主なテー
マの書籍です。
– どうやってリレーショナルデータベースを使いこなすか!
● リレーショナルモデル基礎編
– SQL とリレーショナルモデル
– 述語論理とリレーショナルモデル
– 正規化1: 関数従属性
– 正規化2: 結合従属性
– 直交性
– ドメインの設計
etc
● アプリケーション開発実践編
基礎の基礎から
よくある間違いを
指摘しつつ
– 履歴
– グラフ
– インデックスの設計
– ウェブアプリケーションのためのデータ構造
etc
応用まで