トップ  > メモ一覧  > カテゴリ「高速化・負荷分散」の絞り込み結果 : 53件

53件中 1 〜 10 表示  1 | 2 | 3 | 4 ... 次の10件> 最後»

No.3683 RESET QUERY CACHE; クエリキャッシュ削除

RESET QUERY CACHE; クエリキャッシュ削除

mysql> SHOW STATUS LIKE'Qcache%';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| Qcache_free_blocks      | 1         |
| Qcache_free_memory      | 134133824 |
| Qcache_hits             | 43        |
| Qcache_inserts          | 38        |
| Qcache_lowmem_prunes    | 0         |
| Qcache_not_cached       | 29        |
| Qcache_queries_in_cache | 36        |
| Qcache_total_blocks     | 94        |
+-------------------------+-----------+
8 rows in set (0.00 sec)

mysql> RESET QUERY CACHE;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS LIKE'Qcache%';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| Qcache_free_blocks      | 1         |
| Qcache_free_memory      | 134199976 |
| Qcache_hits             | 43        |
| Qcache_inserts          | 38        |
| Qcache_lowmem_prunes    | 0         |
| Qcache_not_cached       | 30        |
| Qcache_queries_in_cache | 0         |
| Qcache_total_blocks     | 1         |
+-------------------------+-----------+
8 rows in set (0.00 sec)

更新:2011/05/20 10:42 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.3153【引用】NoSQLとしてMySQLを使うDeNAが、memcachedよりも高速な75万クエリ/秒を実現

NoSQLとしてMySQLを使うDeNAが、memcachedよりも高速な75万クエリ/秒を実現
2010年10月27日
タグ : MySQL , NoSQL , リレーショナルデータベース
モバゲーで知られるDeNAは、バックエンドデータベースにNoSQLを使っていません。なぜか? それはMySQL/InnoDB 5.1の環境で秒間75万クエリという、多くのNoSQLでも実現できないような高性能を実現しているから。DeNAの松信嘉範(まつのぶよしのり)氏 は、自身のブログにこんな内容のエントリ「 Using MySQL as a NoSQL - A story for exceeding 750,000 qp...

引用元

更新:2010/10/27 17:16 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.3032 max_connectionsのチューニング

max_connectionsのチューニング

<IFRAME WIDTH=150 HEIGHT=150 MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0 SCROLLING=no BORDERCOLOR="#000000" SRC="http://ngs.impress.co.jp/html.ng/site=TI&sp=ti_rec_bage&article=general"> <A HREF="http://ngs.impress.co.jp/click.ng/Params.richmedia=yes&site=TI&sp=ti_rec_bage&article=general"><IMG SRC="http://ngs.impress.co.jp/image.ng/Params.richmedia=yes&site=TI&sp=ti_rec_bage&article=general"></A> </IFRAME>    前回「第2回:負荷によるベンチマークを試す」の測定結果では、測定途中でmax_connectionsに達してしまい、計画していた測定を完了することができませんでした。そこでmax_connectionsを増やして、再度測定してみましょう。

   max_connectionsを増やすには2通りの手段があります。まず「/etc/my.cnf」に設定を追記する方法です。設定値は450に変更します。
[mysqld]
max_connections=450

   上記のように、[mysqld]の設定にmax_connections=450を追記します。その後、下記のコマンドでMySQLサービスを再起動してください。

# /etc/init.d/mysql restart

   一方、稼動中でもmax_connectionsは変更することもできます。その際は下記のコマンドを実行します。

$ mysql -u root -p
mysql> set global max_connections=450;

   いずれの方法でも結果は同じです。正しく変更できたかどうかを確認しましょう。


 
max_connectionsチューニング後の測定結果

   設定変更後、再度負荷テストを実施しました。以下がその結果です。

再度行った負荷テストの結果
図1:再度行った負荷テストの結果
(画像をクリックすると別ウィンドウに拡大図を表示します)

   今回は何とか同時接続数400まで測定できました。Queries_per_secが安定しているかどうかをあらわす境界線手前の測定では、Max_used_connectionsは128まで上昇しました。

   ではmax_connectionsの変更は性能向上に効果があったといえるかというと、そうでもないのです。なぜならQueries_per_secは最初の測定結果と同様の傾向で、性能低下も同じようなタイミングで発生しているからです。

   この結果から、無闇にmax_connectionsを増やしても性能は向上しないことがわかります。
 
1   2  3  次のページ

引用元

更新:2010/09/29 02:00 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.3031 max_connectionsとは

max_connectionsとは

<IFRAME WIDTH=150 HEIGHT=150 MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0 SCROLLING=no BORDERCOLOR="#000000" SRC="http://ngs.impress.co.jp/html.ng/site=TI&sp=ti_rec_bage&article=general"> <A HREF="http://ngs.impress.co.jp/click.ng/Params.richmedia=yes&site=TI&sp=ti_rec_bage&article=general"><IMG SRC="http://ngs.impress.co.jp/image.ng/Params.richmedia=yes&site=TI&sp=ti_rec_bage&article=general"></A> </IFRAME>    max_connectionsとは、「MySQLサーバが許可する、MySQLクライアントの同時接続最大数」です。この値は、MySQLクライ アントから無制限にコネクションが張られることによってMySQLサーバの負荷が増大し、最終的にはサービスが停止してしまう…といった事態を防ぐため に、同時接続してよいMySQLクライアントの数を制限することが目的です。

   さらにもう少しパフォーマンスに注目していい換えれば、MySQLサーバがもっとも良い効率で稼動できる範囲にMySQLクライアントの接続数を制限する、ということになります。

   あなたの環境ではいくつに設定されているでしょうか。パラメータ設定一覧を取得するコマンドは「第1回:定量的な情報収集のススメ」で説明した通りですので、以下のように実行してみましょう。
