ددلاک (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 فقط برای خطاهای شناختهشده ددلاک
این مشکل با ریس کاندیشن و پسیمیستیک لاکینگ ارتباط دارد، اما همه ریس کاندیشنها به ددلاک منجر نمیشوند.