2000年−2001年
DBエンジンの要の機能と言えば、それは排他制御と言われる、データベースへの同時アクセスの制御です。
何十台のクライアントマシンから同じテーブルに対して更新がかかると、他のマシンの要求を待たせた上で1台ずつ順に要求を処理していく必要があります。ここらへんをいい加減に作ると、ACCESSの初期のバージョンのように原因不明のデータベースの破損が発生します。
私たちのDBエンジンも、このデータベースの破損に見舞われました。
破損と言っても様々な現象があります。
初期の頃は、排他制御を行うための基本の機能であるロックが効かないために同じ出荷番号が採番されるという現象で、本来別々の伝票にならなければならないのに、一つの伝票になってしまうと言うものです。この欠陥は致命的です。こんなことが起きてしまえば、全く使い物にはなりません。
よくよく調べると、ロック機能がおかしいのではなく、コミット命令というWindowsAPIが機能していないことが判明しました。それが判ったのはいいのですが、替わりのAPIが見つかりません。試行錯誤の末、別のAPIで問題が起きなくなることが判りました。問題が起きてから解決するまでの1ヶ月間、ほとんど寝るまもなく調べ続けました。
そして、数十台規模の運用で、最後まで残った破損の現象がインデックスの破損です。
このストーリーの2回目にも出てくるインデックスが、突然おかしくなる現象です。どうおかしくなるかというと、2回目の話でIBと書いたインデックスブロックの一つの中身が、突然まるで関係のない別の内容に置き換わってしまうのです。
これには参りました。全く手がかりがつかめないまま1年以上が経過してしまいました。その間、大規模ユーザーの環境で2ヶ月に1回くらいの割合で発生します。
DBエンジンの完成
これも試行錯誤の末、手がかりを掴みました。2001年1月のことです。
3回目に書いたようにリエントラントな構造にするために、必要なメモリーはすべてdllの中で動的に確保し、それを、呼び出し側から渡されるポインタが指すエリアに格納していました。
この動的にメモリーを確保するAPIが、先のコミット同様機能していないのではという結論でした。リターンコードと呼ぶAPIからの戻り値はゼロ(正常終了)であるにもかかわらず、実際にはメモリーが確保できていなかったのです。何らかのタイミングで何兆回に一度の割合で発生する現象です。
IBを読み込むためのバッファと言われる領域も、当然動的に確保していました。その領域が、実は実際には確保されず、全く関係ない領域を使用していたために、せっかくバッファの内容を更新しても実際に書き込まれる内容が別の内容に置き換わってしまうと言う現象だったのです。
原因が判れば対策可能です。
メモリーの確保は、すべて動的に確保するのを止めて、呼び出し側に最初からマックスの静的メモリーを持たせることで、そのメモリーを使い廻す構造にコードを書き換えたのです。
すぐ対策版を組み込んで内部で入念なチェックの後、ユーザー環境に入れました。これから2ヶ月間、インデックス破損が発生しなければ対策できたことになります。
その期限であった5月31日までの間に、1件のインデックス破損も発生しませんでした。
bisonと私は、8年前とは違う、西麻布のとあるバーのカウンターで二人だけの祝杯を上げました。 KAI