
اگر با Oracle Database کار کرده باشید، احتمالاً با خطای معروف زیر روبهرو شدهاید:
ORA-00060: deadlock detected while waiting for resource
این پیام یعنی تراکنشهای شما گیر کردهاند و هیچکدام نمیتوانند ادامه دهند؛ چیزی که به آن Deadlock یا «بنبست» میگوییم.
خبر خوب این است که هم میتوان آن را شناسایی کرد، هم رفع کرد، و حتی پیشگیری نمود.
در این مقاله آموزش اوراکل در بخش آموزش Oracle SQL، قدمبهقدم با مثالهای کاربردی، بهترین روشها را بررسی میکنیم.
اآیا تا حالا در دیتابیس اوراکل (Oracle Database) به اشتباه یک رکورد مهم رو حذف یا آپدیت کردی؟!! پیشنهاد می شود نوشته زیر را مطالعه کنید:
در این نوشته شما می خوانید
Deadlock در Oracle چیست؟
به زبان ساده:
Deadlock زمانی رخ میدهد که دو یا چند تراکنش، قفلهایی را گرفتهاند و هر کدام منتظر آزاد شدن قفلهایی هستند که دیگری نگه داشته است. نتیجه؟ هیچکدام جلو نمیروند.
یک مثال ساده Deadlock
فرض کنید جدولی به نام accounts داریم:
CREATE TABLE accounts (
account_id NUMBER PRIMARY KEY,
balance NUMBER
);
INSERT INTO accounts VALUES (1, 1000);
INSERT INTO accounts VALUES (2, 2000);
COMMIT;
دو Session (کاربر) داریم: Session 1
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
Session 2
UPDATE accounts SET balance = balance - 200 WHERE account_id = 2;
حالا:
- Session 1 میخواهد روی حساب ۲ قفل بگیرد.
- Session 2 میخواهد روی حساب ۱ قفل بگیرد.
هیچکس موفق نمیشود → Deadlock رخ میدهد.
روشهای شناسایی Deadlock در Oracle
۱. پیام خطا
وقتی تراکنشی درگیر Deadlock شود، Oracle یک تراکنش را بهطور خودکار Rollback میکند و پیام ORA-00060 نمایش میدهد.
۲. Alert Log و Trace File
Oracle جزئیات Deadlock را در Alert Log ثبت میکند و یک Trace File میسازد:
$ORACLE_BASE/diag/rdbms/DB_NAME/instance_name
/trace/instance_name_ora_pid.trc
۳. استفاده از ویوهای سیستمی
برای پیدا کردن Sessionهایی که قفل یا بلاک ایجاد کردهاند:
SELECT s.sid, s.serial#, s.username, l.type,
l.lmode, l.request, l.id1, l.id2
FROM v$session s
JOIN v$lock l ON s.sid = l.sid
WHERE l.block != 0 OR l.request != 0;
بهترین روشها برای پیشگیری از Deadlock
۱. نظم در ترتیب قفلگیری
تمام تراکنشها را طوری طراحی کنید که همیشه به یک ترتیب به جداول/ردیفها دسترسی بگیرند.
۲. کوتاه کردن تراکنشها
زود Commit کنید و از قفل نگه داشتن طولانیمدت پرهیز کنید.
۳. استفاده از NOWAIT یا SKIP LOCKED
SELECT * FROM accounts FOR UPDATE NOWAIT;
یا:
SELECT * FROM accounts FOR UPDATE SKIP LOCKED;
۴. انتخاب Isolation Level مناسب
اغلب، استفاده از READ COMMITTED میتواند احتمال Deadlock را کاهش دهد.
۵. مانیتورینگ مداوم
با اسکریپتهای دورهای Sessionهای بلاکشده را پیدا کنید:
SELECT blocking_session, sid, serial#, wait_class, seconds_in_wait
FROM v$session
WHERE blocking_session IS NOT NULL;
اسکریپت کاربردی تشخیص Deadlock در اوراکل
SELECT s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ' )'
AS blocker,
s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' )'
AS blocked
FROM v$session s1
JOIN v$session s2 ON s1.sid = s2.blocking_session;
سوالات متداول درباره Deadlock در اوراکل
این خطا یعنی دو یا چند تراکنش در دیتابیس منابع را به شکلی قفل کردهاند که منتظر همدیگر ماندهاند و هیچکدام قادر به ادامه نیستند.
Oracle برای رفع این وضعیت، یکی از تراکنشها را بهطور خودکار Rollback میکند.
برای شناسایی Deadlock میتوانید:
- پیام خطای ORA-00060 را بررسی کنید.
- جزئیات آن را در Alert Log و Trace File ببینید.
- از دستورهای vsession∗∗و∗∗vsession** و **vsession∗∗و∗∗vlock برای پیدا کردن Sessionهای بلاک شده استفاده کنید.
- همیشه به یک ترتیب ثابت به جداول و رکوردها قفل بگیرید.
- تراکنشها را کوتاه نگه دارید و سریع Commit کنید.
- از گزینههای FOR UPDATE NOWAIT یا SKIP LOCKED برای جلوگیری از انتظار طولانی استفاده کنید.
- Isoط÷lation Level مناسب، مثل READ COMMITTED را تنظیم کنید.
خیر، Deadlock باعث خرابی دیتابیس یا از بین رفتن داده بهطور کلی نمیشود، اما باعث Rollback شدن بخشی از تراکنشها و کاهش عملکرد سیستم میگردد.
همچنین میتواند تجربه کاربری را مختل کند، مخصوصاً در سیستمهای پرتراکنش.
📦 جمعبندی
- Deadlock در Oracle مشکلی شایع ولی قابل تشخیص و قابل پیشگیری است.
- Alert Log، Trace File و Viewهای سیستمی ابزارهای اصلی شناسایی هستند.
- با طراحی درست قفلها، commit سریع، و رعایت نظم دسترسی به دادهها میتوان جلوی بیشتر Deadlockها را گرفت.
📥 اگر سوالی داری در مورد Deadlock در اوراکل داری، در بخش کامنتها بپرس.

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