ESC را فشار دهید تا بسته شود

زمیوس آموزش، یادگیری و سرگرمی

ORA‑۰۰۰۶۰: Deadlock Detected – ریشه‌یابی و حل بن‌بست در تراکنش‌های Oracle

خطای ORA‑۰۰۰۶۰: Deadlock Detected یکی از خطاهای مهم در Oracle Database است که معمولاً به‌طرز ناگهانی در سیستم‌های پایدار ظاهر می‌شود و باعث توقف بخشی از عملیات برنامه می‌گردد.

این خطا یعنی دو تراکنش درگیر یک چرخه‌ی قفل‌گذاری شده‌اند و هیچ‌کدام قادر به ادامه نیستند.

در ادامه  آموزش Oracle در بخش آموزش خطاهای اوراکلی، رایج‌ترین دلایل بروز بن‌بست، روش بازتولید، نحوه‌ی تحلیل Trace File، و بهترین راهکارهای جلوگیری از Deadlock را با مثال‌های واقعی توضیح می‌دهم.

حتماً تا حالا در دنیای Oracle با ارور معروفی روبه‌رو شدی که روی صفحه نوشت:
				
					ORA-02291: integrity constraint violated - parent key not found
				
			

اگر دیدی این پیغام ظاهر شد، یعنی داری رکوردی را وارد جدول فرزند می‌کنی که والدش هنوز در پایگاه داده وجود ندارد.

پیشنهاد می کنم این مقاله زیر رو حتما مطالعه کنی.

در این مقاله شما می خوانید

Deadlock در Oracle دقیقاً چیست؟

برای اینکه یک برنامه‌نویس یا DBA بتواند مشکل ORA‑۰۰۰۶۰ را حل کند، باید بفهمد Deadlock دقیقاً چه رخدادی است.

Deadlock یعنی:

دو یا چند Session در حال Update یا خواندن داده‌ها هستند و هرکدام منتظر قفلی هستند که دیگری نگه داشته است. این چرخه باعث توقف کامل می‌شود.

مثال ساده:

  • Session A رکورد ۱ را قفل می‌کند
  • Session B رکورد ۲ را قفل می‌کند
  • A برای ادامه نیاز به رکورد ۲ دارد
  • B برای ادامه نیاز به رکورد ۱ دارد

هیچ‌کدام نمی‌توانند ادامه دهند → Oracle وارد عمل می‌شود و یکی را Fail می‌کند تا دیتابیس قفل نشود. نتیجه: خطای ORA‑۰۰۰۶۰.

این خطا همیشه نشان‌دهنده‌ی یک اشتباه در طراحی یا ترتیب دسترسی تراکنش‌ها است، نه مشکل از Oracle.

مثال کامل و واقعی از ایجاد Deadlock

مرحله ۱: ساخت جدول تست

				
					CREATE TABLE employees_test (
    id NUMBER PRIMARY KEY,
    name VARCHAR2(100)
);

INSERT INTO employees_test VALUES (1, 'Ali');
INSERT INTO employees_test VALUES (2, 'Sara');
COMMIT;

				
			

مرحله ۲: ایجاد بن‌بست با دو Session

				
					Session A:

UPDATE employees_test SET name = 'Ali A' WHERE id = 1;
				
			
				
					Session B:

UPDATE employees_test SET name = 'Sara B' WHERE id = 2;

				
			

حالا هر دو تراکنش قفل گرفته‌اند اما Commit نکرده‌اند.

 

				
					Session A:

UPDATE employees_test SET name = 'Sara A' WHERE id = 2;
				
			

Session A منتظر آزاد شدن قفل Session B می‌ماند.

				
					Session B:

UPDATE employees_test SET name = 'Ali B' WHERE id = 1;

				
			

در این لحظه Deadlock رخ می‌دهد و Oracle یکی از Sessionها را Fail می‌کند و خطای زیر برمی‌گردد:

				
					ORA‑۰۰۰۶۰: deadlock detected while waiting for resource

				
			

