Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

DB ロックテーブルを使用した分散ロック (Distributed Lock) の設計

0
Posted at

はじめに

たまによく使うテーブル設計の手法で、ロックテーブル?セマフォテーブル?(正式名称が分かりません...)というものがあります。今回はそれについての備忘録です。

設計

複数のプロセス(プログラムやスレッド、サーバーなど)で同じリソースを同時に使用すると、データの破損や二重実行などの問題が発生するため、排他制御が必要になります。本設計では行ロックを利用することで、排他制御を行います。

テーブルは非常にシンプルです。

create_m_lock.sql
-- ロックテーブルの作成。
CREATE TABLE m_lock (
    lock_id   VARCHAR(50)   NOT NULL, -- ロック ID
    lock_name NVARCHAR(100) NOT NULL, -- ロック名称
    
    -- lock_id を主キーに設定する。
    CONSTRAINT PK_m_lock PRIMARY KEY CLUSTERED (lock_id)
);

-- レコードの登録。
INSERT INTO m_lock (lock_id, lock_name) 
VALUES ('0', 'XXXX 処理ロック');

実装

C# + SQL Server での実装例になります。

WITH (UPDLOCK, ROWLOCK, NOWAIT) は DB との接続が切れた瞬間に SQL Server 側で自動的にロックを強制解放してくれるという特性があるため、ゾンビロックが残らず、安心して使用できます。

Example.cs
private void Example()
{
    try
    {
        // 1. トランザクションを開始する。
        DB.BeginTransaction();

        // 2. クエリを実行して、行ロックを試みる。
        // ※ 先客がいる場合、待機せずに即座に例外が発生する。
        DB.Execute("SELECT * FROM m_lock WITH (UPDLOCK, ROWLOCK, NOWAIT) WHERE lock_id = '0'");

        // 3. ロックが取得できた場合、処理を行う。
        ExecuteProcess();

        // 4. 正常に処理が完了したら、トランザクションをコミットする。
        DB.CommitTransaction();
    }
    catch (SqlException ex)
    {
        if (ex.Number == 1222)
        {
            // 1222 : ロック要求タイムアウトの場合、実行をスキップする。
            Logger.Info("処理は既に別のプロセスで実行中のため、実行をスキップします。");
            DB.RollbackTransaction();
        }
        else
        {
            Logger.Error(ex, "例外が発生しました。");
            DB.RollbackTransaction();
        }
    }
    catch (Exception ex)
    {
        Logger.Error(ex, "例外が発生しました。");
        DB.RollbackTransaction();
    }
}

参考

言及している記事が思ったよりもありませんでした。Web 屋さんのマイクロサービスなどで利用される分散ロックと考え方の方向性は同じかと思います。

余談

SQL Server の場合 sp_getapplock という組込のストアドプロシージャを使用すると、テーブルを用意しなくても実現できるようです。

おわりに

逆に Web 業界でも似たような考え方をするんだって気付きになりました。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?