devsの常識、dbaは非常識
DESCRIPTION
2013/09/14 at PHP Conference 2013TRANSCRIPT
MySQL Admin が見たDevs の常識、 DBA は非常識
2013/09/14yoku0825@MyNA
PHP Conference 2013
\こんにちは!/
● yoku0825● とある企業の DBA● MySQL 歴 5 年くらい
● オラクれない● ポスグれない● 嫁の夫● せがれの父
● 日本 MySQL ユーザ会 (MyNA) のスベり担当
\しゃべること!/
● 日常的に MySQL のソースコードに触れる変態DBA がフツーの Devs に投げた愛のマサカリ集( のつもり )● ウチの開発言語は PHP > Java >> Ruby らしいです
● ウチでは DBA がサーバーの構築、 Devs が設計・テーブル構築・運営、 DBA はトラブルシュートや改善提案 ( 運用 ) 、というサイクルで回しています。
それでは Devs からのお便りを紹介していきます
yoku0825 さんこんにちは。
現在 MySQL 4.0 を使用しているサービスがあるのですが、このたびサーバーのリプレースに伴いMySQL 5.6 を導入したいと思っています。
最新版なので特に問題なく移行できると考えていますが、注意するポイントなどがあれば教えて下さい。
( 30 代・東京都・ Perl Monger )
( ゚ д ゚ ) えっ
● レプリケーションを使ったバージョンアップ
● 旧バージョンのスレーブがある場合、マスターのバージョンアップをかける前に 1 台ずつ切り離してバージョンアップしておく。
● スレーブを全部バージョンアップできたら、新バージョンのスレーブ 1 台を使ってカスケードレプリケーション構成にしておく。
● どこかのタイミングで新バージョンのスレーブをマスターとして参照するように切り替える。
● 旧マスターをバージョンアップして新マスターのスレーブにしてしまう。
● 停止時間は切り替え時間だけで済む。
● オフラインバージョンアップ
● データファイルに互換性があれば、 mysqld 停止 ⇒ バイナリー入れ替え ⇒ 起動 ⇒ mysql_upgrade で OK 。
● データファイルの互換性がなければ mysqldump でダンプして新しいmysqld にリストアする(最後の手段)
● ダンプの SQL 自体互換性がなくてちょっといじらないといけない場合も。
● 基本的にレプリケーション , オフラインバージョンアップできるのは 1 つ上のメジャーバージョンまで。
● MySQL 3.23.31(2001/01) ~ 3.23.58(2003/9)● MySQL 4.0.12(2003/03) ~ 4.0.30(2007/02)● MySQL 4.1.7(2004/10) ~ 4.1.25(2008/12)● MySQL 5.0.15(2005/10) ~ 5.0.96(2012/03)● MySQL 5.1.30(2008/11) ~ 5.1.71● MySQL 5.5.8(2010/12) ~ 5.5.33● MySQL 5.6.10(2013/02) ~ 5.6.13
● 4.0 -> 4.1 -> 5.0 -> 5.1 -> 5.5 -> 5.6 と上げるといっても難しいので、サービスを止めて mysqldump でどれだけ速く上げられるか。
Perl Monger さん、お便りありがとうございます。
バージョンアップの決意が 5 年ほど遅かったようです。バージョンアップそのものもそれなりに大変ですが、アプリケーションがそのまま動くかどうかのテストや改修の方が余程大変だと思います。
わたしも頑張るので Perl Monger さんも頑張ってください。
はい次のお便り
yoku0825 さんこんにちは。
私のサービスで使っている MySQL は既にレコードが 3000 万件になり、パーティショニングしてもSELECT が重くなってきました。 InnoDB バッファプールも Free buffers が 0 です。
そろそろスケールアウトを考えているのですが、どのような構成が良いでしょうか?
( 30 代・東京都・じゃばー)
( ゚ д ゚ ) えっ
● スケールアウトのしどき● 物理的にメモリー、ストレージが足りない時。
– アプリケーションで水平シャーディングしてやるのが多い。– 参照局所性が高い場合はメモリーが尽きてるように見えても意
外と大丈夫なこともある。● SHOW ENGINE INNODB STATUS のバッファプールヒッ
ト率とかを参考に。● INSERT, DELETE が重い時はパーティショニングが有効。
– PRIMARY KEY 直打ちのケースしか SELECT は速くならない。
● SELECT, UPDATE が重い時は大概そこじゃない。
– イケてないクエリー、イケてないインデックス、イケてないパラメータ。
– SHOW FULL PROCESSLIST の State を見てみると、 copying to tmp table とか書いてあったりしないかい?
– スケールアウトさせてもまたへたれるパターン。
● スケールアップのしどき● 物理的にメモリー、ストレージが足りない時。
● IOPS を上げるようなスケールアップよりは余るまでメモリーを積む方がコストパフォーマンスが良い。
– RDS や EC2 だとこういう悩みはありそう。
– メモリーを積んでもパフォーマンスが伸びなくなってから、更にパフォーマンスが欲しいなら IOPS 。
– とはいえクエリーが適度にチューニングされているのが前提なのはスケールアウトといっしょ。
– 高 IOPS な感じにするのであれば innodb_{read|write}_threadとか上げるんだけどあんまり情報無い。。前にベンチマークした時は {12|12} でデフォルトの {4|4} の 2 倍くらいスコア出た。
● 残念ながら CPU や NIC がネックになるほど綺麗にスキーマ作ってあってクエリーが綺麗な DB は今のところ見たことがない(´ ・ ω ・` )
じゃばーさん、お便りありがとうございます。
Free buffers のもうちょっと下にある、 Buffer pool hit rate も見てあげてください。これが 1000/1000 のうちは取り敢えず大丈夫です。
というか、 SELECT が重いのはまずクエリーをチューニングしましょう。。
はい次のお便り
yoku0825 さんこんにちは。
私のサービスでは新規のテーブルを作る時には必ず開発担当同士でスキーマと SQL のレビューをしていますが、先日 DBA が「そのレビューは何をレビューしているんだ」とケチをつけてきました。
勿論、結果が正しく返ってくるか、インデックスが使われているかをどうかを確認しているのですが、どうすれば彼に伝わるでしょうか?
( 20 代・東京都・ぺちぱー)
( ゚ д ゚ ) えっ
● SQL レビュー?● 文化な話もあるけれど。
● 「今」「想定通りのインデックスで」「想定通りの結果が返ってくる」のは、ある意味当たり前というかなんと言うか。。
● 今よりレコード件数が増えても、「想定通りのインデックスで」「想定している範囲のレスポンスで」結果が返ってくることも勘案してください。
● EXPLAIN の select_type が DEPENDENT SUBQUERY 、 typeが ALL 、 Extra が Using temporary table や Using filesort の場合は大体件数が伸びると重くなってきます。
– イケてないクエリーはデータの件数が増えれば増えるほど加速度的に重くなっていくパターンが多いので、テストデータの件数や分布も大事。
ぺちぱーさん、お便りありがとうございます。
うるさい場合、「 mysqladmin にinnodb_buffer_pool_dump_now インプリメントできない?」とでも振っておくと勝手にパッチ書き始めて黙ると思います。
ただ、 SQL レビューはもう少しデータが増えた時のことも考えてやっていただけるとお互い幸せになります。よくわからなければ DBA に聞いてください。
はい次のお便り
yoku0825 さんこんにちは。
最近、親テーブルと子テーブルの間でデータ不整合が頻発し対応に追われています。
簡単に自動化する方法はあるのでしょうか?
( 30 代・東京都・じゃばー)
( ゚ д ゚ ) えっ
● 外部キー制約● これ嫌いな人多いですよね。
● 嫌いな理由ベスト (?)3 は、
– テスト目的などのテキトーなデータを突っ込もうとするとエラーが出る。
● その操作が不整合の原因になるからやめろってエラーなんですけどね。
– そもそも外部キー制約を追加する ALTER TABLE が転ける。● それってつまり既に不整合g
– 重くなりそう。● tpcc_mysql で試した時には重くなかった。
– 外部キー > セカンダリキー > キーなし– 誤差レベルしか違わなかったけど。
● これだけじゃなく、適切なトランザクションのコミット単位も大事。
じゃばーさん、たびたびのお便りありがとうございます。
不整合を自動で解消するよりも、そもそも不整合を起こしにくい仕組みを導入しましょう。
というかまず不整合徹底的に直さないと ALTER TABLE できませんので何というか一緒に頑張りましょう orz
はい次のお便り
いつまで続くんだこれ
yoku0825 さんこんにちは。
このクエリー、速くならない?
( 30 代・東京都・ 831 )
( ゚ д ゚ ) えっ
● 相関サブクエリー使ってる● サブクエリーの内側の WHERE 句で外側クエリーのテーブルのカ
ラム参照してるやつ。
– SELECT .., (SELECT .. FROM t2 WHERE t1.xx> t2.yy) FROM t1 .. WHERE .. みたいな。
● 相関サブクエリーは外側クエリーからフェッチした行数だけサブクエリーを実行するので、外側クエリーのテーブルが大きくなればなるほど一気に重くなる。
● CPU 使用率を跳ね上げることが多い。というか CPU 使用率が跳ね上がったら大量アクセスかこれを疑う。
● パズルだと思って JOIN に書き換えるか、中間テーブルやアプリ側に一度値を保持させてクエリーを分割する。
● EXPLAIN すら返ってこなくなるパターンはほぼこれ。
● PostgreSQL はこのへんもそつなくこなすイメージ。
● インデックスが足りない● MyISAM はテーブルスキャンでも割と速いけれど、そのノリで
InnoDB に向かうと地獄が見える。
● MySQL が 1 つのリレーションで使えるインデックスは基本的に 1つだけなので、重いクエリーには複合インデックスを作る。
– 基本その 1 、 WHERE 句の AND 条件でつながれているものを順番に並べる。
– 基本その 2 、それに ORDER BY で使われているカラムを足す。
– SELECT .. FROM .. WHERE c4= xx AND c2= yy ORDER BY c3 なら、 (c4, c2, c3)
– 不等号とか OR 演算子使ったりすると ORDER BY まで波及しないとか、 LIMIT 使ってるなら WHERE よりも ORDER BY を狙ってインデックス作ると速いとかこれ以外にもコツはある。
● 特に COUNT は全てインデックスで解決できないと非常に重い。
● パラメータがイケてない● 体感ではこのパターン少ない。
● innodb_buffer_pool_size は データ格納量 か搭載メモリー全体の75% くらい突っ込む。
– 仮想マシンで構築する時は、データ格納予想量の 1.35 倍を割当メモリーにしてる。
● MyISAM テーブルは key_buffer_size や OS のページキャッシュを使うので、その分 innodb_buffer_pool_size を下げないといけない。
– なるべくどちらか片方にした方がメモリーの奪い合いがなくて良し。
● SSD などの高速ストレージの場合は innodb_flush_method やinnodb_io_capacity でかなり変わる。
● マウントオプションに noatime 足すのも結構効く。
● query_cache_type= 1 はこのパターンに入るんだろうか。
831 さん、お便りありがとうございます。
MySQL はアホの子なので、難しいクエリーを投げるとなかなか返してくれません。 MySQL でも判るような簡単なクエリーに書き換えたり、インデックスでヒントをあげて下さい。
大事なことなのでもう一度言います。 MySQL はアホの子です。ナントカとハサミは使いようだと思って頑張ってください。
はい次のお便り
yoku0825 さんこんにちは。
イケてないクエリーが特定できない時やイケてない箇所が判らない時ってどーすんべ?
( 30 代・東京都・ 831 )
( ゚ д ゚ ) えっ
● そのままではスローログに載らないクエリー● SET GLOBAL long_query_time= 0.3; SET GLOBAL
log_queries_not_using_indexes= 1; とかして 10 分くらいサンプリングする。
– 大概死ぬほどスローログ吐くので、 pt-query-digest やmysqldumpslow と併用。
– 予めログをローテートさせておかないと混じって見にくい。● pager egrep -v "Sleep|handlersocket|Binlog Dump" からの SHOW
FULL PROCESSLIST を連打。
– 個人的にはこれお気に入り。
– TeraTerm 使ってると Recurring Command って設定があるので、これで 0.5 ~ 1 秒間隔くらいで連続実行させる。
– State に「今やってる処理」が表示されるので、ざっくりあたりをつけられる。
● どこがイケてないんだかいまいち判らないクエリー● まずは EXPLAIN
– Key で想定しているキーが使われているかどうか、 Key lengthが想定している長さで使われているか。
● (int, datetime, varchar(32)) のキーなのに Key length が 4だと、左端の int にしかキーが効いてない。
– Using filesort は意外と重い。 covering index か ORDER BY狙いのキーを作る。
● オプティマイザーは ORDER BY 狙いのキーよりもWHERE 狙いのキーの方を選びたがるので、 USE INDEXでキーを狙い撃ちしてやる。
● SET profiling= 1; からのクエリー実行からの SHOW PROFILE;
– たまに遅い、というようなケースには不向き。– 内部のステージごとに所要時間が表示されるので、再現性が
あるなら最強。
– 5.6 で deprecated に。
831 さん、お便りありがとうございます。
色々テクニックはあるのですが、深掘りしていくとそれなりに MySQL そのものの知識が必要になってきたりはします。
いつでも MySQL 専門の DBA に振ってあげてください。決して説明するのが面倒な訳じゃないです。
はい次のお便り
もう 1 つくらいいけるかな
yoku0825 さんこんにちは。
私はある企業で DBA を勤めていますが、となりのひとが MySQL をいじってばかりで Oracle やPostgreSQL に触ろうとしません。
どうしたら良いでしょうか?
( 30 代・神奈川県・となりのひと)
( ゚ д ゚ ) えっ
( ゚ д ゚ ) _ (__ つ /  ̄ ̄ ̄ / _ \ / /
( ゚ д ゚ ; ) _ (__ つ /  ̄ ̄ ̄ / _ \ / /
ちょうど良い時間になりましたので、今日はこのへんで。。
` となりのひと ' は俺の上長 (DBA チームのリーダー ) 。。
この番組は弊社 Devs のみなさんの ( 質問の ) 提供でDBA の yoku0825 がお送りいたしました。
See you next time!
ご清聴ありがとうございました
身近に DBA がいない方はぜひ、日本 MySQL ユーザ会に遊びにきてください!