Lazy Diary @ Hatena Blog

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

情報システムにおける「排他処理」のバリエーション

一言で「排他処理」と言っても、Javaで実装したWebシステムで「排他」というキーワードに関連する処理を考えただけでもこれだけある。初学者はこれらがごっちゃになることも多いんじゃないかと思うのだけれど、こういう切り口でノウハウをまとめた書籍とかってないんだろうか?

DBMSの話

  • トランザクション分離レベル
    • READ COMMITTEDやREPEATABLE READなど、分離レベルごとのDirty ReadやNon-Repeatable Readの有無の指定。DBMSインスタンスやセッション等の単位で指定する。DBMSの製品ごとに、デフォルトの分離レベル、READ UNCOMMITTEDの指定可否、クエリ単位での指定可否などが異なる。
  • 行ロック
    • SELECT FOR UPDATEなど、DMLDDL実行時のロック指定。同じようなクエリを実行しても、DBMSの製品ごとに取得されるロックの強度が異なる。また製品によってはロックエスカレーションの仕組みがある。
  • テーブルロック
    • LOCK TABLEによるテーブルロック。主にバッチ処理中に処理対象となるテーブルを保護したり、DBAの叩くSQLから保護したりするときに使う。
  • 行ロックやテーブルロック以外のロック
    • 製品ごとにロックのかかる単位が異なる。SQL Serverはロックエスカレーションがあるし、行単位以外にもページ単位でロックがかかったりする*1
    • MySQLl*2PostgreSQL*3にはアドバイザリロックの仕組みがある。

アプリケーション実装方法の話

  • DBレコードの楽観排他・悲観排他の選択
    • 楽観排他・悲観排他それぞれの実装方法の検討も含む。
  • 業務処理の設計時に考慮する業務閉塞処理やバッチウィンドウの分離
    • 夜間バッチのバッチウィンドウ設計の際に、同じリソースを使うバッチを同時に走らせない設計をする場合などがこれ。

アプリケーションフレームワークの話

  • DBレコードの楽観排他
    • 楽観排他処理の実装にJPA@javax.persistence.Versionを使う場合など。
  • リソース分離

言語処理系の話

  • 処理系組込みの同期化機構
    • Javaだとsynchronized
  • プロセス内の並行処理用のライブラリ
    • Javaだとjava.util.concurrent.ConcurrentHashMapなど。
  • 言語処理系のライブラリにおける同期化有無
    • JavaだとHashMapVectorの違いなど。
  • 言語処理系がライブラリとして提供するプロセス内同期化機構
    • Javaだとjava.util.concurrent.Semaphoreなど。
  • 共有リソースの分離
    • 複数プロセスから参照可能なリソースの分離。一時ファイル名を一意にする際にFiles.createTempFile()を使用するなど。

ミドルウェアの話

  • リクエスト窓口制御による直列化
    • TomcatMaxThreadsを1にするなど。
  • トランザクションごとのリソース分離
    • OLTPモニタにおけるSYSOUTデータセットの書き込み先ファイルの分離など。
  • アプリケーションサーバによるセッション分離
    • HttpSessionによるセッション単位の分離、ThreadLocalによるスレッド単位の分離など。

OSの話

  • プロセス多重起動禁止
    • .NETではSystem.Threading.Mutexを使う例が多いけど、Javaだと何かあるかな。
  • OSによるプロセス間の排他制御
  • OSのファイルロック
    • POSIXだとfcntl(2)、最近の*NIXであればflock(2)。ローカルのファイルシステム上や、最近のLinuxカーネルがNFSv3上のファイルをロックする場合は基本的にアドバイザリロックになる*4flock(2)が使えない状況、たとえば「これから作る予定だけどまだ存在しないファイルに対するロックを獲得する」のような場合は代替の方法を使う必要がある*5
  • 共有リソースの分離
    • 複数プロセスから参照可能なリソースの分離。出力ファイル名を一意にする際にユーザIDやUUIDを使用するなど。