ددلاک (Deadlock) که در فارسی به آن بن‌بست گفته می‌شود، زمانی رخ می‌دهد که دو یا چند عملیات برای آزاد شدن منابعی منتظر یکدیگر بمانند و هیچ‌کدام نتواند پیش برود. در دیتابیس این وضعیت اغلب به‌خاطر ترتیب متفاوت قفل کردن ردیف‌ها ایجاد می‌شود.

یک مثال واقعی با دو ترنزکشن

ترنزکشن A ابتدا سفارش ۱۰ را قفل می‌کند و سپس منتظر سفارش ۲۰ می‌ماند. هم‌زمان ترنزکشن B سفارش ۲۰ را گرفته و منتظر سفارش ۱۰ است. موتور دیتابیس معمولا یکی از ترنزکشن‌ها را به‌عنوان قربانی انتخاب و Rollback می‌کند.

-- Session A
BEGIN;
SELECT * FROM orders WHERE id = 10 FOR UPDATE;
SELECT * FROM orders WHERE id = 20 FOR UPDATE;
-- Session B (concurrently)
BEGIN;
SELECT * FROM orders WHERE id = 20 FOR UPDATE;
SELECT * FROM orders WHERE id = 10 FOR UPDATE;

پیشگیری و بازیابی

  • قفل کردن ردیف‌ها با ترتیب یکسان در تمام مسیرهای برنامه
  • کوتاه نگه داشتن مدت ترنزکشن و پرهیز از API خارجی داخل آن
  • استفاده از Index مناسب برای محدود کردن ردیف‌های قفل‌شده
  • Retry محدود با Backoff فقط برای خطاهای شناخته‌شده ددلاک

این مشکل با ریس کاندیشن و پسیمیستیک لاکینگ ارتباط دارد، اما همه ریس کاندیشن‌ها به ددلاک منجر نمی‌شوند.