パラメータ設定一覧を取得
図1:パラメータ設定一覧を取得
(画像をクリックすると別ウィンドウに拡大図を表示します)

   特に意識して設定を変更していなければ、上記のようにデフォルト値である100が表示されるはずです。

   なお、実際に接続可能な数は「max_connections+1」で、SUPER権限を持つユーザ(rootなど)用に+1の接続が予約されてい ます。そうすることにより、max_connectionsに達してしまった場合でも、管理者は優先的にMySQLサーバへ接続して原因調査ができる仕組 みになっているのです。

 
現在の接続数確認方法

   先ほどの説明でmax_connectionsの設定値はわかりました。それでは今、どれくらいの数のMySQLクライアントが接続しているでしょうか。これについても、前回お話したように「mysqladmin」コマンドで取得可能です。

mysqladminコマンドを実行
図2:mysqladminコマンドを実行
(画像をクリックすると別ウィンドウに拡大図を表示します)

   Threads_cachedについては別途チューニング項目として取り上げますので後に譲るとして、その他のパラメータは以下の意味を持ちます。

パラメータ 意味
Max_used_connections これまでに記録された同時接続数の最大値
Threads_connected 現在開いている接続の数
Threads_created 接続を処理するために生成されたスレッド数
Threads_running スリープ状態になっていないスレッド数

表1:各パラメータの意味

   Max_used_connectionsはともかく、「スレッドって何?」という疑問が湧くかもしれません。ここでは単純化のために「スレッド数=MySQLクライアントの接続数」と理解してください。

   例えば図2の取得した情報を読み解くと「現在接続しているMySQLクライアントは2で、そのうち処理を実行中のものは1。これまでに接続された総数は12で、そのうち同時に接続された最大値は3である」となります。
 
1   2  3  次のページ

引用元

更新:2010/09/29 01:57 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2872 データベースサーバを複数台構成とか2010年代には流行らない

奥一穂さんの「ウェブアプリケーションサー バを複数台構成とか2010年代には流行らない」にフォローのような感じで。 例によってタイトルは煽りです。

奥一穂さんのエントリーでは、「5,000万PV/Month」という見積もりでアプリケーションサーバの台数を1台と計算していますが、これから は「1,000万PV/Day」を超えるサイトが多く生まれてくると予想しています。どんなサイトかというと、mixiアプリやモバゲーなどにソーシャル ゲームを提供するサイトです。

ソーシャルゲームサイトのキャパシティプランニングについては中澤さんのエントリーが参考になります。

最も人気がでた場合には数千万から数億PV/Dayという数字がならんでいます。怖い怖い

1,000万PV/Dayとなると、ピークのリクエスト数が平均の2倍として秒間に230リクエストとなります。

( 10,000,000 pv / 86400 sec/day ) * 2 = 231.481481


奥一穂さんの試算であれば、クアッドコアのサーバで秒間40回の処理が可能なので、6台程度のアプリケーションサーバがあれば、1日1,000万PV、月 に3億PVがさばけることになります。冗長性や安全をとるためにサーバを増やしたり、またクアッドコアを2つ搭載するマシンを採用することも考えられます が、この数字は自分の経験と比べても大きなずれはない数字です。

さて、ここからが本題で、1,000万PV/Day(秒間230 req/sec)には何台のデータベースが必要となるのでしょうか。Shardingを行ってデータベースの分散を行い多くのデータベースサーバを運用す る必要があるのでしょうか。

1リクエストにつき、SQLを8回発行した場合、秒間のクエリー数の最大は1840query/sec

230 req/sec * 8 = 1840 query/sec


このうち、5%程度が更新系のクエリーだったとしたら、更新系クエリは92 query/secとなり、

1840 query/sec * 0.05 = 92 query/sec


残りが参照クエリとなり、1748 query/secとなります。1リクエストあたりのSQL数や更新回数はアプリケーションにより大きく変動しますが、この程度のクエリー数の場合、 MySQLであれば1台で処理することは可能です。冗長性やバックアップのためのSLAVEサーバも追加して1組2台あれば安定稼働できます。

多くのSQLをさばくためには、クアッドコア以上のCPUや十分なメモリー、最適なデータベースサーバの設定や、効率のよいスキーマとSQLの設計 が必要です。Blogサービス等でなければデータをあまり蓄積しないのも重要です。MySQLであれば次の書籍が非常に参考になります。


もし、アプリケーションがもっと多くのクエリーを発行していたり、負荷が大きな場合には、安くなったSSDを使ったり、SLAVEサーバを追加して参照ク エリーを分散を行ったり、memcachedを利用して参照クエリを減らしたり、また、更新が多いテーブルだけを別のMySQLサーバに移動したり、デー タが単純なkey-valueであればTokyo TyrantRedisなどを利用すれば、データベースサーバを最小限に とどめることができます。

2010年代は手軽に購入できるようになった高性能なハードウェアでスケールアップし、OSやミドルウェアのチューニングを行うことで、アプリケー ションサーバ、データベースサーバを最小限に食い止め、サービスの収益率を改善してお給料を増やしてもらうのがよいのだろうと思う。

引用元

更新:2010/07/27 12:40 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2799 グリーの大規模分散ストレージ戦略(nanofs)

