ページ

2009年9月12日土曜日

『たとえ那由多の彼方でも、俺には十分すぎる』

0 件のコメント:
さてさて、先輩から、こないだ出たけいおん!のアルバムの特典であるバンドスコアを買い取った。
つい2週間ほど前に、Cagayake!GIRLSのバンドピースを購入したのに、Cagayake!GIRLSのスコアが買い取ったバンドスコアにも載っていて僕なみだ目wwwwだが、オフィシャルのやつはかなり正確で、バンドピースでは再現しきれてない部分も記載されているので、ガッツリ練習する。
先ずは、『ふでぺん~ボールペン』を弾けるようにしよう。このバンドスコア、けいおん!の歌の結構な数を網羅してるから、とても価値があるように思えるんだ。

持つべきはオタクの先輩だね。


部内の技術教育担当に選ばれた。僕は前線で開発を行ってるから、そこで得た実践的な技術を敷衍してほしいとのこと。
まあ僕が知ってるような実践知識でいいなら…ってか、僕なんてまだ入って1年半年ぐらいだから、実践的な技術ってもたいしたことない。どっちかって言うと、僕は理論7割実践3割って感じだ。セオリーの類は納得出来るまで色々調べてきたからね。
理論の全てが実践で役立つわけではない。が、実践で理論が必ず得られるわけではない。だから、僕はそのお手伝いと言うわけだ。誰もがより抽象的に、複雑なソフトウェア開発が行えるように。

先日、某国で稼動しているアプリケーションで問題が発生していると聞いた。
それは僕の担当ではなかったのだけど、先輩から助言を求められ、僕は推断しか出来なかった。
「何故」それが起こるのかがわかっても、解決法がわからなかった。
結局、データベースのインデックスを変更してから挙動がおかしくなったから、元に戻してみるということで話は済んだんだが(元に戻すというのは、リスクが最も伴わない堅実な方法)、再発を防ぐ手立てが見つかってない以上、放置しておくわけにもいかない。それに、似たようなことは必ずまたどこかで起こる。

何が起こっていたのか?
とあるデータ転送プログラムで、デッドロックが発生していた。
デッドロックとは、2つ以上のトランザクションがロックの奪い合いをすることで「永遠の待ち状態」が起きる論理的な障害だ。厨二病的に言うと、エターナルウェイトコンディション。相手は死ぬ。
AというDBからBというDBへ定期的にデータを転送するプログラムと、Aに対して新規データを書き込むプログラムがある。
転送プログラムは、ストアドプロシージャなどを使わず、EXEをバッチで動かして、その内部でSQLコマンドを走らせていると言う少しお粗末な代物だった。
その転送SQLは、INSERT ~ SELECT。選択した表をそのままテーブルへINSERTすると言うSQL。
一方、Aへ書き込むプログラムは単なるINSERT。
さて、これでどうデッドロックが発生するのか?

考えられる唯一のパターンは、
①転送PGがAに対してINSERT SELECTコマンドを発行する。
②最初はSELECT文が走るので、Aには共有ロックがかかる。
③データ書き込みPGがAに対してINSERTコマンドを発行する。
④データ書き込みPGはAに占有ロックをかけたいが、共有ロックがあるので、それが外れるまで待つ。
⑤転送PGはSELECTで結果を得たため、占有ロックをかけてINSERTを行いたい。しかし、データ書き込みPGの占有ロックがある。
⑥めでたくデッドロック。

というものだ。が、これが何故今まで起こらなかったか、と言う疑問がある。
先輩は、「インデックスが変えられている」と言う話をした。運用担当者が恐らく何らかの理由で変更したのだろう。
インデックスが変更されてから、SELECT文の速度が目に見えて落ちたと言う情報も教えてくれた。

一応ピースは揃った。
つまり、インデックスが変更される前は、SELECTにかかる時間が非常に短かったため、共有ロックをかけている間に占有ロックをかけられると言うことが起きなかったからだ。
(それでも、可能性があると言う時点で『今までは運が良かった』と言う評価は免れない)
SELECTにかかる時間が長くなったから、全ての原因っぽい。

さて、これが確実だとすると、対処法としては、少なくともPGの変更が必要だ。
両方のPGに対して、キチンとしたトランザクション管理のコードを書く。INSERT SELECTが走る前には占有ロックをかけるようにする。
書き込みPGに対しては、占有ロックが検出された段階で待つように設定する。書き込みが失敗すると言うのが、要件的にマズイらしいからだ。

しかしながら、因果なことに、問題が解ったからと言ってすぐにPGを変更するわけにはいかない。そこはビジネスだ。
別の先輩曰く「ビジネスでは、ぞうきんは常にまだ絞れるようにしておけ」だそうで。
それに、会社としての取り決め・手順がある。面倒くさいことに。
今回の場合は、運用時点で発覚した『潜在』バグなので、緊急性はさほどない。起こる可能性があると言うだけで、インデックスの変更さえしなければ速度の問題は特に出ないため起こりようがないからだ。少なくとも、今までの稼動実績からして、問題が起こる可能性はほぼないと言って良い。
ただまあ、その教訓は敷衍するべきだろう。早ければ来月くらいに講習を依頼されるみたいなので、そこで話すネタとしてストックしておこう。