Mybatisで排他制御のやり方

Mybatisで排他制御のやり方

MyBatisでの排他制御

MyBatisで排他制御を行うための方法として、楽観的排他制御と悲観的排他制御の2つがあります。
ここでは、それぞれの方法について、testUserというテーブルと対応するTestUserクラスを例に解説します。

1. 楽観的排他制御

楽観的排他制御では、更新対象のレコードにバージョン番号やタイムスタンプなどを持たせ、更新時にその値をチェックします。
更新時に値が変わっていなければ更新を許可し、変わっていれば更新を拒否します。

<テーブル設計>

CREATE TABLE testUser (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    version INT
);

<エンティティクラス>

public class TestUser {
    private int id;
    private String name;
    private int version;
    // getters and setters
}

<MyBatisの更新SQL>

<update id="updateTestUser">
    UPDATE testUser
    SET name = #{name}, version = version + 1
    WHERE id = #{id} AND version = #{version}
</update>

上記のように、update文ではwhere条件にversionを含め、更新が成功した場合のみバージョン番号をインクリメントします。
更新が失敗した場合は、誰かがその間に更新を行ったと判断できます。

2. 悲観的排他制御

悲観的排他制御では、更新対象のレコードに対してロックをかけ、他のトランザクションからのアクセスを制限します。

<テーブル設計>

楽観的排他制御と同じテーブルを使用します。

<MyBatisのselect for update SQL>

<select id="selectForUpdateTestUser" resultType="TestUser">
    SELECT id, name, version
    FROM testUser
    WHERE id = #{id}
    FOR UPDATE
</select>

このselect文はトランザクション内で実行し、select文が実行されたレコードに対してロックをかけます。
他のトランザクションは、このロックが解除されるまでレコードを更新できません。

実装のポイント

  • 楽観的排他制御はトラフィックの多いシステムやデータ競合が少ないシステムで有効です。
  • 悲観的排他制御はデータ競合が頻繁に発生する場面で有効ですが、デッドロックに注意が必要です。

排他制御の選択は、システムの特性や要件に応じて適切に行うことが重要です。