自動化の落とし穴
グローバル社会は24時間眠らない。
「9時から5時まで働いて、土日は完全休日。」正月からスーパーが開いている現代ではそんな古き良き時代の働き方は皆無と言えるかもしれません。
私の場合、以前某官公庁で大型汎用計算機の運用に携わっていた頃は、朝7時に当番が早めに出勤してコンピュータを立ち上げ、夕方18時くらいには電源を落として帰るような運用をしていました。(当然土日は休みです。)
しかし、DBAとして本格的に働き始めた2000年ごろから、24時間止められない運用とその運用を支える仕組みを直に担当するようになりました。
24×365(24時間365日)運用というものは携わった者でなければ理解できないシビアな世界です。ちょうどこの頃はインターネットをビジネスで使うということが当たり前のようになっていった時期であり、世界規模(グローバル)にビジネスを展開することが多くの企業で求められ始めた頃でもありました。
私はスペシャリストとしてオンコールで対応する立場でしたが、運用エンジニアは3交代シフトで24時間365日運用を行うような体制でした。
この会社は主に日本国内の企業を対象にしていましたが、それでも24時間システムを維持管理する必要があります。
特にグローバルに事業を展開している企業はより高いレベルでサービスを提供するため、例えばOracle社のサポートは当時日本、米国、英国に拠点を持ち、サポート案件を拠点間でハンドリングすることで、シームレスで高度なサポートを提供しているというようなことを聞きました。
その他にも外国為替市場のように、業界全体がグローバルに広がっている場合の運用もシビアです。
あるFX会社におけるパフォーマンス問題
Oracle10gは2004年にR1がリリースされましたが、以下は比較的早い時期にOracle9iから10gR1にアップグレードした、とあるFX(外国為替証拠金取引)会社で実際に起きた事例を若干の脚色を加えて再現したものです。
FXにおける繁忙時間帯は夜の21時です。なぜなら世界の主要取引市場である東京、ロンドン、ニューヨーク市場はそれぞれ朝7時に開かれます。ニューヨーク市場は元々の規模が大きことや、東京・ロンドン市場の取引傾向の影響を受けるために、日本国内のFX個人投資家にとっても14時間の時差があるニューヨーク市場の動向は非常に気になるのです。仕事から帰ってきたサラリーマンが自宅のパソコンで取引を始める時間帯ということもあり、21時からの数時間は日本のFX業者にとって最もクリティカルな時間帯なのです。
問題は21時にニューヨーク市場が開いて、トランザクション数が次第に伸びてきた22時過ぎに起きました。
さっきまで何の問題もなかったOLTPの取引処理が全く無応答になってしまったのです。
秒単位以下で変動する為替レートに対しリアルタイムに処理が完了しなければならないのに、この状況は致命的でした。
注文や約定と呼ばれる処理が遅れてしまっているため、焦った個人投資家がさらに取引処理を行おうとしたのかもしれません。滞留したトランザクションが膨大になり、状況はさらに悪化していきました。
このようなタイミングでアプリケーションの変更を行うはずがありません。性能劣化の原因が不明のまま時間だけが過ぎていきます。
ついに運用責任者がデータベースの強制再起動を決断しました。
未処理のトランザクションはすべてロールバックされ、せっかくの注文処理が無効になってしまいました。
そればかりか、レートが大きく変動したことによる損失を少しでも小さくするための決済処理が無効になってしまったため、投資家によっては大きな損失が発生してしまったかもしれません。
ほとんどの投資家はネット上で取引を行っているため、深刻なシステム障害はネットの掲示板等で瞬時に広まります。業者にとって投資家に対する補償等だけでなく、悪い評判が拡散してしまうということも大変にダメージが大きなことなのです。
障害の真相
後日、障害の原因を特定することができたのですが、それは唖然とするものでした。
まず初めに障害の背景となった事情について触れておきます。
Oracle10gからルール・ベース・オプティマイザ(RBO)がサポートされなくなりました。RBOで開発していた頃は、FROM句の後に記述するテーブルの順序を入れ替えただけで実行計画がガラッと変わり、パフォーマンスが大きく異なることがよくありました。
具体的には、レコード件数の多い順に記述するような原則で
FROM TBL-A(件数大),TBL-B(件数中),TBL-C(件数小)
のような感じで記述します。(この最適な順番を見つけるのが開発者の腕の見せどころでもありました。)
従って、テーブル件数が大きく変動するような場合は、なかなか開発者の意図した結果とならず苦労したという経験は、ベテランのOracle開発者であれば誰でも1つや2つ持っているのではないでしょうか?
ところが、Oracle10g 以降でコスト・ベース・オプティマイザ(CBO)のみになってから、世界は大きく変わりました。データ件数が変動しても統計情報を正しく取得していれば、最適な実行計画を必要に応じて算出してくれる、という理想のオプティマイザがCBOなのです。
前回のルート検索の例で言うと、渋滞情報をリアルタイムに収集して場合に応じた経路を示してくれるという機能がCBOに求められているのです。
つまり、地図上の最短距離だけでルートを示してくれるのがRBOで、渋滞情報を加味したルートを示すのがCBOなのです。
また、カーナビの渋滞情報が変わることに対するルート計算は比較的柔軟に再実行できるような気がしますが、実行計画算出(解析)は負荷の高い処理故、Oracleでは解析済みSQL文を共有することでその負荷がなるべく小さくなるような仕組みになっています。
つまり、渋滞がされた後でもずっと迂回路を案内してしまうような難しさをCBOは併せ持っているのです。
しかも、「正しく統計情報が取得されている」状態でなければ最適な実行計画は算出されないのです。Oracle社はこれに対してテーブル・インデックスの統計情報をデフォルトで自動的に収集する機能を実装しました。
収集の対象となるテーブル・インデックスを特定する条件はありますが、自動統計情報収集処理は10gの場合毎日22時に起動されています。
ほとんどの企業にとって夜の22時はオンライン業務が終了し、バッチ処理も終わっている頃、というのが自動統計情報収集の仕組みを作った開発者の頭の中にあったかどうかはわかりませんが、デフォルト設定がそのようになっているというのは事実です。
日本のFX業者にとってこの仕様が最悪の結果をもたらす可能性があるということは残念ながらあまり知られていませんでした。
詳細は関知していないのですが、このパフォーマンス問題が発生した経緯や背景事情を以下の通り想像を交えてまとめてみます。
- 繁忙時間帯が夜21時過ぎから日付が変わるあたりまでということは前述の通りですが、ニューヨーク市場がクローズされてから東京市場がオープンされる翌朝7時までのごく短い間にバッチ処理は終了するようになっています。
- 通常の問題のない日においては22時に自動統計情報収集処理が起動されていましたが、実行計画に影響を与えるようなデータの変動がバッチ処理で行われなかったため、統計情報が大きく変更され実行計画が突然入れ替わってしまうようなことはありませんでした。
- 問題の起きた日は、朝のバッチ処理でデータの大きな変動がありました。
- 21時の時点では前日の統計情報により良好な実行計画でOLTPが動いていました。
- 22時に通常と同じように自動統計情報収集処理が起動され、結果として良好な実行計画が変更されてしまいました。
- 実行計画算出処理(SQL文解析処理)は元々CPUリソースを消費するものでもあるので、それがOLTPに対して少なからず影響を与えていたというのも事実です。
再発防止策は?
障害の大きな原因として考えられるのは以下の2つです。
- 22時という極めてクリティカルな時間帯であるにも関わらず、自動統計情報収集処理がデフォルトのまま起動されてしまった。
- 実行計画に影響を与えるようなデータの変更があり、実行計画が変更されてしまった。
このケースでは「実行計画が意図せず変更されてしまった。」という問題に対する対策としては、
- 自動統計情報収集処理を業務影響の少ない時間帯に変更する。
- 統計情報収集処理を必要最小限の実行にとどめ、毎日は実施しない。
- 実行計画に影響を与えることが予めわかっているテーブルは統計情報が変更されないようにロックする。
のような項目を実施したと聞いています。
変動するデータに応じて最適な実行計画を立案する仕組みが、Oracle10g以降の「自動化」機能で実現されたわけですが、自動化というのは決して万能ではありません。
上の対策はある意味せっかくの自動化を意図的に殺すことで、(最適ではないかもしれないけれど)安定した運用を実現するものです。
私は「自動化の落とし穴」というテーマで、今までこの事例をいろいろな機会において紹介してきたのですが、反面自動化を選択するか否かの二者択一という考え方で本当に良いのかということをずっと考えてきました。
つまり、自動化と非自動化の中間に「半自動化」という概念があっても良いのではないかというのがその結論であり、次回紹介する「オプティマイザ統計の保留」というあまり注目されていない機能の特徴でもあります。
次回へ続く