はじめに
「在庫の競合更新でオーバーセールが発生した」——楽観的ロックで対処できない強い競合にはSELECT FOR UPDATEが必要。デッドロックを防ぎながら実装する設計をClaude Codeに生成させる。
CLAUDE.mdに設計ルールを書く
## ペシミスティックロック設計ルール
- 使用基準: 在庫・残高など競合が高頻度で発生する更新
- デッドロック防止: 複数行ロック時はID昇順で取得
- SET LOCAL lock_timeout = '5s'(トランザクション単位)
- NOWAIT: 即座に失敗 / SKIP LOCKED: キューワーカー向け
生成される実装(抜粋)
// ID昇順でロック(デッドロック防止)
export async function lockRows(tx, table, ids, mode = 'UPDATE') {
const sortedIds = [...ids].sort(); // 必ずID昇順
await tx.$executeRawUnsafe(
`SELECT id FROM "${table}" WHERE id = ANY($1::uuid[]) ORDER BY id FOR ${mode}`,
sortedIds
);
}
// 在庫競合更新(オーバーセール防止)
async deductInventory(orderItems) {
await withLockTimeout(prisma, 5000, async (tx) => {
await lockRows(tx, 'Product', orderItems.map(i => i.productId), 'UPDATE');
// ロック取得後に在庫確認(安全)
for (const item of orderItems) {
if (product.inventory < item.quantity) throw new InsufficientInventoryError(...);
}
await Promise.all(orderItems.map(item =>
tx.product.update({ where: { id: item.productId }, data: { inventory: { decrement: item.quantity } } })
));
});
}
// SKIP LOCKED: 複数ワーカーが同じキューを安全に処理
async dequeueForProcessing() {
return prisma.$transaction(async (tx) => {
const rows = await tx.$queryRaw`
SELECT id FROM "Order" WHERE status = 'pending'
ORDER BY created_at ASC LIMIT 1 FOR UPDATE SKIP LOCKED
`;
if (!rows.length) return null;
return tx.order.update({ where: { id: rows[0].id }, data: { status: 'processing' } });
});
}
// デッドロック自動リトライ
const RETRYABLE_PG_CODES = new Set(['40001', '40P01', '55P03']);
async function withLockRetry(fn, maxAttempts = 3) {
for (let i = 0; i < maxAttempts; i++) {
try { return await fn(); }
catch (error) {
if (!RETRYABLE_PG_CODES.has(error?.code)) throw error;
await sleep(50 * 2**i * (0.5 + Math.random() * 0.5));
}
}
}
まとめ
- CLAUDE.md に使用基準(高頻度競合)・ID昇順ロック必須・lock_timeout 5s・NOWAIT/SKIP LOCKED使い分けを明記
- ID昇順ソートでロック取得 ——複数行をロックする際に順序を統一することでデッドロックの発生を根本的に防止
- SKIP LOCKED で複数ワーカーが同じキューを処理可能——他のワーカーが処理中の行をスキップして次の行へ
- デッドロック(40P01)を検出して自動リトライ ——ジッター付き指数バックオフで競合を分散
DB設計のレビューは **Code Review Pack(¥980)* の /code-review で確認できます。*
みょうが (@myougatheaxo) — ウーパールーパーのVTuber。
Top comments (0)