グリーの大規模分散ストレージ戦略(nanofs)

はじめに

はじめまして、グリー株式会社でエンジニアをしておりますkgwsと申します。今回は、グリー内で写真データの保存を行っている分散ストレージ (nanofs)を紹介させていただければと思います。

背景

弊社で運営させていただいている “GREE” ではユーザの写真や動画データを保存することができます。1億ユーザを目指すグリーは、ユーザの増加とともに写真や動画データは上限なしに増加していきま す。またユーザの皆様の大切なデータを失うことは許されませし、サービスを止めることも許されません。そんな状況の中、様々な技術や仕組みを使いサービス を運営してまいりました。

グリーのストレージの歴史は大きく分けて3世代がありました。

第一世代

第一世代ではアプリケーションサーバからNFSサーバをマウントし画像データを保存しておりました。簡単に導入できることと高価なサーバを使用すれ ば信頼性や安定性も保たれるので利用しておりましたが、アプリケーションサーバへのトラフィックが増加するとNFSへのトラフィックが増え、結果として NFSサーバのパフォーマンスが低下してしまいました。より高価なNFSサーバを導入すれば解決できるのですが安価なサーバでスケールアウトする仕組みを 導入しない限りエンドレスに高価なサーバを買いつづけなければいけないため早い段階で第二世代に移行されました。

第二世代

第二世代ではまずユーザ毎にパーティションを設定し1パーティションに対し2台のwebDAVサーバにダブルライトする仕組みを取り入れました。こ のことにより比較的安価なサーバでスケールアウトすることが可能となりサーバ費用を圧縮することができました。しかし、ユーザの増加とともにパーティショ ン数を増やさなければいけなくなり多くのwebDAVサーバを構築し運用しなければいけなくなるため、運用コストの増加が問題となりました。

スケールアウトしてサーバが増えることは必ずしもよいことではありませんでした。

サーバが増えることは壊れる可能性が増えユーザの皆様にご迷惑をおかけすることにつながります。大規模サービスではスケールアウトする仕組みを導入 することは重要なのですが同時に運用コストを減らしていかないとサーバの構築だけで一日が終わってしまいます。

第三世代

第三世代では、第二世代の仕組みに加え高価なサーバを購入することにより1台のサーバでより多くのユーザを処理できるようにパフォーマンスを向上さ せました。同時に1台のサーバ内の複数のHDDに画像データを保存するため信頼性を向上し、また多くの画像を保存できるためサーバの台数を減らすことがで きました。しかし1台のサーバへのトラフィックが上がりwebDAVサーバのアプリケーションが処理しきれなくなってしまいました。ある程度はアプリケー ションのチューニングにより改善を行うことは可能ですがトラフィックを分散させない限りいつかアプリケーションの限界を迎えることとなります。スケールア ウトするのでサーバを増やせばよいのですが今度はサーバ費用が増加することになります。

そんな、悩ましい日々がつづきました。

画像データをどのように管理し、どのように運用していくべきなのか。第四世代目はどうあるべきなのか。

次回にご期待ください!

うそです。

序盤で熱くなってしまい大変申し訳ありませんでした。

第四世代目のストレージシステム

これまでの経験上Webサービスに適したシステムは下記の3つです。

  • Scalability     (拡張性)
  • Availability    (可用性)
  • Maintainability (保守性)

この3つのことをグリーの一部では “SAM(サム)” と呼ばれております。テストにはでませんので忘れてください・・・。

Scalability(拡張性)は、スケールアウトすることがトラフィックを分散させることに繋がります。

Availability(可用性)は、一部のサーバで障害が発生しても安定して稼働しつづける冗長化が保たれたシステムが好ましいと考えます。

Maintainability(保守性)は、運用コストが低く運用し易いシステムであるべきと考えました。

この3つに当てはまるアプリケーションとなるとMogileFSが思い浮かんだのですがよりシンプルな構造の分散ストレージがよかったので自社で開 発する道を選びました。

分散ストレージ(nanofs)構成

nanofsは、主に3つのプロセスで構成されております。

nanofsd(dispatcher)

  • アプリケーションサーバからリクエストを受け取り実際に保存されているnanofsnに振り分ける
  • 5つのHTTPメソッドをサポートしている(GET、PUT、DELETE、HEAD、MKCOL)
  • データベースに保存したデータの情報を送る
  • queueに処理の指示を送る

nanofsw(worker)

  • queueに送られた指示にしたがい非同期に処理を行う
  • 複数のnanofsnにデータをコピーする
  • nanofsnに保存されているデータを削除する

nanofsn(node)

  • データを保存する

特徴

nanofsは下記の特徴を持っています。

  • ファイル毎の分散
  • データベースとの通信以外HTTPで通信する
  • データベースはKVSを使用
  • 開発言語はRuby

さいごに

nanofsのソースコードはもし反響がございましたら公開させていただきたいと考えております。

次回はnanofsのHTTPメソッド毎の処理の流れについて書きたいと思います。

引用元

更新:2010/07/13 10:01 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2759 MySQLでサービス停止のないALTERTABLEの検討


MySQLでサービス停止のないALTER TABLEの検討

MySQLでテーブルへのカラム追加、インデックス追加やテーブルの再編成などを行うと、その間テーブルに共有ロックがかかってしまいます。そのためこれらのメンテナンス処理は、通常利用者の少ない深夜早朝帯にサービスを止めて実施する必要があります。本日はそれを無停止、オンラインのままでできないかという話題です。