Oracle چگونه Deadlock را تشخیص می‌دهد؟

Oracle یک گراف از قفل‌ها می‌سازد: هر Session یک گره و هر انتظار برای قفل یک خط ارتباطی است.

اگر بین این گره‌ها یک حلقه‌ی بسته (Cycle) ایجاد شود، Oracle فوراً آن را Deadlock تشخیص می‌دهد.

ویژگی مهم Oracle

Deadlock را سریع تشخیص می‌دهد و به‌جای معطل نگه داشتن سیستم، یکی از تراکنش‌ها را Fail می‌کند تا دیتابیس دچار توقف عمومی نشود.

تحلیل Trace File و پیدا کردن منبع Deadlock

هر زمان Deadlock رخ بدهد، Oracle یک Trace File کامل تولید می‌کند.

مسیر معمول Trace:

				
					$ORACLE_BASE/diag/rdbms/<db_name>/<instance>/trace

				
			

در Trace File بخشی با عنوان Deadlock graph وجود دارد:

				
					Deadlock graph:
  Session A is waiting for Row Lock held by Session B
  Session B is waiting for Row Lock held by Session A

				
			

در انتهای فایل معمولاً این جمله را می‌بینی:

				
					This deadlock is not an Oracle error. It is due to application logic.

				
			

این یعنی مشکل به طراحی برنامه ربط دارد، نه دیتابیس.

دلایل رایج بروز خطای ORA‑۰۰۰۶۰

این‌ها شایع‌ترین دلایل هستند:

• ترتیب غیرمنظم در دسترسی به رکوردها

• نبود Index مناسب روی ستون‌های WHERE

• تراکنش‌های طولانی و سنگین

• وجود Triggerهایی که در پس‌زمینه Update یا Insert انجام می‌دهند

• عملیات Batch بدون Commit منطقی

• تعامل چند سرویس یا API با الگوهای متفاوت دسترسی

اگر Deadlock در سایتت «ناگهانی» شروع شده (طبق تجربه قبلی‌ات)، معمولاً دلیل آن یکی از موارد زیر است:

  • کدی تازه Deploy شده
  • Trigger جدید اضافه شده
  • حذف یا خراب شدن Index
  • افزایش حجم داده و تغییر مسیر Query Plan

بهترین روش‌های جلوگیری از Deadlock

راهکار ۱ — یکسان‌سازی ترتیب Update

اصلی‌ترین و مهم‌ترین راه حل:

تمام تراکنش‌ها باید رکوردها را به ترتیب یکسانی Update کنند.

مثلاً همیشه از ID کوچک‌تر به بزرگ‌تر.

راهکار ۲ — تراکنش‌های کوتاه

قفل‌ها را سریع آزاد کن.

تراکنش‌های طولانی یعنی احتمال Deadlock بیشتر.

راهکار ۳ — ساخت Index مناسب

اگر Oracle مجبور باشد برای پیدا کردن رکورد Full Scan انجام دهد، احتمال قفل‌های غیرضروری بالا می‌رود.

راهکار ۴ — بررسی Triggerها

یکی از خطرناک‌ترین منابع Deadlock «به‌روزرسانی مخفی» داخل Trigger است.

راهکار ۵ — استفاده از SELECT FOR UPDATE SKIP LOCKED

این روش برای سیستم‌های با ترافیک بالا بسیار عالی است:

				
					SELECT * FROM employees_test
WHERE id = 1
FOR UPDATE SKIP LOCKED;

				
			

راهکار ۶ — Lock رقمی یا ترابری

در اپلیکیشن‌هایی که چند سرویس هم‌زمان روی یک منبع کار می‌کنند، بهتر است یک Strategy Lock تعریف شود.

