همانطور که می دانید، با شروع یک تراکنش، undo segmentای هم به آن اختصاص داده می شود تا اطلاعاتی که تراکنش در حال کار با ان است را در خود جای دهد به طور مثال، قبل از حذف یک رکورد در یک تراکنش، اطلاعات آن رکورد در undo segment نوشته خواهد شد.
هدف از این مسئله به پشتیبانی اوراکل از قابلیتهایی چون read consistency، rollback operation و انواع مختلف flashbackها در دیتابیس بر می گردد که البته در مورد هر کدام از این قابلیتها، قبلا مطالبی را ارائه کردیم و در این مطلب صرفا به بررسی نکته ای در مورد flashback query خواهیم پرداخت.
توجه 1: undo segment صرفا به یک تراکنش اختصاص ندارد و در یک زمان ممکن است چندین تراکنش با یک undo segment در حال کار باشند.
توجه 2: در نسخه های قدیمی اوراکل، undo به صورت دستی مدیریت می شد به عبارت تخصصی تر، از rollback segment به جای undo segment استفاده می شد. البته هنوز هم امکان ایجاد و استفاده از rollback segmentها در نسخه های فعلی اوراکل(12c,18c,19) وجود دارد.
با توجه به نکات گفته شده، روشن است که می توان اطلاعات قبلی جداول را با کمک undo segmentها مشاهده و یا در صورت لزوم برگرداند(البته در صورت وجود فضای کافی برای undo tablespaceها و سپری نشدن retention خودکار مشخص شده توسط دیتابیس).
برای مثال، با حذف اطلاعات جدول mytbl، می توان از اطلاعات موجود در undo کمک گرفته و اطلاعات حذف شده را مشاهده و در صورت لزوم برگرداند:
SQL> create table mytbl as select level a from dual connect by level<10;
Table created
SQL> select count(*),to_char(sysdate,’YYYY/MM/DD HH24:mi:ss’) date_ from mytbl;
COUNT(*) DATE_
———- ——————-
9 2020/03/28 10:39:53
SQL> delete mytbl;
9 rows deleted
SQL> commit;
Commit complete
SQL> select to_char(sysdate,’YYYY/MM/DD HH24:mi:ss’) date_ from dual;
DATE_
——————-
2020/03/28 10:43:01
SQL> select count(*) from mytbl as of timestamp( sysdate -interval ‘5’ minute);
ORA-01466: unable to read data – table definition has changed
SQL> select count(*) from mytbl as of timestamp( sysdate -interval ‘3’ minute);
COUNT(*)
———-
9
حال اگر تغییری در متن پروسیجر، فانکشن، پکیج، تریگر و … ایجاد شده باشد و یا هر کدام از این اشیا به اشتباه و یا به عمد حذف شده باشند، چگونه می توان با کمک undo این اشیا را برگرداند و یا محتویات قبلی آنها را مشاهده کرد؟
در ابتدا باید در نظر داشته باشیم که محتویات این نوع از اشیا(پروسیجر، فانکشن و…)، در یکی از جداول دیتادیکشنری که $source نام دارد ذخیره می شود و با هر گونه تغییر در متن هر کدام از این اشیا، رکورد یا رکوردهای از این جدول هم تغییر خواهند کرد پس برای مشاهده شکل قبلی اطلاعات این نوع از اشیا، می توان نگاهی به اطلاعات موجود در جدول $source و یا ویوی dba_sources انداخت:
SQL> create or replace function func RETURN date
2 as
3 a date;
4 begin
5 select sysdate into a from dual;
6 return a;
7 end;
8 /
Function created
SQL> select * from dba_source p where p.NAME=’FUNC’;
فرض کنید بعد از مدتی، متن این function را به صورت زیر تغییر داده ایم:
SQL> create or replace function func RETURN varchar as
2 b varchar2(30);
3 begin
4 select ‘vahid usefzadeh’ into b from dual;
5 return b;
6 end;
7
8 /
Function created
SQL> select func from dual;
FUNC
————–
vahid usefzadeh
SQL>select * from dba_source p where p.NAME=’FUNC’;
بر اساس انچه که بیان شد، برای مشاهده شکل قبلی این تابع، می توان به قسمتی از اطلاعات قدیمی جدول $source که در undo موجود هستند، رجوع کرد(با اتصال به کاربر sys):
SQL> show user
User is “SYS”
SQL> select * from dba_source as of timestamp( sysdate -interval ’14’ minute) where NAME = ‘FUNC’;
این قاعده در مورد حذف این function هم صادق خواهد بود:
SQL> drop function func;
Function dropped
SQL> select * from dba_source as of timestamp( sysdate -interval ’65’ minute) where NAME = ‘FUNC’;
همانطور که می بینید، با کمک undo به متن این فانکشن دسترسی پیدا کردیم.