YASD-TECH
YASD TECH
# DB

advisory lock

投稿日:2026/6/19

更新日:2026/6/21

ttitleImage

はじめに

複数のアプリケーションプロセスやCI/CDジョブが、同じDBに対して同時に処理を走らせることがあります。
このとき「同じ処理は同時に1つだけ実行したい」という場面で使えるのが advisory lock です。

advisory lockとは

アプリケーションが任意の意味を持たせて使うDB側のロック機能です。

通常の行ロックやテーブルロックは、特定のテーブル・行・DDL操作にDBが意味を持たせて管理します。
一方で advisory lock は、ロック対象の意味をDBではなくアプリケーション側が決めます。

たとえば以下のような用途です。

  • バッチ処理を同時に1つだけ実行する
  • マイグレーションを同時に1つだけ実行する
  • 外部API同期処理の二重起動を防ぐ
  • 特定の業務ID単位で排他制御する

DBの機能か、ORMの機能か

advisory lock の仕組み自体は DBの機能です。

代表例:

  • PostgreSQL: pg_advisory_lock, pg_try_advisory_lock
  • MySQL: GET_LOCK, RELEASE_LOCK
  • SQL Server: sp_getapplock

ORMやマイグレーションツールは、このDB機能を利用して排他制御します。
つまり「ロック機構そのものはDB」「いつ・何のために使うかはアプリやツール側の実装」です。

通常のロックとの違い

行ロック

特定の行を更新・参照する処理を守るためのロックです。

SELECT *
FROM orders
WHERE id = 1
FOR UPDATE;

この場合、orders テーブルの特定行に対する同時更新を防ぎます。

advisory lock

テーブルや行とは直接関係ない、任意のキーに対するロックです。

SELECT pg_advisory_lock(12345);

この 12345 にどういう意味を持たせるかは、アプリケーション側が決めます。
たとえば 12345 を「日次集計バッチ用のロック」として扱えます。

PostgreSQLでの例

ロックを取得する

SELECT pg_advisory_lock(12345);

同じキー 12345 のロックを他のセッションがすでに持っている場合、このSQLは待機します。

取れなければ待たずに失敗させる

SELECT pg_try_advisory_lock(12345);

戻り値が true ならロック取得成功、false なら他のセッションがロック中です。

ロックを解放する

SELECT pg_advisory_unlock(12345);

セッション単位とトランザクション単位

PostgreSQLには大きく2種類あります。

セッション単位

SELECT pg_advisory_lock(12345);
SELECT pg_advisory_unlock(12345);

DB接続セッションに紐づくロックです。
明示的に解放するか、接続が切れるまで保持されます。

トランザクション単位

BEGIN;
SELECT pg_advisory_xact_lock(12345);
-- 処理
COMMIT;

トランザクション終了時に自動で解放されます。
解放漏れを避けたい場合はこちらの方が扱いやすいです。

Prismaでのadvisory lock

Prisma Migrate は、マイグレーションの同時実行を防ぐために advisory lock を使います。

対象になる主なコマンド:

  • prisma migrate deploy
  • prisma migrate dev
  • prisma migrate resolve

たとえばCI/CDで2つのデプロイが同時に走り、両方が prisma migrate deploy を実行すると、同じマイグレーションを同時に適用しようとして不整合が起きる可能性があります。
PrismaはDBの advisory lock を使って、複数のマイグレーションコマンドが同時に進まないようにしています。

Prismaのポイント:

  • ロック機構そのものはDBの機能
  • Prisma Migrate がそのDB機能を利用している
  • 通常の findManycreate のような Prisma Client のクエリに毎回かかるものではない
  • ロック用テーブルをPrismaが作るわけではない
  • Prismaの advisory lock は10秒でタイムアウトする
  • タイムアウトした場合は基本的に再実行する
  • Prisma 5.3.0以降は PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK で無効化できる

使いどころ

バッチ処理の二重起動防止

SELECT pg_try_advisory_lock(1001);

true なら処理を開始し、false なら「すでに実行中」として終了します。

マイグレーションの同時実行防止

CI/CDで複数ジョブが同じDBにマイグレーションをかける可能性がある場合、advisory lock で片方だけ進めます。

業務ID単位の排他制御

たとえば「同じ請求IDに対する再計算処理は同時に1つだけ」にしたい場合、請求IDからロックキーを作って advisory lock を取る設計ができます。

注意点

  • DBはロックキーの意味を知らないため、キー設計はアプリ側の責任
  • セッション単位のロックは解放漏れに注意する
  • connection pool を使う場合、どの接続でロックを取っているかに注意する
  • 長時間ロックを持つと、待機する処理が詰まる
  • advisory lock はDB内の排他制御なので、DBをまたぐ分散ロックには向かない

まとめ

advisory lock は、DBが提供する「任意キーの排他制御」機能です。
行ロックやテーブルロックと違い、ロックキーの意味はアプリケーション側が決めます。

Prismaの advisory lock は、DBの advisory lock 機能を Prisma Migrate が利用しているものです。
主な目的は、マイグレーションの同時実行を防ぐことです。

学習リソース

Index

  • はじめに
  • advisory lockとは
  • DBの機能か、ORMの機能か
  • 通常のロックとの違い
  • 行ロック
  • advisory lock
  • PostgreSQLでの例
  • ロックを取得する
  • 取れなければ待たずに失敗させる
  • ロックを解放する
  • セッション単位とトランザクション単位
  • セッション単位
  • トランザクション単位
  • Prismaでのadvisory lock
  • 使いどころ
  • バッチ処理の二重起動防止
  • マイグレーションの同時実行防止
  • 業務ID単位の排他制御
  • 注意点
  • まとめ
  • 学習リソース