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

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

رفع خطای ORA‑۰۱۵۵۵: Snapshot Too Old در Queryهای طولانی اوراکل

اگر از برنامه‌نویسان یا DBAهای باتجربه‌ی Oracle باشید، احتمالاً حداقل یک بار با ارور کلاسیک زیر روبه‌رو شده‌اید:

				
					ORA-01555: snapshot too old: rollback segment number with name "" too small

				
			

این خطا نه‌تنها یکی از پراستفاده‌ترین ارورها در دیتابیس‌های بزرگ است، بلکه نشانه‌ای از عدم تعادل میان Undo Tablespace، مدت نگهداری نسخه‌ی داده‌ها (Undo Retention) و طول زمان اجرای کوئری‌ها محسوب می‌شود.

در ادامه آمورش اوراکل از بخش آموزش Oracle SQL به زبان ساده و در عین حال فنی توضیح می‌دهیم چرا این خطا اتفاق می‌افتد، چطور آن را تشخیص دهیم، و چگونه به‌صورت پایدار رفعش کنیم.

در Oracle، ابزار این کار معمولاً Sequence است؛ اما زمانی که از دستورهای جمعی مثل Bulk Insert یا Parallel Insert استفاده می‌کنیم، گاهی مشاهده می‌شود که Sequence مقادیر تکراری یا نامرتب تولید می‌کند.

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

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

⚙️ معنی و منطق خطا ORA‑۰۱۵۵۵: Snapshot Too Old در معماری Oracle

در قلب اوراکل مفهومی به نام Consistent Read وجود دارد.

یعنی وقتی یک Query اجرا می‌شود، اوراکل باید وضعیت داده‌ها را همان‌طور که در لحظه‌ی شروع Query وجود داشت، تا پایان پردازش نگه دارد.

برای این کار از Undo Segments یا Undo Tablespace استفاده می‌کند.

اگر فضای Undo کوچک باشد یا تراکنش‌های دیگر هم‌زمان مقدار زیادی داده را تغییر دهند، نسخه‌های قدیمی داده‌ها پاک می‌شوند و Oracle دیگر نمی‌تواند Snapshot اولیه را بازسازی کند؛

در نتیجه خطای ORA‑۰۱۵۵۵: Snapshot Too Old رخ می‌دهد.

💡 مثال کاربردی از بروز خطا Snapshot Too Old

فرض کنید یک گزارش‌گیری سنگین دارید:

				
					SELECT employee_id, salary
FROM hr.employees
WHERE department_id IN (
   SELECT department_id
   FROM hr.departments
   WHERE location_id = 1700
);

				
			

هم‌زمان با اجرای این Query، فرایند دیگری میلیون‌ها رکورد از جدول employees را به‌روزرسانی و commit می‌کند.

اگر Undo Tablespace کوچک باشد، بخش‌هایی از داده‌های قدیمی حذف می‌شوند و کوئری بالا دیگر قادر به مشاهده‌ی “snapshot اولیه” نیست → نتیجه:

				
					ORA‑۰۱۵۵۵
				
			

🔧 مکانیزم‌های داخلی Undo در Oracle

هر تراکنش تغییر داده، لاگ Undo تولید می‌کند.

این داده‌ها در Extentهای مخصوص در Tablespace ذخیره می‌شوند.

اگر اندازه‌ی Tablespace یا زمان نگهداری داده‌ها (Undo Retention) پایین باشد، اوراکل مجاز است Extentها را reuse کند.

فرمول ساده‌ی پیدایش خطا:

Query طولانی + فعالیت زیاد تراکنش‌های دیگر > فضای Undo موجود ⇒ Snapshot Too Old

🚀 بررسی در نسخه‌های جدید (۱۹c, 21c)

حتی در نسخه‌های جدید اوراکل که از Automatic Undo Management (AUM) استفاده می‌کنند، احتمال وقوع خطا وجود دارد. موارد معمول:

  • کم بودن مقدار پارامتر UNDO_RETENTION
  • پردازش هم‌زمان با حجم بالای تغییرات (DML)
  • عملیات بزرگ Materialized View Refresh
  • اجرای کوئری‌های طولانی صادرات (Data Pump) یا Flashback Queryها

🛠 راهکارهای قطعی و پایدار برای رفع خطای ORA‑۰۱۵۵۵

✅ افزایش حجم Undo Tablespace

اگر فایل Undo کوچک است، به‌راحتی آن را بزرگ‌تر کنید:

				
					ALTER DATABASE DATAFILE '/u01/app/oradata/UNDO01.dbf' RESIZE 5G;

				
			

یا فایل جدید اضافه کنید:

				
					ALTER DATABASE ADD DATAFILE '/u01/app/oradata/UNDO02.dbf' SIZE 5G AUTOEXTEND ON NEXT 500M;

				
			

✅ افزایش مدت نگهداری Undo

پارامتر UNDO_RETENTION زمان نگه‌داری نسخه‌های قدیمی داده‌ها را تعریف می‌کند. مقدار پیشنهادی بین ۹۰۰ تا ۳۶۰۰ ثانیه است:

				
					ALTER SYSTEM SET UNDO_RETENTION = 1800;

				
			

اگر از Automatic Undo Tuning استفاده شود، Oracle خودش این مقدار را بهینه می‌کند.

✅ جدا کردن زمان گزارش‌ها از پردازش‌ها

بهترین کار این است که گزارش‌های طولانی در ساعات کم‌ترافیک اجرا شوند یا روی Replica/Standby Database منتقل گردد.

استفاده از Materialized View هم بسیار مؤثر است.

✅ بهینه‌سازی Loopهای PL/SQL