基本的なアイデア

  1. メンテナンス対象の元テーブルをコピーして、作業用の仮テーブルを作ります
  2. 仮テーブルに対して、カラム追加などの変更を加えます
  3. その間、元テーブルに対して行われる更新処理について差分を記録しておきます
  4. 仮テーブルの変更が終わったら、記録しておいた差分データを仮テーブルに反映します
  5. 差分データの反映が終わったら、元テーブルと仮テーブルを入れ替えます

これと似たようなことを考えた方は結構いらっしゃるのではないでしょうか。ただ、言うは易し、行うは難しです。整合性がきちんと取れるかどうか分からない、こんな危険なことはできないというのが普通の反応だと思います。

openark kit

このアイデアを実装したプログラムがあります。openark kitoak-online-alter-tableです。

openark kitはイスラエル在住のMySQLコンサルタントShlomi Noach氏が開発したMySQLユーティリティ集です。10種類のプログラムから構成されており、すべてPythonで書かれています。ライセンスBSDです。類似のMySQLユーティリティ集としてはMaatkitが有名ですが、Webで探すとそれ以外にもさまざまなソフトウェアが見つかります。

oak-online-alter-tableの仕組み

oak-online-alter-tableがどのようにしてオンラインのままテーブル定義を変更するのか、その仕組みを確認していきましょう。これはMySQLの一般クエリログをONにしてプログラムを実行することで、簡単に調べることができます。oak-online-alter-tableの仕組みは、実際には上で述べた基本的なアイデアよりも少し複雑になっています。

1. 空の仮テーブルを作成する

CREATE TABLE … LIKE文を用いて、元テーブルと同じ構造の仮テーブルを作成します。データのコピーはまだ行いません。

f:id:sh2:20100703155806p:image

CREATE TABLE sbtest.__oak_sbtest LIKE sbtest.sbtest;

2. 仮テーブルに変更を加える

仮テーブルに対し、カラム追加、インデックス追加などの変更を加えます。

f:id:sh2:20100703155807p:image

ALTER TABLE sbtest.__oak_sbtest ADD test VARCHAR(10);

3. 元テーブルにトリガを作成する

元テーブルに対してAFTER INSERT、AFTER UPDATE、AFTER DELETEの3つのトリガを作成します。これらのトリガによって、元テーブルに対する更新が仮テーブルに伝播するようになります。MySQLのトリガはそれぞれのイベントに対して一つしか作成できないため、すでにトリガの存在するテーブルに対してoak-online-alter-tableを使用することはできません。

f:id:sh2:20100703155808p:image

CREATE TRIGGER sbtest.sbtest_AI_oak AFTER INSERT ON sbtest.sbtest FOR EACH ROW
    REPLACE INTO sbtest.__oak_sbtest (c, pad, k, id) VALUES (NEW.c, NEW.pad, NEW.k, NEW.id);
//
CREATE TRIGGER sbtest.sbtest_AU_oak AFTER UPDATE ON sbtest.sbtest FOR EACH ROW
BEGIN
    DELETE FROM sbtest.__oak_sbtest WHERE (id) = (OLD.id);
    REPLACE INTO sbtest.__oak_sbtest (c, pad, k, id) VALUES (NEW.c, NEW.pad, NEW.k, NEW.id);
END;
//
CREATE TRIGGER sbtest.sbtest_AD_oak AFTER DELETE ON sbtest.sbtest FOR EACH ROW
    DELETE FROM sbtest.__oak_sbtest WHERE (id) = (OLD.id);
//

それぞれのトリガを見てみると、INSERTイベントに対してはREPLACE文、UPDATEイベントに対しては DELETEおよびREPLACE文、DELETEイベントに対してはDELETE文が発行されています。UPDATEイベントに対して一旦DELETE を行っているのは、主キーを更新するSQLに対応するためです。

f:id:sh2:20100703155809p:image

4. 元テーブルから仮テーブルにレコードをコピーする

INSERT IGNORE文を用いて、元テーブルのレコードを仮テーブルにコピーします。仮テーブルにすでにトリガによってコピーされたレコードがある場合、INSERT IGNORE文はエラーを返すことなく単にそのレコードを無視します。

f:id:sh2:20100703155810p:image

INSERT IGNORE INTO sbtest.__oak_sbtest (c, pad, k, id)
    (SELECT c, pad, k, id FROM sbtest.sbtest
     WHERE (((id > @unique_key_range_start_0) OR ((id = @unique_key_range_start_0)))
            AND ((id < @unique_key_range_end_0) OR ((id = @unique_key_range_end_0))))
     LOCK IN SHARE MODE)

oak-online-alter-tableはすべてのレコードを一度にコピーするのではなく、デフォルトで1,000レコードずつコピーを行います。こうすることで、アプリケーション側の処理がロック待ちのタイムアウトで失敗することを防ごうとしています。また、システムが過負荷になることを防ぐため、1,000レコード処理するごとにスリープ時間を設けることもできるようになっています。

f:id:sh2:20100703155811p:image

5. 元テーブルで削除されたレコードを、仮テーブルから削除する

INSERT IGNORE文によるレコードのコピーには、一つだけ元テーブルと仮テーブルの間に不整合を生じさせるパターンがあります。それは次の図に示すような、DELETE文とINSERT IGNORE文が同時に発生するパターンです。

f:id:sh2:20100703155812p:image

