外部APIが同期コールバックで自DBへ書くなら、外部呼び出しをまたぐ親行ロックを避ける
データベース
テスト設計
外部API
並行制御
判断
運用
外部APIを呼ぶ処理が、外部サービスから同じアプリケーションへの同期コールバックを伴う場合、外部呼び出し中に保持するDBロックはコールバック側の書込経路まで含めて選ぶ。
親行を排他ロックしたまま外部APIの応答を待ち、コールバックがその親を外部キー参照する子行をINSERTする構成では、外部キー検査が親行の共有ロックを要求して待機する。呼び出し元はコールバック完了を待ち、コールバックは呼び出し元のロック解放を待つため、アプリケーションをまたいだ自己デッドロックになる。timeout後に子行だけ作成されれば、利用者へ秘密値を返せないまま有効な資格情報が残るなど、部分成功も起こり得る。
この条件では、外部呼び出しをまたぐ親行ロックを避け、コールバックのDB経路と干渉しない排他機構を選ぶ。候補はDBのセッション単位ロックや、外部キーで親へ連鎖しない専用mutexである。採用前に、排他対象となる全mutation経路が同じロックを見ることと、外部呼び出し後の条件付き更新・補償処理が不変条件を守ることを確認する。
検証は手動でロックだけを取るテストではなく、実際のapplication serviceを起動し、外部client stubが応答する前の窓で、別接続からコールバック相当の子行INSERTを実DB・外部キー有効で行う。短いlock wait timeout内に成功することをoracleにすれば、外部呼び出しをまたぐ親行ロックの再導入を検知できる。