کوئری‌های طولانی در حلقه‌ها معمولاً عامل اصلی هستند.

نمونه‌ی نادرست:

				
					FOR r IN (SELECT * FROM big_table) LOOP
   process_record(r);
END LOOP;

				
			

بهینه‌شده با LIMIT:

				
					DECLARE
   TYPE t IS TABLE OF big_table%ROWTYPE;
   v_tab t;
BEGIN
   LOOP
      FETCH c BULK COLLECT INTO v_tab LIMIT 500;
      process_bulk(v_tab);
   END LOOP;
END;

				
			

✅ پایش Undo

برای مانیتورینگ فضای Undo:

				
					SELECT tablespace_name, status, bytes/1024/1024 AS MB FROM dba_undo_extents;

				
			

برای بررسی میزان نگه‌داری:

				
					SELECT undo_retention FROM dba_tablespaces WHERE contents='UNDO';

				
			

🧠 راهکارهای پیشرفته برای رفع خطا Snapshot Too Old

۱. اجرای گزارش‌ها در READ ONLY session

				
					   ALTER SESSION SET ISOLATION_LEVEL=READ ONLY;

				
			

۲. گزارش‌گیری از Data Guard (Read-only Standby)

۳. پایش خودکار با دستور:

				
					   SELECT tuned_undo_retention FROM v$undostat;

				
			

📋 چک‌لیست طلایی رفع خطای ORA‑۰۱۵۵۵

اقدام هدف نمونه دستور
🔹 بزرگ کردن Undo Tablespace جلوگیری از Reuse سریع حافظه ALTER DATABASE DATAFILE RESIZE 5G;
🔹 افزایش Undo Retention نگهداری snapshot طولانی‌تر ALTER SYSTEM SET UNDO_RETENTION=1800;
🔹 استفاده از LIMIT در PL/SQL Loop بهینه‌سازی حافظه در Queryهای حجیم BULK COLLECT LIMIT 500;
🔹 تفکیک گزارش از DML کاهش تداخل اجرای هم‌زمان زمان‌بندی گزارش‌ها در کم‌ترافیک‌ترین ساعت
🔹 پایش v$undostat تحلیل وضعیت Undo و Retention SELECT tuned_undo_retention FROM v$undostat;

سوالات متداول درباره رفع خطا Snapshot Too Old در اوراکل

خطای ORA-01555: Snapshot Too Old یعنی اوراکل نتوانسته نسخه‌ی اولیه‌ی داده‌ها (snapshot) را برای اجرای کوئری طولانی بازسازی کند.

این اتفاق معمولاً زمانی رخ می‌دهد که فضای Undo Tablespace پر شده یا داده‌های قدیمی در حین اجرای Query پاک شده باشند.

درواقع اوراکل حافظه‌ی موقتی برای نگه‌داشت داده‌های قبلی ندارد و نمی‌تواند Consistent Read انجام دهد.

زیرا کوئری‌های طولانی زمان زیادی برای پردازش نیاز دارند، و در این مدت تراکنش‌های دیگر ممکن است رکوردهای مورد نیاز را تغییر دهند.

وقتی Undo آن رکوردها دوباره استفاده (overwrite) یا پاک می‌شود، Query طولانی نمی‌تواند snapshot اولیه را ببیند و خطای ORA‑۰۱۵۵۵ تولید می‌شود.

هرچه زمان اجرای Query و ترافیک DML همزمان بیشتر باشد، احتمال بروز خطا بالاتر است.

سه گام کلیدی وجود دارد:

  1. افزایش فضای Undo Tablespace (مثلاً ۵ تا ۱۰ گیگ)
  2. افزایش پارامتر UNDO_RETENTION به حداقل ۱۸۰۰ ثانیه
  3. جدا کردن گزارش‌ها از پردازش‌های DML همزمان

همچنین اجرای گزارش‌ها در حالت READ ONLY یا روی Standby Database در نسخه‌های جدید مثل Oracle 19c، ۲۱c تقریباً این خطا را ریشه‌کن می‌کند.

DBA می‌تواند با مانیتورینگ Viewهای سیستمی زیر، رفتار Undo را زیر نظر بگیرد:

SELECT tuned_undo_retention, undoblks, txncount FROM v$undostat
ORDER BY begin_time DESC;

اگر مقدار tuned_undo_retention کمتر از زمان متوسط اجرای Queryها باشد، احتمال بروز Snapshot Too Old بالاست.

در این حالت باید فضای Undo یا مقدار Retention افزایش داده شود تا Queryها بدون خطا اجرا شوند.

جمع‌بندی

خطای ORA‑۰۱۵۵۵: Snapshot Too Old به معنی از بین رفتن نسخه‌ی قدیمی داده‌هاست که فرآیند Consistent Read را مختل می‌کند. این خطا معمولاً به دلیل:

  • حجم کم Undo Tablespace
  • مقدار پایین Undo Retention
  • یا اجرای کوئری طولانی هم‌زمان با DML زیاد رخ می‌دهد.

با داشتن Undo کافی، تنظیم Retention مناسب و جداسازی بار گزارش از تراکنش‌ها، این خطا کاملاً قابل کنترل است و سیستم شما به پایداری بالا می‌رسد.

در دیتابیس‌های Enterprise یا بانکی، استفاده از Autoextend Undo، مانیتورینگ v$undostat و اجرای گزارش‌ها در Read-only mode به‌صورت زمان‌بندی‌شده، عملاً این خطا را برای همیشه حذف می‌کند.

📥 اگر سوالی داری در مورد خطا Snapshot Too Old در اوراکل داری، در بخش کامنت‌ها بپرس.

میثم راد

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

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

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