DELETE文によるレコードの削除がCOMMITされる前にINSERT IGNORE文が発行されると、一度は削除されたレコードがINSERT IGNORE文によって復活してしまいます。これに対処するため、oak-online-alter-tableはレコードのコピー後にもう一度テーブルをスキャンし、元テーブルで削除されているレコードを仮テーブルからも削除します。

f:id:sh2:20100703155813p:image

DELETE FROM sbtest.__oak_sbtest
WHERE (((id > @unique_key_range_start_0) OR ((id = @unique_key_range_start_0)))
       AND
      ((id < @unique_key_range_end_0) OR ((id = @unique_key_range_end_0))))
  AND (id) NOT IN
      (SELECT id FROM sbtest.sbtest
       WHERE (((id > @unique_key_range_start_0) OR ((id = @unique_key_range_start_0)))
              AND
              ((id < @unique_key_range_end_0) OR ((id = @unique_key_range_end_0))))
      )

6. 元テーブルと仮テーブルをリネームし、旧:元テーブルを削除する

RENAME TABLE文を用いてテーブルの名前を変更します。MySQLのRENAME TABLE文は、複数のテーブルに対してアトミックに名称変更を行うことができます。最後に旧:元テーブルを削除して、作業完了です。

f:id:sh2:20100703161626p:image

RENAME TABLE sbtest.sbtest TO sbtest.__arc_sbtest,
             sbtest.__oak_sbtest TO sbtest.sbtest;
DROP TABLE IF EXISTS sbtest.__arc_sbtest;

修正パッチ

現在公開されているopen arkバージョン111のoak-online- alter-tableには、テーブルの一意キーが数値型(TYNYINT、SMALLINT、INT、BIGINT)の場合に内部で型変換のエラーが発 生してしまうという不具合があります。また、テーブル情報を取得するために最初にごく短い時間テーブルロックをかけるのですが、更新負荷の高い状況ではま れにトリガの存在するテーブルに対するLOCK TABLESが失敗するという問題があります。これら二つの問題に対処する修正パッチを作成したので、オリジナル版が改修されるまでの間、当面このパッチをご利用いただければと思います。

*** oak-online-alter-table_org	2010-07-03 19:42:08.000000000 +0900
--- oak-online-alter-table	2010-07-03 20:04:25.000000000 +0900
***************
*** 726,732 ****
                      AS ratio_complete
                  """
              ratio_complete = float(get_row(ratio_complete_query)["ratio_complete"])
!             verbose("%s range (%s), (%s), %s" % (description, ",".join(unique_key_range_start_values), ",".join(unique_key_range_end_values), get_progress_and_eta_presentation(elapsed_times, elapsed_time, ratio_complete)))
          elif unique_key_type == "temporal":
              ratio_complete_query = """
                  SELECT
--- 726,732 ----
                      AS ratio_complete
                  """
              ratio_complete = float(get_row(ratio_complete_query)["ratio_complete"])
!             verbose("%s range (%s), (%s), %s" % (description, ",".join(map(str, unique_key_range_start_values)), ",".join(map(str, unique_key_range_end_values)), get_progress_and_eta_presentation(elapsed_times, elapsed_time, ratio_complete)))
          elif unique_key_type == "temporal":
              ratio_complete_query = """
                  SELECT
***************
*** 935,942 ****
  
              shared_columns = get_shared_columns()
  
-             create_custom_triggers()
              lock_tables_write()
              unique_key_min_values, unique_key_max_values, range_exists = get_unique_key_range()
              unlock_tables()
  
--- 935,942 ----
  
              shared_columns = get_shared_columns()
  
              lock_tables_write()
+             create_custom_triggers()
              unique_key_min_values, unique_key_max_values, range_exists = get_unique_key_range()
              unlock_tables()
  

動作確認

実際に、oak-online-alter-tableの動作を確認してみましょう。

今回はまずSysBenchのテーブルを用い、これに対して参照のみを行うトランザクションを1スレッド、更新を行うトランザクションを1スレッド立ち上げて、50ミリ秒間隔で繰り返し負荷をかけます。そして負荷テストの途中でテーブルの再編成を行い、スループットがどのように変化するかを確認します。SysBenchのテストデータはデフォルトで1万レコードとなっていますが、このテストでは10倍の10万レコードを用意しています。

負荷テスト開始10秒後にALTER TABLE文によるテーブル再編成をかけます。

mysql> ALTER TABLE sbtest ENGINE = InnoDB;
Query OK, 100000 rows affected (5.56 sec)
Records: 100000  Duplicates: 0  Warnings: 0

この処理には5.56秒かかりました。

続いて、負荷テスト開始30秒後にoak-online-alter-tableによるテーブル再編成をかけます。

$ oak-online-alter-table -u sbtest --ask-pass -S /var/lib/mysql/mysql.sock -d sbtest -t sbtest --sleep=20
-- Connecting to MySQL
Password:
-- Table sbtest.sbtest is of engine innodb
-- Checking for UNIQUE columns on sbtest.sbtest, by which to chunk
-- Possible UNIQUE KEY column names in sbtest.sbtest:
-- - id
-- Table sbtest.__oak_sbtest has been created
-- No ALTER statement provided
-- Checking for UNIQUE columns on sbtest.__oak_sbtest, by which to chunk
-- Possible UNIQUE KEY column names in sbtest.__oak_sbtest:
-- - id
-- Checking for UNIQUE columns on sbtest.sbtest, by which to chunk
-- - Found following possible unique keys:
-- - id (int)
-- Chosen unique key is 'id'
-- Shared columns: c, pad, k, id
-- Attempting to lock tables

