MeWrite Docs

PostgreSQL: deadlock detected

PostgreSQLで複数トランザクションが互いにロックを待ち合うデッドロックエラーの原因と解決策

概要

複数のトランザクションが互いにロックを待ち合う状態になり、自動的に一方がロールバックされるエラーです。

エラーメッセージ

``` ERROR: deadlock detected DETAIL: Process 12345 waits for ShareLock on transaction 67890; blocked by process 54321. Process 54321 waits for ShareLock on transaction 12345; blocked by process 12345. HINT: See server log for query details. ```

原因

  1. トランザクション内でのロック順序不一致: 複数のテーブルを異なる順序で更新
  2. 長時間のトランザクション: ロック保持時間が長すぎる
  3. 明示的ロックの競合: SELECT FOR UPDATEの多用

解決策

1. ロック順序を統一する

```sql – 悪い例: 順序がバラバラ – トランザクション1: UPDATE users SET … WHERE id = 1; UPDATE orders SET … WHERE id = 2; – トランザクション2: UPDATE orders SET … WHERE id = 2; UPDATE users SET … WHERE id = 1;

– 良い例: 常に同じ順序 BEGIN; UPDATE orders SET status = ‘completed’ WHERE id = 2; UPDATE users SET last_order = NOW() WHERE id = 1; COMMIT; ```

2. トランザクションを短くする

```python

悪い例

with db.transaction(): process_order(order_id) # 重い処理 update_user_stats(user_id) send_notification(user_id) # 外部API呼び出し

良い例

process_order(order_id) send_notification(user_id) with db.transaction(): update_user_stats(user_id) ```

3. 行ロックを最小化

```sql – 悪い例: 広範囲ロック SELECT * FROM orders WHERE status = ‘pending’ FOR UPDATE;

– 良い例: SKIP LOCKEDで競合回避 SELECT * FROM orders WHERE status = ‘pending’ FOR UPDATE SKIP LOCKED LIMIT 10; ```

よくある間違い

  • リトライロジックを実装しない
  • トランザクション内で外部API呼び出し
  • 必要以上に大きなトランザクション

関連エラー

関連エラー

PostgreSQL の他のエラー

最終更新: 2025-12-10