Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

業務アプリケーションの排他処理あるある

一言で「排他処理」と言っても、業務アプリケーション開発で「排他」というキーワードに関連する処理はいっぱいある。パッと思いつくだけでもこれだけある。

  • DBMSトランザクション分離レベル(排他レベル)
  • DBMSの共有ロックや排他ロック(WITH EXCLUSIVE LOCK)
  • DBMSのLOCK TABLEによる排他処理 (テーブルのバッチ更新中に、他のバッチやDBAの叩くSQLからテーブルを保護する)
  • アプリケーションフレームワークで行うDBレコードの楽観的排他処理
  • アプリケーションで実装するDBレコードの悲観的排他処理
  • アプリケーションで実装する業務閉塞処理 (バッチ処理中にオンライン業務が走らないようにする)
  • 並行処理用のライブラリ(JavaのConcurrentHashMapなど)
  • 処理系の同期化機構(Javaのsynchronizedなど)
  • リクエストごとのリソース分離(リクエストごとに一時ファイルを分けるとか)
  • 窓口制御による直列化(MaxThreadsを1にしちゃうとか)

これらの処理を混同せず、かつ使う時にはそれぞれの適不適を判断する必要があるわけです。開発者全員にこれらすべてを正確に理解してもらえるかと言ったら、そりゃ無理ってものです。
アーキテクチャ設計が不得手な人に無理に理解して設計してもらおうとすると、こんなことが起こる。全部本当に言われたことです。

  • 「DBの排他レベルはどうなってますか?」と聞くと「楽観排他をしてるからDBの排他レベルは大丈夫です!」と言われる
  • 「楽観排他処理のテストが抜けてませんか?」と聞くと「同じユーザが複数同時にログインすることはないからテストしてません」と言われる
  • 「これだと処理が競合しますよ」と言うと「処理が同時に行われる確率は低いから大丈夫、SHA-256だって『確率は低いから大丈夫』なんでしょ」と返される
  • 「これだと他のスレッドからデータが見えちゃいますよ」と言うと「ConcurrentHashMapを使ってるから他のスレッドから機密データが読まれることはありません」と返される
  • 「処理の追い越しが起こったときに問題が起こりませんか」と言うと「処理の追い越しはされないはずです、DBMSと同じです」と返される
  • 「複数の処理が同時に走ったらどうなりますか」と聞くと「CPUが1つだから複数の処理が同時に走ることはありません」と言われる
  • 「この処理が間に挟まったら他のリクエストから一時ファイルが見えてしまうのでは」と言うと「ソースのすぐ次の行でファイルを削除してるから間に処理は挟まりません」と返される
  • 「DBのテーブルに楽観排他用の連番がないですよ」と言うと「こう処理をしたら楽観排他がなくても大丈夫でしょ」と返される。パッと見大丈夫そうに見えるのだが、実は2多重には耐えられるが3多重になるとダメな処理になっている。

だから、アーキテクトとかテックリードとかが「こういう時にはこの処理を行うこと」 *1 というプロジェクト内ルールを決めたり、個々の開発者が考えなくてもいいようにアプリケーションフレームワークが面倒を見たりするわけです。

でもそうすると個々の開発者は、「フレームワークが面倒見てくれるんでしょ」と言って排他処理のことを考えなくなったり、業務知識の必要な排他処理の設計を「技術チームで検討してよ」と他へ押し付けたりと、排他処理のことをどんどん考えなくなっちゃう。そうするとアーキテクトやテックリードの裾野が狭くなっちゃうわけで、困ったもんですね。

*1:ちなみに、こういう場合にはあえて「排他」という言葉は使わない方が得策です。前述したとおり「排他」にはいろいろ種類があるもんだから、アーキテクトに言われたとおり実装してなかった担当者が「こっちの『排他』でも用は足りるんだからいいでしょ」と不適切な排他処理を自前で実装してしまったりするので……