-- Tables locked WRITE
-- Created AD trigger
-- Created AU trigger
-- Created AI trigger
-- id (min, max) values: ([1L], [100000L])
-- Tables unlocked
-- Copying range (1), (1000), progress: 0%
-- Will sleep for 0.02 seconds
-- Copying range (1000), (2000), progress: 1%
-- Will sleep for 0.02 seconds
-- Copying range (2000), (3000), progress: 2%
-- Will sleep for 0.02 seconds
-- Copying range (3000), (4000), progress: 3%
-- Will sleep for 0.02 seconds

…

-- Deleting range (96000), (97000), progress: 96%
-- Will sleep for 0.02 seconds
-- Deleting range (97000), (98000), progress: 97%
-- Will sleep for 0.02 seconds
-- Deleting range (98000), (99000), progress: 98%
-- Will sleep for 0.02 seconds
-- Deleting range (99000), (100000), progress: 99%
-- Will sleep for 0.02 seconds
-- Deleting range 100% complete. Number of rows: 0
-- Table sbtest.sbtest has been renamed to sbtest.__arc_sbtest,
-- and table sbtest.__oak_sbtest has been renamed to sbtest.sbtest
-- Table sbtest.__arc_sbtest was found and dropped
-- ALTER TABLE completed

こちらの処理には23.06秒かかりました。

このときSysBenchのスループットは以下のように変化しました。

f:id:sh2:20100703214113p:image

ALTER TABLE文によるテーブル再編成時はテーブルに共有ロックがかかるため、更新トランザクションが完全に止まってしまうことが分かると思います。一方oak-online-alter-tableによるテーブル再編成では、スループットこそ落ちるものの更新トランザクションが完全に止まることは避けられています。

CPU使用率は以下のように変化しました。

f:id:sh2:20100703214117p:image

ALTER TABLE文が完全にCPUを使い切ってしまうのに比べ、oak-online-alter-tableはスリープ時間を設定することで負荷の高騰を抑えられていることが分かります。

まとめ

MySQLのALTER TABLE文は現状内部的にテーブルコピーを伴っており、テーブルへのカラム追加、インデックス追加やテーブルの再編成などを行うとテーブルに共有ロックがかかってしまいます。そのためこれら各種メンテナンス作業をオンラインのままで行うことは難しく、これがシステムの無停止運用を妨げる要因の一つとなっていました。こうしたオンラインメンテナンス機能は従来Oracleなど商用RDBMSが得意としてきたところですが、MySQLでもoak-online-alter-tableで示された考え方を応用することで、今後運用性を改善していけるのではないかと思います。

参考ですが、PostgreSQLにも同様の考え方に基づくpg_reorgというテーブル再編成ツールが用意されています。PostgreSQLは追記型アーキテクチャであることから、VACUUMというガベージコレクション処理を運用にどのように組み込むかがとても重要なのですが、pg_reorgによって運用性がかなり改善されました。こうした動きもおさえておきたいですね。


引用元

更新:2010/07/04 01:26 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2727 GREE製MySQLProxy

GREE製 MySQL Proxy

こんにちは。プラットフォーム開発部インフラチームのますやまと申します。

はじめに

梅雨が近づいてきてだんだん蒸し暑さを感じる季節になってまいりました。毎年この時期になると、我が家では梅酒を作ります。梅酒なんて完成品を買っ てくればいいじゃない、と思うかもしれませんが、市販品だとなかなか好みの味に出会えないものです。そこで梅を数kg買ってきて漬けるわけですが、毎年ホ ワイトリカーや焼酎、ブランデーと酒を変えてみたり、氷砂糖の量を変えてみたり、はちみつにしてみたりするうちに、自分の理想の味に近づいてきました。や はり完全に自分好みにできると満足度は高くなります。

普段、グリーではオープンソースのソフトウェアを使用することがほとんどですが、やりたいことと「ちょっとちがう」ということが多々あります。そこ で、複数のソフトウェアを組み合わせて何とか用途に合わせて使ったり、パッチを書いて挙動を変えてしまうのが一般的だと思いますが、やはり用途に合わせて 作ってしまうのが一番理想に近いものができあがります。というわけで、グリー独自で作っているソフトウェアの紹介をさせていただきたいと思います。

MySQL Proxy

MySQLへの接続proxyというとlvsを使用するのが定番で、最近ですと本家のMySQL proxyもあります。しかし、グリーの今のシステムに当てはめるとどちらもいまいちです。

グリーの要望としては

  • 今のアプリケーションの仕組みをまったく変えたくない
  • 複数あるスレーブのロードバランスをしたい。しかも個々のサーバの性能は違うかもしれない
  • マスターがダウンしたら自動的にマスターの切り替えをしてほしい

・・・3つめがとても野心的ではありますが、まあ、こんな感じのプログラムを作ってみました。

名前をg2proxyといいます。

全体構成

  • マスター向け接続とスレーブ向け接続を別のportで待ち受ける
    • 更新クエリと参照クエリをg2proxyが判別することはしませんリクエスト側で判別して投げ分ける必要があります。
  • スレーブは複数台設定し、負荷分散を行う
    • 複数台のスレーブサーバにリクエストを分散します。サーバ毎に重みづけを変えることもできます。
  • コネクションのプーリングを行う
    • 一度MySQLサーバとの間に確立したコネクションは保持し、次のリクエストの際に再利用します
  • マスター切り替えを自動的に実行
    • マスターのダウンを検知したら、スレーブの一台をマスターに昇格させ、サービスを続行します

