زمانی که یک دستور dml ای اجرا می شود ، بانک اطلاعاتی داده ها را، قبل از آن که تغییری بر روی آنها اعمال شود، درundo segment ها که در فضای undo tablespace قرار دارند ذخیره می کند تا در صورت لزوم از آنها برای عملیات هایی مثل rollback کردن یک دستور dml ای و flashback در سطح جداول استفاده کند. به این داده ها ، داده های بازگشتی می گویند .
همچنین از داده های بازگشتی برای ایجاد سازگاری در خواندن داده ها استفاده می شود به طوری که با استفاده از این داده ها اوراکل تضمین می کند که تمام کاربران ، حتی در مواقعی که داده ای در حال تغییر است دید یکسانی نسبت به داده های موجود در بانک اطلاعاتی داشته باشند
اوراکل با شروع هر تراکنش ، یک undo segment به آن اختصاص می دهد و در صورت نیاز به افزایش حجم ، به صورت خودکار extent هایی به آن اضافه می کند. همچنین یک undo segment ، می تواند چندین تراکنش را پشتیبانی کند.
Undo retention
داده ها در undo segment ها به صورت دائمی نگهداری نمی شوند و فضای موجود در آنها با توجه به یک سری نکات و همچنین مقادیر برخی پارامترها مانند undo retention مورد استفاده مجدد قرار می گیرد.
Undo retention میزان حداقل زمانی را نشان می دهد که داده های بازگشتی در undo segment ها باقی می مانند ولی هیچ تضمینی وجود ندارد که undo segment ها به اندازه مقدار تعیین شده در این پارامتر که بر حسب ثانیه نیز می باشد داده ها را در خود نگه دارند و اجازه بازنویسی بر روی آنها را ندهند.
اگر فضا به اندازه کافی در undo tablespace وجود نداشته باشد، اوراکل حتی پارامتر undo retention را نیز نادیده گرفته و مجوز بازنویسی بر روی undo segment ها را صادر می کند.
داده های بازگشتی در undo segment ها به دو قسمت کلی تقسیم می شوند :
1.داده هایی که هنوز وضعیت آنها نهایی نشده و active می باشند، اوراکل به هیچ عنوان اجازه بازنویسی بر روی آنها را نمی دهد
2.داده هایی که وضعیتشان مشخص شده و از حالت active خارج شده اند، به دو قسمت expired و unexpired تقسیم می شوند
*داده های expired ، داده هایی هستند که مدت زمان حضور آنها در undo segment ها از مقدار پارامتر undo retention بیشتر است و اوراکل در اولین اقدام ، مجوز بازنویسی بر روی آنها را صادر می کند
*داده های unexpired نیز داده هایی هستند که مدت زمان قرار گرفتن آنها در undo segment ها از مقدار تعیین شده در پارامتر undo retention کمتر است بنابراین ، این داده ها همچنان در undo segment ها باقی می مانند تازمانی که یا expired شوند و یا فضای undo tablespace به اندازه ای پر شود که اوراکل مجبور شود برای قرار دادن داده های جدید در undo segment ها ، بر روی آنها بازنویسی کند.
مقدار پیش فرض پارامتر undo retention، 900 ثانیه است که در صورت نیاز می توان آن را کاهش یا افزایش داد. برای تعیین دقیق این پارامتر راهکار قطعی ای وجود ندارد و تنها با در نظر گرفتن یک سری اطلاعات مثل اندازه طولانی ترین زمان صرف شده برای یک دستور طی 24 ساعت گذشته ، میتوان مقدار پارامتر undo retention را تعیین کرد.
در مثال زیر، میزان بیشترین زمان صرف شده توسط یک دستور، در بانک اطلاعاتی قابل مشاهده است :
SQL> select max(maxquerylen) from v$undostat;
MAX(MAXQUERYLEN)
—————————–
2100
در مثال فوق و با توجه به عدد بدست آمده و همچنین وجود فضای کافی در undo tablespace، بهتر است مقدار پارامتر undo retention را، بزرگتر یا مساوی 2100 ثانیه در نظر بگیریم.
Retention guarantee
از این ویژگی برای تضمین عدم بازنویسی بر روی داده های unexpired استفاده می شود بطوریکه اگر بر روی همه داده های expired شده عملیات بازنویسی انجام شده باشد و فضای کافی نیز در undo tablespace وجود نداشته باشد، داده های جدید دیگر بر روی داده های unexpired بازنویسی نمی شوند و تراکنش با شکست مواجه می شود . بنابراین این ویژگی گارانتی می کند که همه داده های unexpired موجود در undo segment ها تا زمان تبدیل شدن به داده های expired در فضای undo tablespace باقی خواهند ماند. این ویژگی به صورت پیش فرض غیر فعال است.
در مثال زیر نحوه بکارگیری ویژگی retention guarantee برای undo tablespace مشاهده می شود :
SQL> alter tablespace undotbs retention guarantee;
نکته: در صورت عدم استفاده از ویژگی retention guarantee، اوراکل به صورت خودکار و هر ده دقیقه یکبار، مقدار UNDORETENTION را تعیین می کند که مقدار جاری آن با استفاده از دستور زیر قابل مشاهده است:
SQL>select TUNED_UNDORETENTION from v$undostat;
خطای ORA-01555 “SNAPSHOT TOO OLD”
این خطا زمانی رخ می دهد که ویژگی سازگاری در خواندن داده ها نقض شود. از آنجایی که اوراکل سازگاری داده ها را تضمین می کند هر عملیاتی که باعث نقض این ویژگی شود با شکست مواجه می گردد. سازگاری در خواندن داده ها به این معنا است که همه کاربران باید دید یکسانی از داده ها داشته باشند برای این منظور اگر یک تراکنش DML ای، بر روی یک داده تغییر ایجاد کند، تصویر قبلی آن داده در undo segment ها ذخیره می شود.
حال اگر در همین حین و قبل از انجام عملیات commit، یک پرس و جو برای فراخوانی همان داده اجرا شود، اوراکل به جهت حفظ سازگاری در خواندن داده ها با استفاده از همان تصویر قبلی ، داده را در اختیار آن پرس و جو قرار می دهد . و اگر مدت زمان این پرس و جو طولانی شود به طوری که در این فاصله تراکنش DMLای نهایی شده و تراکنش دیگری قصد بازنویسی بر روی داده هایی که توسط این پرس و جو در حال خواندن است را داشته باشد و همچنین اگر همان داده توسط تراکنش DML ای دیگری مورد تغییر قرار گیرد اوراکل خطای SNAPSHOT TOO OLD داده و اجرای آن پرس و جو را با شکست مواجه می کند.
بنابراین برای جلوگیری از وجود چنین خطایی یکی از راه حل های زیر پیشنهاد می شود :
1.افزایش اندازه undo tablespace
2.استفاده از ویژگی retention guarantee
3.افزایش مقدار پارامتر undo retention
4.بهینه کردن پرس و جو ها
5.Commit کردن سریع تراکنش های گروهی و تقسیم آنها به قسمت های کوچکتر
ایجاد undo tablespace
برای ایجاد یک undo tablespace مشابه دستور ساخت یک tablespace دائمی از دستور زیر استفاده می کنیم با این تفاوت که در این دستور از کلمه undo tablespace بجای tablespace استفاده می شود
SQL> create undo tablespace undotbs
Datafile ‘/oracle/oradata/undotbs01.dbf’ size 100M
Autoextend on
Retention guarantee;
همچنین دستور حذف یک undo tablespace و تغییر در دیتافایل های آن مانند tablespace های دائمی می باشد.
عالی بود
thanks for sharing