سلام. چند روز پیش توی لاگهای دیتابیس یکی از مشتری ها، DEADLOCK دیدم و بهشون گفتم که مشکل رو حل کنید. بعد که بیشتر دقت کردم، دیدم که enq: TX - allocate ITL entry داره که زیر مجموعه CONFIGURATION حساب میشه. برای پیدا کردن ربط اون به deadlock باید چند تا مطلب رو مرور کنیم.
مطلب اول. ITL:
در اوراکل زمانی که برای یک سطر lock توسط یک transaction رخ می دهد، اطلاعات مربوط به آن در header آن block ی قرار می گیرد که داده در آن است. حال زمانی که transaction دیگری می خواهد با همان row کار کند، باید باز هم به سراغ همان block header برود و با اطلاعاتی که در حال حاضر در این قسمت موجود است ، متوجه lock بودن آن سطر می شود. بنابراین به پروسسی که در تئوری به عنوان lock manager ممکن است درست کار کند، دیگر نیازی نیست. به این ساختار داده ای ، Interested Transaction List یا به اختصار ITL گفته می شود که در آن اطلاعات transaction و rowid نگه داری می شود. هر ITL چندین slot برای transactionها دارد. زمانی که transactionِ ی برای اولین بار به سراغ block می آید، شماره rowid در یکی از slotها قرار می گیرد. همینطور زمانی که همین transaction و یا transaction دیگری بخواهد با سطرهای این block کار کند، در slot بعدی قرار می گیرد.
مطلب دوم، initrans:
در زمان ساخت جدول، این پارامتر مشخص می کند که در ابتدا چند slot در ITL وجود داشته باشد.
مطلب سوم، maxtrans:
زمانی که transaction جدیدی برای lock کردن سطری در همین block می آید، slot جدیدی در ITL تشکیل می شود و این تعداد تا MAXTRANS می تواند ادامه یابد.
مطلب چهارم، pctfree:
میزان درصدی که اوراکل برای هر بلاک برای update های بعدی در یک بلاک خالی می گذارد، یعنی اگر pctfree برابر 10 باشد، داده ها تا 90 درصد بلاک را پر خواهند کرد و تنها 10 درصد را برای update های بعد خالی می گذارند.
حالا ببنیم که ITL WAIT چطور پیش میاد. زمانی که در یک block نمی توان slot جدید ایجاد شود، transaction تازه ورود باید منتظر خالی شدن slot های قبلی بشود و بنابراین wait پیش می آید. یک بلاک بلافاصله بعد از بوجود آمدن به شکل زیر است:
چون initrans در ابتدا بصورت پیشفرض یک است ، بنابراین تنها یک slot در ITL وجود دارد. حالا فرض کنیم تعداد INSERT در این بلاک انجام می شود.
حالا transaction اول row1 را update می کند ولی commit نمی کند و بنابراین slot مربوط به آن باقی می ماند،
trnsaction بعدی row2 را update می کند و باز هنوز commit نکرده است. نتیجه می شود:
نتیجه این می شود که با اینکه در مثال ما maxtrans را برابر 11 در نظر گرفته ایم، جایی برای itl slot جدید نخواهد بود.
حالا به سراغ deadlock می رویم که بر اساس داکیومنت شماره 2266279.1 دلیل آن این است که transaction 1 یک ITL بر روی بلاک A دارد و یک تقاضا برای گرفتن ITL بر روی بلاک B و در همین زمان transaction 2 یک ITL بر روی بلاک B دارد و نقاضا برای گرفتن بلاک A که نتیجه deadlock می شود.
راه حل:
افزایش initrans و pctfree در جداول و ایندکسهایی که در این deadlock در گیر هستند. پیشنهاد اوراکل initrans=30 و pctfree=30% است. پس از این تغییرات باید جدول و ایندکسها را move و rebuild کرد.
نکته: دقت داشته باشید که در صورتی که بخواهید این جدول را move کنید، جدول lock خواهد شد و همچنین در زمان rebuild تعدادی متناسب با حجم ایندکس، archive log تولید می گردد. بنابراین زمان و حجم مناسب برای اینکار را انتخاب کنید.
منابع:
http://www.proligence.com/itl_waits_demystified.html
ORA-60 Deadlock 'ENQ: TX - ALLOCATE ITL ENTRY' Error - Doc ID 2266279.1
http://www.orafaq.com/wiki/PCTFREE
----------------------------------------------------------------------------------------------------------------------------------------
لطفاً در هنگام رانندگی به احترام عابرین پیاده بایستیم.
درباره این سایت