性能

MySQLとの間に余計なことするものが入って中継をするので、当然ではありますが性能は低下するはずです。どれくらい低下するか計測してみました。

構成とスペック

CPU XeonE5504
Memory 24GB
HDD 200GB 15krpm
  • MySQLサーバ 1台
  • g2proxyサーバ 1台
  • 負荷をかけるクライアント 1台

負荷をかけるクライアント

MySQLサーバに接続

SELECT * FROM table WHERE id=????? という単純なリクエストを投げる

結果を取る

切断

という単純なサイクルを繰り返すテストクライアントを作成(C + MySQL API で書きました)

結果

※以下、単位は実行にかかった秒数となります

  1並列×10000回実行 10並列×10000回実行 100並列×10000回実行
mysql直接接続 8.059 23.161 202.396
g2proxy経由 9.592 22.343 184.570
性能比 84% 104% 109%

並列数が上がればg2proxy経由の数値がMySQL直接接続に近づくと予想していましたが、まさか超えるとは思いませんでした。MySQLはクライアントが多い状態での新規コネクション受け入れ時の処理に若干コストがかかってしまうようです。

試しに、g2proxyでコネクションプールをoffにして試してみました。

  10並列×10000回実行
MySQL直接接続 23.161
g2proxy経由(コネクションプール on) 22.343
g2proxy経由(コネクションプール off) 29.804

やはり遅くなりました。

おまけ

MySQLの認証が重いんじゃないかないか説がありますので、試しに計測してみました。

mysqldを skip-grant-tablesオプションを追加して起動し、同じテストをしてみます。

  1並列×10000回実行 10並列×10000回実行 100並列×10000回実行
MySQL直接接続 8.059 22.161 202.396
skip-grant-tables オプション追加 6.914 20.158 197.285

若干ではありますが向上しています。

さいごに

g2proxyはグリー内でさらなる実績を積んで公開しようと思っています。

その際にはぜひ使ってみてください!

引用元

更新:2010/06/24 00:25 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2570 2009-04-14MySQL5.1のmysqldumpslowで快速チューニング

2009-04-14 MySQL 5.1のmysqldumpslowで快速チューニング

MySQL 5.1のmysqldumpslowを使うとチューニングが楽になる!という話題です。

mysqldumpslowはもともとMySQLに付属しているツールで、スロークエリログを集計してくれるものです。これ自体はMySQL 5.1で特に変わったところはありませんが、スロークエリログ本体の方が機能強化されているため、組み合わせるとなかなか便利になっています。MySQL 5.1におけるスロークエリログの主な機能強化は以下の三点です。

  • long_query_timeに1秒未満の値を設定できるようになった。
  • 出力先を設定できるようになった。
  • これらの設定をオンラインで変更できるようになった。

これでどうなるかというと、MySQLの性能分析をしたいと思ったときに、サーバを止めずにその場で

mysql> set global slow_query_log = 1;
mysql> set global slow_query_log_file = '/tmp/test.log';
mysql> set global long_query_time = 0;

と打てることになります。スロークエリログの出力先を変更するとともに、long_query_timeを0にすることですべてのクエリを出力対象にしてしまいます。

その後サーバが過負荷になったりログでディスクが溢れたりしないかを注意深く監視しつつ、数十秒~数分待ってから設定を元に戻します。

mysql> set global slow_query_log = 1;
mysql> set global slow_query_log_file = '/var/lib/mysql/testsrv-slow.log';
mysql> set global long_query_time = 10;

書き出されたスロークエリログをmysqldumpslowにかけます。

$ mysqldumpslow -s t /tmp/test.log

すると以下のようなレポートが出力されます。負荷ツールにはDBT-1カスタマイズしたものを用いています。

Count: 769  Time=0.02s (16s)  Lock=0.00s (0s)  Rows=5.0 (3827), dbt[dbt]@localhost
  SELECT STRAIGHT_JOIN i_id, i_title, a_fname, a_lname FROM item, author WHERE
  i_title LIKE 'S' AND i_a_id = a_id ORDER BY i_title ASC LIMIT N

Count: 1271  Time=0.01s (8s)  Lock=0.00s (0s)  Rows=50.0 (63550), dbt[dbt]@localhost
  SELECT i_id, i_title, a_fname, a_lname   FROM item, author   WHERE i_subject = 'S'
  AND i_a_id = a_id   ORDER BY i_pub_date DESC, i_title ASC LIMIT N

Count: 49040  Time=0.00s (5s)  Lock=0.00s (0s)  Rows=1.8 (86230), dbt[dbt]@localhost
  #

Count: 710  Time=0.01s (4s)  Lock=0.00s (0s)  Rows=44.4 (31500), dbt[dbt]@localhost
  SELECT i_id, i_title, a_fname, a_lname FROM item, author WHERE i_subject = 'S' AND
  i_a_id = a_id ORDER BY i_title ASC LIMIT N

Count: 6916  Time=0.00s (3s)  Lock=0.00s (0s)  Rows=5.0 (34520), dbt[dbt]@localhost
  SELECT i_id,i_thumbnail FROM item WHERE i_id = (SELECT i_related1 FROM item WHERE
  i_id = N) OR i_id = (SELECT i_related2 FROM item WHERE i_id = N) OR i_id = (SELECT
  i_related3 FROM item WHERE i_id = N) OR i_id = (SELECT i_related4 FROM item WHERE
  i_id = N) OR i_id = (SELECT i_related5 FROM item WHERE i_id = N)