بهترین الگو برای برنامه‌نویسان Back‑End

  •  تراکنش‌ها را Atomic نگه دارید
  •  رکوردها را همیشه در ترتیب یکسان Lock کنید
  • Queryها را با Explain Plan بررسی کنید
  •  برای Updateهای همزمان از SKIP LOCKED استفاده کنید
  • Triggerها را مستندسازی و بازبینی کنید

سوالات متداول درباره رفع خطای ORA‑۰۰۰۶۰ در اوراکل

در اغلب سیستم‌ها Deadlock زمانی رخ می‌دهد که الگوی دسترسی داده تغییر کرده باشد.

این تغییر می‌تواند ناشی از موارد زیر باشد:

  • انتشار نسخه جدید کد (Deployment)
  • اضافه شدن Trigger جدید
  • حذف یا خراب شدن Index
  • افزایش حجم داده و تغییر Query Plan
  • هم‌زمانی بیشتر درخواست‌ها در ساعات خاص

به همین دلیل حتی اگر سیستم سال‌ها بدون مشکل کار کرده باشد، ناگهان ORA‑۰۰۰۶۰ شروع به ظاهر شدن می‌کند.

بهترین و قطعی‌ترین روش، بررسی Trace File است که Oracle هنگام وقوع Deadlock تولید می‌کند.

در این فایل، این موارد دقیقاً ثبت شده:

  • Sessionهای درگیر
  • نوع قفل
  • رکورد یا ROWID مشکل‌ساز
  • کوئری‌ای که باعث انتظار شده
  • Chain دسترسی‌ها

با جستجوی عبارت

Deadlock graph:

می‌توانی منبع واقعی Deadlock را پیدا کنی.

تقریباً همیشه مشکل از طراحی تراکنش‌ها یا ترتیب Update در برنامه است.

Oracle در Trace File هم معمولاً این جمله را می‌نویسد:

This deadlock is not an Oracle error. It is due to application logic.

یعنی Oracle مقصر نیست — فقط Deadlock را کشف می‌کند.

بهترین و مؤثرترین روش این است که ترتیب دسترسی به رکوردها را استاندارد کنید.

یعنی همه تراکنش‌ها همیشه رکوردها را به یک ترتیب ثابت Update کنند (مثلاً از کوچک به بزرگ).

راهکارهای مهم دیگر:

  • کوتاه نگه داشتن تراکنش‌ها
  • ایجاد Index مناسب
  • حذف عملیات پنهان در Trigger
  • استفاده از SELECT … FOR UPDATE SKIP LOCKED در سیستم‌های پرترافیک

اگر فقط یک روش را انتخاب کنی، ترتیب ثابت Update بیشترین اثر را دارد.

جمع‌بندی

خطای ORA‑۰۰۰۶۰ هشدار می‌دهد که در برنامه یا دیتابیس شما چرخه‌ی قفل‌گذاری نادرست وجود دارد.

برای حل آن باید:

  • سناریو را بازتولید کنید
  • Trace File را بررسی کنید
  • ترتیب دسترسی را اصلاح کنید
  • Indexهای لازم را اضافه کنید
  • تراکنش‌ها را کوتاه کنید

📥 اگر سوالی داری در مورد رفع خطای ORA‑۰۰۰۶۰ در اوراکل داری، در بخش کامنت‌ها بپرس.

سؤالی درباره این مقاله داری؟

اگر نکته‌ای در این مقاله برات مبهم بود یا خواستی بیشتر بدونی، همین حالا برام بنویس تا دقیق و صمیمی پاسخت رو بدم — مثل یه گفت‌وگوی واقعی 💬

برو به صفحه پرسش و پاسخ

میثم راد

من یه برنامه نویسم که حسابی با دیتابیس اوراکل رفیقم! از اونایی ام که تا چیزی رو کامل نفهمم،ول کن نیستم، یادگرفتن برام مثل بازیه، و نوشتن اینجا کمک می کنه تا چیزایی که یاد گرفتم رو با بقیه به شریک بشم، با هم پیشرفت کنیم.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *