楽観的ロック
データの読み取り時にロックせず、更新時にバージョンを検証して競合を検出する排他制御
楽観的ロックとは
楽観的ロック (Optimistic Locking) は、データの読み取り時にロックを取得せず、更新時にバージョン番号を検証して競合を検出する排他制御である。「競合はめったに起きない」という楽観的な前提に基づく。
悲観的ロック vs 楽観的ロック
悲観的ロックと楽観的ロックの違いを以下にまとめる。
| 観点 | 悲観的ロック | 楽観的ロック |
|---|---|---|
| ロックのタイミング | 読み取り時 | 更新時 (検証のみ) |
| 前提 | 競合が頻繁に起きる | 競合はめったに起きない |
| スループット | 低い (ロック待ち) | 高い (ロックなし) |
| 競合時の動作 | 待機 | エラー → リトライ |
| デッドロック | 発生する | 発生しない |
DynamoDB での楽観的ロック
DynamoDB での楽観的ロックのコード例を示す。
// 1. アイテムを取得 (version を含む)
const item = await db.get({ TableName: 'products', Key: { id: 'P1' } });
// { id: 'P1', name: 'Widget', stock: 10, version: 3 }
// 2. 更新時に version を検証
await db.update({
TableName: 'products',
Key: { id: 'P1' },
UpdateExpression: 'SET stock = :stock, version = :newVersion',
ConditionExpression: 'version = :currentVersion',
ExpressionAttributeValues: {
':stock': 9,
':newVersion': 4,
':currentVersion': 3, // 読み取り時の version
},
});
// version が 3 でなければ ConditionalCheckFailedException → リトライ
競合の検出
競合の検出を図で示す。
ユーザー A: 読み取り (version=3) → 更新 (version=3→4) ✅ 成功
ユーザー B: 読み取り (version=3) → 更新 (version=3→4) ❌ 失敗 (version は既に 4)
ユーザー B: 再読み取り (version=4) → 更新 (version=4→5) ✅ 成功
RDS での楽観的ロック
RDS での楽観的ロックの例を示す。
-- 更新時に version を検証
UPDATE products
SET stock = 9, version = version + 1
WHERE id = 'P1' AND version = 3;
-- 影響行数が 0 なら競合が発生 → リトライ
使い分け
使い分けの指針を以下にまとめる。
| ケース | 推奨 |
|---|---|
| 読み取りが多く、競合が少ない | 楽観的ロック |
| 競合が頻繁に発生 | 悲観的ロック |
| DynamoDB | 楽観的ロック (条件付き書き込み) |
| 在庫管理 (高競合) | アトミックカウンター (ADD stock :dec) |
アトミックカウンター (楽観的ロック不要)
アトミックカウンター (楽観的ロック不要) のコード例を示す。
// version チェックなしで安全に減算
await db.update({
TableName: 'products',
Key: { id: 'P1' },
UpdateExpression: 'ADD stock :dec',
ConditionExpression: 'stock >= :dec',
ExpressionAttributeValues: { ':dec': -1 },
});
実務での活用方法は関連書籍にも詳しい。
この記事は役に立ちましたか?
関連用語
レースコンディション
複数のプロセスやスレッドが共有リソースに同時アクセスし、実行順序によって結果が変わる不具合
冪等性
同じ操作を何度実行しても結果が変わらない性質で、分散システムの信頼性を支える
DynamoDB
AWS のフルマネージド NoSQL データベースで、ミリ秒単位のレイテンシとシームレスなスケーリングを提供する
分散ロック
分散システムで複数のプロセスが同じリソースに同時アクセスすることを防ぐ排他制御
ミューテックス
複数のスレッドが共有リソースに同時アクセスすることを防ぐ排他制御の同期プリミティブ
API スロットリング
API へのリクエスト数を制限し、サーバーの過負荷を防ぐトラフィック制御手法
関連する記事
「あとで読む」ブックマークが 100 件を超えたら本を買え
ブラウザのブックマークに技術記事を溜め込んでいませんか。断片的な記事を 100 件読むより、同じテーマの本を 1 冊読む方が効率的な理由を解説します。
深夜 3 時のデプロイ前に読み返したい 1 ページ
本番デプロイの直前、最終確認のチェックリストとして技術書の特定のページが役立つことがあります。緊張の場面で頼りになる「お守りの 1 ページ」の見つけ方と活用法。
技術書の読む順番戦略 - 複数冊を組み合わせて理解を加速させる
技術書を 1 冊ずつ読むのではなく、複数冊を戦略的に組み合わせることで理解の深さと速度を飛躍的に高める方法を解説します。