いかがでしょうか。サーバで実行されたすべてのSQLが種類別に集計され、合計時間の悪いものから順番にレポートされています。あとはこれを上から順に直していけば良いというわけです。

特に、MySQL 5.1では1回の実行には0.01秒しかかからないが、毎分1万回実行されるので実は負荷の大半を占めている、といったSQLを簡単に特定できるようになったところがポイントです。MySQL 5.0まではこのようなSQLを調べる手段がありませんでした。

また、Oracle経験者の中には上のレポートを見てピンときた方もいらっしゃると思います。そうです、これはSTATSPACKレポートのSQL ordered by Elapsedセクションにそっくりなのです。

SQL ordered by Elapsed time for DB: ORA111  Instance: ORA111  Snaps: 46 -47
-> Total DB Time (s):              50
-> Captured SQL accounts for   66.4% of Total DB Time
-> SQL reported below exceeded  1.0% of Total DB Time

  Elapsed                Elap per            CPU                        Old
  Time (s)   Executions  Exec (s)  %Total   Time (s)  Physical Reads Hash Value
---------- ------------ ---------- ------ ---------- --------------- ----------
     17.47          352       0.05   35.1      17.49               0  797834135
Module: dbdriver_o@sandbox03 (TNS V1-V3)
SELECT i_id, i_title, a_fname, a_lname FROM ( SELECT i_id, i_tit
le, a_fname, a_lname FROM item, author WHERE i_title LIKE :"SYS_
B_0" AND i_a_id = a_id ORDER BY i_title ASC) WHERE ROWNUM <= :"S
YS_B_1"

      4.08          627       0.01    8.2       4.23               0 4063139509
Module: dbdriver_o@sandbox03 (TNS V1-V3)
SELECT i_id, i_title, a_fname, a_lname FROM ( SELECT i_id, i_tit
le, a_fname, a_lname FROM item, author WHERE i_subject = :"SYS_B
_0" AND i_a_id = a_id ORDER BY i_pub_date DESC, i_title ASC ) WH
ERE ROWNUM <= :"SYS_B_1"

      3.77          354       0.01    7.6       3.44               0 4242795701
Module: dbdriver_o@sandbox03 (TNS V1-V3)
SELECT i_id, i_title, a_fname, a_lname FROM ( SELECT i_id, i_tit
le, a_fname, a_lname FROM item, author WHERE i_a_id=a_id AND a_l
name LIKE :"SYS_B_0" ORDER BY i_title ASC ) WHERE ROWNUM <= :"SY
S_B_1"

これもSQLを種類別に集計して、合計時間の悪いものから順番にレポートしてくれるものです。STATSPACKはOracle 8iからの機能なのでかれこれ10年前からあるわけですが、このような仕事の生産性を上げるための機能について、MySQLもようやく商用のメジャーなRDBMS製品に追いついてきたのかもしれません。

と、ここまで持ち上げてきましたが、いくつか注意点があります。一つは全クエリをロギングするので当然サーバの負荷が上がってしまうということ。基本的には開発・試験環境で使うテクニックだと思います。もう一つはset global文の影響範囲です。set global文によって変更されたパラメータは、設定後に新規接続してきたセッションに対してのみ有効です。そのためTomcatなどコネクションプーリングを用いた構成では設定が即時反映されません。コネクションプーリングを用いている場合は、スロークエリログの設定後にアプリケーションサーバ再起動してください。

set global文の融通が利かない点はBug#38704GoogleMark Callaghan氏が報告しています。しかし「Not a Bug」ということで改善の予定はなさそうです。惜しいですね。

引用元

更新:2010/05/29 16:33 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ

No.2556【引用】PHPで、MySQLのコネクションプール

PHPで、MySQLのコネクションプール
たぶんPHPの技術者の中では当たり前のことかもしれない。
自分の技術・知識不足を露呈するエントリーかもしれないけど、きっと知らない人もいるはずなのでメモをかねてエントリー。

PHPを使っていて「MySQLの接続が遅い」と感じたことがないので、あまり意識したことはないんだけど、
心のどこかに「コネクションプールしたほうが良いよな」ってのがずっとあって、調べてみた。

自分のサイトもフォートラベルも、
本とか、その辺の解説サイトに書いてあるように普通につないで...

引用元

更新:2010/05/26 02:42 カテゴリ: MySQL  > 高速化・負荷分散 ▲トップ
53件中 1 〜 10 表示  1 | 2 | 3 | 4 ... 次の10件> 最後»

FuelPHP

Mac

フロントエンド開発

web開発

プロマネ

マネタイズ

プレゼン

webサービス運用

webサービス

Linux

サーバ管理

MySQL

ソース・開発

svn・git

PHP

HTML・CSS

JavaScript

ツール, ライブラリ

ビジネス

テンプレート

負荷・チューニング

Windows

メール

メール・手紙文例

CodeIgniter

オブジェクト指向

UI・フロントエンド

cloud

マークアップ・テキスト

Flash

デザイン

DBその他

Ruby

PostgreSQL

ユーティリティ・ソフト

Firefox

ハードウェア

Google

symfony

OpenPNE全般

OpenPNE2

Hack(賢コツ)

OpenPNE3

リンク

個人開発

その他

未確認

KVS

ubuntu

Android

負荷試験

オープンソース

社会

便利ツール

マネー

Twig

食品宅配

WEB設計

オーディオ

一般常識

アプリ開発

Python

サイトマップ

うずら技術ブログ

たませんSNS

rss2.0