一連のデータベース障害まとめ。(ちょっと技術的なことを。)
ここ数日、ご覧の皆さまには
本当にご迷惑をおかけしました。
申し訳ありません。
今日は障害の原因など
技術的なことも含めてまとめて書いておきます。
-----
まずは1つ目。
データベースの処理遅延について。
このサイトではデータベースアプリケーションに
「MySQL」を導入しています。
これにはいくつかのエンジンがありまして
高速処理が売りのMyISAMというエンジン
安定性が売りのInnoDBというエンジンがまあ主な2つ。
これまでずっとこのサイトでは
MyISAMというエンジンを使用して、まあそこそこなスピードで処理ができていました。
んで先日より、更新系と参照系で使い分ける
レプリケーションという機能を使用して
プログラムでのデータ登録を更新系データベースに
MySQLの内部処理で非同期で参照系データベースと一致させ
Webからの参照を参照系データベースで行うという処理に変えました。
(更新系データベースは今までのサーバ(ゲストOS)上に、
参照系データベースは今までのサーバが動いているホストOS上に配置)
これは今までのサーバの負荷を軽減させることが目的です。
そしたら先日…(月曜日だったかな?)
更新系と参照系の同期の際に、なぜか極端に時間がかかってしまい
参照系データベースをロックしてしまうという現象が発生。
つまり
更新系データベースがデータを更新するために参照系データベースを握ってしまい、
他から参照系データベースを使うことが一切できなくなってしまうという。
いわゆる「排他制御」ってやつです。
これ、MySQLのMyISAMエンジンの一つの欠点だと思うんですが
データ更新の際にはテーブルロック(対象のデータが入っている表を全部ロック)
してしまうんですね。
1頭の結果を更新するのに
すべての結果データ(約680万データくらいあります)のすべてをロックしてしまうため
更新処理に何らかの不具合があって時間がかかってしまうと
すべてのデータが表示できなくなってしまいます。
こら参った…と。
そこで
InnoDBというエンジンだと
テーブルロックではなく行ロック(更新対象の1データのみをロック)する構造なため
ロックによる遅延がなくなるのではないかと。
ということでエンジンをMyISAMからInnoDBへ変えて、
データもすべて変換して…ってのが火曜日の話。
んで昨日。冒頭に書いた通り、
高速だけどテーブルロック仕様のMyISAMから
安定していて行ロック使用のInnoDBに変えて
…当然高速ではなくなります。
単純なデータ取得処理でも数十秒かかるようになってしまい
結局はこれによってデータベース全体の負荷が上がり
ページの読み込みが遅いとか、ページが全く表示されないとか
様々な不具合が発生しました。
(ページが全く表示されないのはWebサーバの設定(同時アクセス数上限を超えたため))
単純なWebからの参照だけでなく
更新系データベースからの同期処理にも遅延が発生し…
ほぼ丸1日のデータ更新が遅れました。
本日夜勤明けで
データベースをInnoDBエンジンからMyISAMエンジンへ戻しました。
ですがこれでは根本的な解決策にはなってません。
(結局テーブルロックされる状態にもどってしまったので)
一応処理スピードは以前の状態に戻ったものの
何らかの原因でロックされてしまった場合に、きっとまた一気に高負荷になる可能性があります。
今後の方針としては
一応InnoDBを使うことを前提として
データベースそのものの設定の見直し(メモリの使い方とかファイルの設定など)
そしてSQL(データベースからデータを取得する言語)の書き方を変えるなどして
処理を少しでも高速に動くように直していくしかないんじゃないかと。
うちのデータベースにはさまざまなデータがたくさん入っていますから
どのデータを取得するときにどれくらいの時間がかかるのかを検証したうえで
その部分を中心に改善をしていかないとなりません。
-----
2つ目の障害は「G1予想大会」。
予想が投稿されず、表示もされない。でもポイントは消費しているというところ。
実はこれ、内部的には投票されていました。
ですが、一部のデータしか登録されておらず
データが不完全な状態で登録されていたために表示できませんでした。
この障害も
結局は「更新系」「参照系」の話に通じます。
参照系データベースはつい最近インストールしたもので
更新系データベースとはバージョンが異なります。
おそらくデータベースの仕様だと思うんですが
データベース上のテーブルに「デフォルト値」が設定されていない場合の挙動が
更新系データベースと参照系データベースとで異なっていました。
これまで普通に使用していたデータベース(今の更新系データベース)では
データを挿入する際、値を設定していない列に入るデータ(デフォルト値)は
’’(空文字)が標準で入りました。これは何の設定をしなくても。
んで最近インストールしたデータベース(参照系データベース)では
デフォルト値が設定されていない列に何も値をセットしないで挿入すると
エラーとなりデータが挿入されなくなりました。
これ…先ほどまで気づきませんでした。
今回の対応は
データベースの表のすべての列にデフォルト値を設定して
これまでと同じ挙動になることを確認しています。
次回の「G1予想大会」は2月の中旬ですので
それまでに再度確認のため動作試験を行ってみようと思っています。
-----
今朝夜勤から帰宅してデータベースの設定見直し後は
一応安定して動いているみたいです。
サーバの負荷もそれほど高くありません。
今後はSBメンバーズサイトをはじめ、各ページのリニューアルを進めるにあたり
データベースの構成変更が多く発生しますが
今回発生した障害の対応も兼ねてデータベースをいじっていく予定です。
今後も技術的なことも含め
気になったことは少しずつメモとしてブログにも残そうと思います。
改めて
皆さまにはここ数日多大なるご迷惑をおかけしましたことを
重ねてお詫びするとともに
今後もこんな拙い運営の「The Sunday Breeze」ではありますが
ご愛顧いただきますようよろしくお願い申し上げます。
本当にご迷惑をおかけしました。
申し訳ありません。
今日は障害の原因など
技術的なことも含めてまとめて書いておきます。
-----
まずは1つ目。
データベースの処理遅延について。
このサイトではデータベースアプリケーションに
「MySQL」を導入しています。
これにはいくつかのエンジンがありまして
高速処理が売りのMyISAMというエンジン
安定性が売りのInnoDBというエンジンがまあ主な2つ。
これまでずっとこのサイトでは
MyISAMというエンジンを使用して、まあそこそこなスピードで処理ができていました。
んで先日より、更新系と参照系で使い分ける
レプリケーションという機能を使用して
プログラムでのデータ登録を更新系データベースに
MySQLの内部処理で非同期で参照系データベースと一致させ
Webからの参照を参照系データベースで行うという処理に変えました。
(更新系データベースは今までのサーバ(ゲストOS)上に、
参照系データベースは今までのサーバが動いているホストOS上に配置)
これは今までのサーバの負荷を軽減させることが目的です。
そしたら先日…(月曜日だったかな?)
更新系と参照系の同期の際に、なぜか極端に時間がかかってしまい
参照系データベースをロックしてしまうという現象が発生。
つまり
更新系データベースがデータを更新するために参照系データベースを握ってしまい、
他から参照系データベースを使うことが一切できなくなってしまうという。
いわゆる「排他制御」ってやつです。
これ、MySQLのMyISAMエンジンの一つの欠点だと思うんですが
データ更新の際にはテーブルロック(対象のデータが入っている表を全部ロック)
してしまうんですね。
1頭の結果を更新するのに
すべての結果データ(約680万データくらいあります)のすべてをロックしてしまうため
更新処理に何らかの不具合があって時間がかかってしまうと
すべてのデータが表示できなくなってしまいます。
こら参った…と。
そこで
InnoDBというエンジンだと
テーブルロックではなく行ロック(更新対象の1データのみをロック)する構造なため
ロックによる遅延がなくなるのではないかと。
ということでエンジンをMyISAMからInnoDBへ変えて、
データもすべて変換して…ってのが火曜日の話。
んで昨日。冒頭に書いた通り、
高速だけどテーブルロック仕様のMyISAMから
安定していて行ロック使用のInnoDBに変えて
…当然高速ではなくなります。
単純なデータ取得処理でも数十秒かかるようになってしまい
結局はこれによってデータベース全体の負荷が上がり
ページの読み込みが遅いとか、ページが全く表示されないとか
様々な不具合が発生しました。
(ページが全く表示されないのはWebサーバの設定(同時アクセス数上限を超えたため))
単純なWebからの参照だけでなく
更新系データベースからの同期処理にも遅延が発生し…
ほぼ丸1日のデータ更新が遅れました。
本日夜勤明けで
データベースをInnoDBエンジンからMyISAMエンジンへ戻しました。
ですがこれでは根本的な解決策にはなってません。
(結局テーブルロックされる状態にもどってしまったので)
一応処理スピードは以前の状態に戻ったものの
何らかの原因でロックされてしまった場合に、きっとまた一気に高負荷になる可能性があります。
今後の方針としては
一応InnoDBを使うことを前提として
データベースそのものの設定の見直し(メモリの使い方とかファイルの設定など)
そしてSQL(データベースからデータを取得する言語)の書き方を変えるなどして
処理を少しでも高速に動くように直していくしかないんじゃないかと。
うちのデータベースにはさまざまなデータがたくさん入っていますから
どのデータを取得するときにどれくらいの時間がかかるのかを検証したうえで
その部分を中心に改善をしていかないとなりません。
-----
2つ目の障害は「G1予想大会」。
予想が投稿されず、表示もされない。でもポイントは消費しているというところ。
実はこれ、内部的には投票されていました。
ですが、一部のデータしか登録されておらず
データが不完全な状態で登録されていたために表示できませんでした。
この障害も
結局は「更新系」「参照系」の話に通じます。
参照系データベースはつい最近インストールしたもので
更新系データベースとはバージョンが異なります。
おそらくデータベースの仕様だと思うんですが
データベース上のテーブルに「デフォルト値」が設定されていない場合の挙動が
更新系データベースと参照系データベースとで異なっていました。
これまで普通に使用していたデータベース(今の更新系データベース)では
データを挿入する際、値を設定していない列に入るデータ(デフォルト値)は
’’(空文字)が標準で入りました。これは何の設定をしなくても。
んで最近インストールしたデータベース(参照系データベース)では
デフォルト値が設定されていない列に何も値をセットしないで挿入すると
エラーとなりデータが挿入されなくなりました。
これ…先ほどまで気づきませんでした。
今回の対応は
データベースの表のすべての列にデフォルト値を設定して
これまでと同じ挙動になることを確認しています。
次回の「G1予想大会」は2月の中旬ですので
それまでに再度確認のため動作試験を行ってみようと思っています。
-----
今朝夜勤から帰宅してデータベースの設定見直し後は
一応安定して動いているみたいです。
サーバの負荷もそれほど高くありません。
今後はSBメンバーズサイトをはじめ、各ページのリニューアルを進めるにあたり
データベースの構成変更が多く発生しますが
今回発生した障害の対応も兼ねてデータベースをいじっていく予定です。
今後も技術的なことも含め
気になったことは少しずつメモとしてブログにも残そうと思います。
改めて
皆さまにはここ数日多大なるご迷惑をおかけしましたことを
重ねてお詫びするとともに
今後もこんな拙い運営の「The Sunday Breeze」ではありますが
ご愛顧いただきますようよろしくお願い申し上げます。
このネタへのコメント:
コメントはありません。