خرابی بلاکهای دیتابیس که block corruption خوانده می شود، برای اکثر dbaها آشناست. این خطا که ممکن است سبب از دست رفتن دیتا شود معمولا به دلایل سخت افزاری و یا سیستم عاملی رخ می دهد و در صورت نداشتن backup سالم از بلاکهای خراب شده، به ناچار باید از اطلاعات ذخیره شده در آن قسمت، صرف نظر کنیم.
معمولا خرابی بلاکها، به دو صورت رخ می دهد:
Physical corruption: در این حالت، اطلاعات بلاک غیرقابل فهم هستند و دیتابیس قادر به شناسایی محتویات بلاک نخواهد بود این نوع از خرابی، مانع از دسترسی کاربر به اطلاعات ذخیره شده خواهد شد.
علت این اتفاق به خطای در i/o، خطای در حافظه، Server Controller و … برمی گردد. همچنین بلاک می تواند به دلایل مختلفی چون خرابی هدر، نامعتبری checksum بلاک و ناسازگاری ابتدای بلاک با دنباله آن، خراب محسوب شود.
نکته: در زمان دسترسی کاربر به بلاکهای خراب از نوع Physical corruption، خطای ORA-01578 به کاربر برمی گردد.
Logical corruption: در این نوع خطا معمولا اطلاعات header و footer بلاک سالم و با هم منطبق هستند اما در محتویات بلاک تناقض وجود دارد و بلاک ساختار مدنظر اوراکل را ندارد.
این نوع خطا را می توانیم با ابزار dbv پیدا کنیم شیوه انجام ان در ادامه توضیح داده خواهد شد.
نکته: اگر پارامتر db_block_checking فعال شود، این خطا بصورت [ORA-600 [kddummy_blkchk و [ORA-600 [kdBlkCheckError و یا [ORA-00600[3339 در alert log ثبت خواهد شد.
خرابی بلاک ممکن است برای کنترل فایل، دیتافایل، آرشیولاگ و یا redo log fileها رخ دهد منتها در متن پیش رو، روشهای شناسایی و رفع بلاکهای خراب شده دیتافایل مورد بررسی قرار خواهد گرفت.
این خرابی ممکن است در چهار سطح زیر رخ دهد:
Data dictionary object – (Undo header – Undo block) – File header block – Data/Index block
که بدترین اتفاق ممکن، خرابی در سطح Data dictionary object می باشد که ممکن است مانع از استارت و دردسترس قرار گرفتن دیتابیس شود.
برای شناسایی سریعتر block corruption و همچنین جلوگیری از رخ دادن آن، پارامترهایی اثر گذار هستند نظیر:
پارامتر db_block_checksum: مقدار پیش فرض این پارامتر، برابر با true می باشد به این معنی که DBWR بر اساس بیتهای ذخیره شده در بلاک، بیت کنترلی را محاسبه کرده و آن را در cache header بلاک می نویسد زمانی که این بلاک برای read مورد دسترسی قرار می گیرد، checksum بر اساس اطلاعات درون بلاک دوباره مورد محاسبه قرار خواهد گرفت در صورتی که این مقدار محاسبه شده با مقدار ذخیره شده در هدر بلاک یکسان نباشد، خطای ORA-01578 رخ خواهد داد.
این پارامتر حدودا از 1 تا 5 درصد بر روی عملیات DMLای سربار خواهد گذاشت.
پارامتر db_block_checking: این پارامتر سبب می شود بلاکها قبل از انتقال به دیسک، از نظر صحت header ،footer و بقیه قسمتها مورد ارزیابی قرار بگیرند.
این پارامتر هم حدود1 تا 10 درصد ممکن است بر روی عملیات DMLای سربار اضافه ایجاد کند.
در ادامه سعی داریم تا به طور مختصر، روشهای شناسایی و رفع block corruption را مورد بررسی قرار دهیم.
روشهای شناسایی و رفع block corruption
برای ارائه یک سناریو، در ادامه متن، با استفاده از دستور لینوکسی dd، یکی از بلاکهای متعلق به جدولی از دیتابیس را خراب و یا اصطلاحا corrupt می کنیم و پس از آن، با استفاده از روشهایی، از این بلاک خراب صرف نظر می کنیم و یا آنکه به صورت کامل، این بلاک را ترمیم می کنیم.
نکته: علاوه بر استفاده از دستور dd، می توان از ابزار درونی اوراکل به نام BBED هم برای دستکاری و یا حتی ترمیم بلاکهای datafile استفاده کرد.
مثال:پرس و جوی زیر نشان می دهد که جدول usef_temp شامل 10000 رکورد می باشد و بلاکهای این جدول، فاقد هرگونه خرابی می باشند:
select count(*) from usef.usef_temp;
10000
با دستور زیر، ادرس فیزیکی بعضی از رکوردهای جدول usef_temp را مشخص می کنیم:
select * from (select distinct dbms_rowid.rowid_block_number(rowid) from USEF_TEMP) where rownum < 6;
10246
با کمک دستور dd، بلاک شماره 10246 که حاوی تعدادی از رکوردهای این جدول می باشد را خراب می کنیم:
dd of=/u01/oracle/11g/db1/dbs/USEF_TBS.dbf bs=8192 seek=10246 conv=notrunc count=1 if=/dev/zero
همانطور که در قسمت زیر می بینید، اجرای مجدد دستور بالا، با خطا مواجه شد:
alter system flush buffer_cache;
select * from usef.usef_temp;
ERROR:
ORA-01578: ORACLE data block corrupted (file # 5, block # 10246)
ORA-01110: data file 5: ‘/u01/oracle/11g/db1/dbs/USEF_TBS.dbf’
خطای ORA-01578 شماره دیتافایل و شماره بلاک خراب شده را نمایش می دهد با داشتن این اطلاعات، و کمک با دستور زیر، مشخص می کنیم که اطلاعات کدام object خراب شده است:
SELECT tablespace_name, segment_type, owner, segment_name, partition_name FROM dba_extents WHERE file_id = 5 AND 10246 between block_id and block_id + blocks-1;
در جدول زیر، تعدادی از روشهای شناسایی و ترمیم خرابی بلاک، لیست شده اند:
تعمیر/صرف نظر کردن | شناسایی |
ROWID | DBVERIFY |
(export(expdp | export |
RMAN | RMAN |
Event | Event |
DBMS_REPAIR | DBMS_REPAIR |
Data guard | ORA-1578 و ALERT.LOG |
Data Recovery Advisor | Data Recovery Advisor |
ANALYZE TABLE |
در ادامه متن، هر کدام از این روشهای شناسایی و ترمیم را مورد بررسی بیشتر قرار خواهیم داد.
1.ابزار DBV
این ابزار، همراه با نصب نرم افزار اوراکل، در دسترس خواهد بود و برای شناسایی بلاکهای خراب دیتافایلها کاربرد دارد تعدادی از ویژگهای این ابزار را در قسمت زیر، می بینید:
ویژگی ها:
1.بلاکهای خالی را هم بررسی می کند.
2.با کمک این ابزار، بررسی به صورت بازه ای، هم امکان پذیر خواهد بود.
3.تنها برای دیتافایلها قابل استفاده است.
مثال:
dbv file=/u01/oracle/11g/db1/dbs/USEF_TBS.dbf
DBVERIFY: Release 11.2.0.1.0 – Production on Mon Aug 31 15:34:11 2015
Copyright I 1982, 2009, Oracle and/or its affiliates. All rights reserved.
DBVERIFY – Verification starting : FILE = /u01/oracle/11g/db1/dbs/USEF_TBS.dbf
Page 10246 is marked corrupt
Corrupt block relative dba: 0x01402806 (file 5, block 10246)
Completely zero block found during dbv:
DBVERIFY – Verification complete
Total Pages Examined : 256000
Total Pages Processed (Data) : 88482
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 796
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 166721
Total Pages Marked Corrupt : 1
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 3570163974 (36.3570163974)
2.دستور ANALYZE TABLE
این دستور هم برای شناسایی بلاکهای خراب کاربرد دارد.در قسمت زیر، تعدادی از ویژگی های این دستور را در این زمینه، برشمردیم:
ویژگی ها:
1.در سطح object خرابی بلاک را بررسی می کند.
2.خرابی از نوع logical را هم مورد بررسی قرار خواهد داد.
مثال:
ANALYZE TABLE usef.usef_temp VALIDATE STRUCTURE CASCADE;
ANALYZE TABLE usef.usef_temp VALIDATE STRUCTURE CASCADE
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 5, block # 10246)
ORA-01110: data file 5: ‘/u01/oracle/11g/db1/dbs/USEF_TBS.dbf’
3.خطای ORA-1578 و ALERT LOG
ویژگی ها:
1.با دسترسی به یک جدول با بلاکی خراب از نوع physical corruption، خطای ORA-01578 برگردانده می شود همچنین این خطا در alert log هم ثبت می شود. فرمت این خطا، به صورت زیر می باشد:
ORA-01578:ORACLE data block corrupted (file # string, block # string)
2.همانطور که در ابتدای متن هم اشاره شد، logical corruptionها با خطای ORA-600 مشخص می شوند این نوع از خطاها هم در alert log قابل رویت می باشند.
4.ابزار RMAN
ویژگی ها:
1.این ابزار می تواند بدون گرفتن backup،بلاکهای خراب را شناسایی کند.
2.با کمک ابزار rman، می توان به صورت موازی شناسایی بلاکهای خراب را انجام داد.
3.می توان به صورت محدوده ای بلاکها را مورد ارزیابی قرار داد.
4.اطلاعات rman در مورد بلاکهای خراب، در ویوی v$database_block_corruption و v$backup_corruption قابل رویت می باشند.
5.می توان دیتافایل، آرشیو لاگ و کنترل فایل را با این ابزار مورد بررسی قرار داد.
6.تنها با داشتن بکاپ یک datafile هم می توان بلاکهای ان دیتافایل را ترمیم کرد البته داشتن آرشیولاگها از زمان گرفتن بکاپ تا زمان ریکاوری، اجباری می باشد.
7.به صورت پیش فرض، ابزار RMAN با مشاهده اولین بلاک خراب، بکاپ گیری را متوقف خواهد کرد، برای جلوگیری از این مسئله، می توانیم از دستور زیر، در بلاک RUN استفاده کنیم:
set maxcorrupt for datafile #DATAFILE_NUMBER to #COUNT_BLOCK;
8.با این روش، data lost نخواهیم داشت.
مثال(شناسایی):
قبل از اوراکل 11g:
*backup validate datafile 5;
*Backup validate check logical database;
*BACKUP VALIDATE DATABASE ;
*BACKUP VALIDATE CHECK LOGICAL DATABASE ;
بعد از اجرای هر کدام از دستورات بالا، برای مشاهده بلاکهای خراب، باید ویوی v$database_block_corruption را مورد بازبینی قرار داد:
select * from v$database_block_corruption;
بعد از اوراکل 11g:
*validate check logical database;
*VALIDATE DATAFILE 5 block 10246;
*backup validate tablespace usef_tbs;
*VALIDATE ARCHIVELOG ALL;
*VALIDATE CHECK LOGICAL CURRENT CONTROLFILE;
مثال(رفع):
catalog start with ‘/u01/oracle/databkp.bkp’;
BLOCKRECOVER DATAFILE 5 BLOCK 10246 ;
Starting recover at 06-SEP-15
using channel ORA_DISK_1
channel ORA_DISK_1: restoring block(s)
channel ORA_DISK_1: specifying block(s) to restore from backup set
restoring blocks of datafile 00005
channel ORA_DISK_1: reading from backup piece /u01/oracle/databkp.bkp
channel ORA_DISK_1: piece handle=/u01/oracle/databkp.bkp tag=TAG20150905T144833
channel ORA_DISK_1: restored block(s) from backup piece 1
channel ORA_DISK_1: block restore complete, elapsed time: 00:00:25
البته اگر تعداد بلاکهای خراب زیاد باشد، می توان از دستور زیر استفاده کرد:
blockrecover corruption list;
5.پارامتر EVENTS
ویژگی ها:
- با تنظیم این پارامتر می توان شناسایی و رفع block corruption را انجام داد.
- برای همه حالتها جواب نمی دهد.
- با این روش، data lost خواهیم داشت.
مثال(شناسایی):
event = “10210 trace name context forever, level 10” à for data block
event = “10212 trace name context forever, level 10” àfor cluster block
event = “10211 trace name context forever, level 10” à for index block
مثال(صرف نظر کردن از بلاکهای خراب):
برای اینکه از full table scan جلوگیری نشود:
event = “10231 trace name context forever, level 10”
برای اینکه از index range scan جلوگیری نشود:
Event=”10233 trace name context forever, level 10″
***
با در نظر داشتن خرابی بلاک مربوط به جدول USEF_TEMP، با کمک این پارامتر از این خرابی صرف نظر می کنیم:
SQL> ALTER SYSTEM SET EVENTS=’10231 trace name context forever,level 10′;
SQL> create table usef.usef_health as select * from usef.usef_temp;
SQL> select count(*) from usef_health;
count(*)
9998
SQL> DROP TABLE usef_temp;
SQL> RENAME usef_health to usef_temp;
SQL> ALTER SYSTEM SET EVENTS ‘10231 trace name context off’;
6. بسته DBMS_REPAIR
ویژگی ها:
1.عدم پشتیبانی ستون out of line برای جداولی با نوع داده LOB .
2.Index-organized table و LOB index پشتیبانی نمی شوند.
3.Clusters در CHECK_OBJECT قابل ارزیابی نیست اما در REBUILD_FREELISTS و SKIP_CORRUPT_BLOCKS قابل استفاده می باشد.
مثال(شناسایی):
برای اینکه بتوانیم عملیات تعمیر را با dbms_repair انجام دهیم حداقل به یک جدول نیاز داریم تا اطلاعات corrupt block را در آن قرار دهیم:
exec DBMS_REPAIR.ADMIN_TABLES(TABLE_NAME => ‘REPAIR_TABLE’,TABLE_TYPE => dbms_repair.repair_table,ACTION => dbms_repair.create_action,TABLESPACE => ‘USERS’);
در ابتدا باید block corruption را در جدول شناسایی کرد این کار با استفاده از پروسیجر CHECK_OBJECT قابل انجام است:
declare
num_corrupt int;
begin num_corrupt := 0;
dbms_repair.check_object(schema_name => ‘USEF’,
object_name => ‘USEF_TEMP’,
repair_table_name => ‘REPAIR_TABLE’,
corrupt_count => num_corrupt);
dbms_output.put_line( ‘number corrupt: ‘ || to_char (num_corrupt));
end;
بلاکهای خراب شناسایی شده را می توان در ویوی زیر دید:
select * from repair_table;
مثال(رفع):
DECLARE
num_fix INT;
BEGIN num_fix := 0;
DBMS_REPAIR.FIX_CORRUPT_BLOCKS ( SCHEMA_NAME => ‘USEF’,
OBJECT_NAME => ‘USEF_TEMP’,
OBJECT_TYPE => dbms_repair.table_object ,
REPAIR_TABLE_NAME => ‘REPAIR_TABLE’,
FIX_COUNT => num_fix);
DBMS_OUTPUT.PUT_LINE(‘num fix: ‘ || TO_CHAR(num_fix));
END;
exec dbms_repair.skip_corrupt_blocks (schema_name => ‘USEF’, object_name =>’USEF_CORRUPTION’ , flags => 1);
برای غیر فعال کردن skip، flags را برابر با sys.dbms_repair. noskip_flag قرار می دهیم.
برای بازسازی freelist جدول می توانیم به شکل زیر عمل کنیم:
begin
dbms_repair.rebuild_freelists (schema_name => ‘USEF’,
object_name => ‘USEF_TEMP’, OBJECT_TYPE => dbms_repair.table_object);
end;
7. rowid method
ویژگی ها:
1. در ابتدا با کمک rowid رکوردهایی که در بلاک خراب قرار دارند، جدولی ایجاد می کنیم پس از آن، اطلاعات بالای rowidهای خراب را در جدول جدید insert می کنیم در نهایت، جدول قبلی را حذف کرده و جدول جدید را جایگزین آن کنیم.
2. با این روش، data lost خواهیم داشت.
SELECT tablespace_name, relative_fno, segment_type, owner, segment_name, partition_name FROM dba_extents WHERE file_id = 5 AND 10219 between block_id and block_id + blocks-1;
5
SELECT data_object_id FROM dba_objects WHERE object_name = ‘USEF_TEMP’ AND owner = ‘USEF’;
75057
SELECT dbms_rowid.rowid_create (1,75057,5 ,10219, 0) LOW_RID from DUAL;
‘AAASUxAAFAAACfrAAA’
SELECT dbms_rowid.rowid_create (1,75057, 5, 10219 +1,0) HI_RID from DUAL;
‘AAASUxAAFAAACfsAAA’
create table usef.usef_temp5 as select * from usef.usef_temp A WHERE rowid < ‘AAASUxAAFAAACfrAAA’;
insert into usef.usef_temp5 select * from usef.usef_temp WHERE rowid >= ‘AAASUxAAFAAACfsAAA’;
8. EXPDP
با استفاده از ابزار expdp هم می توان از بلاکهای خراب صرف نظر نمود:
expdp directory=usef dumpfile=usef3.dmp tables=usef_test
Starting “USEF”.”SYS_EXPORT_TABLE_01″: usef/******** directory=usef dumpfile=usef3.dmp tables=usef_test
Estimate in progress using BLOCKS method…
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 40 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
. . exported “USEF”.”USEF_TEST” 28.72 MB 9982 rows
Job “USEF”.”SYS_EXPORT_TABLE_01″ successfully completed at 15:08:55
impdp directory=usef dumpfile=usef3.dmp tables=usef_test remap_table=usef_test:usef_test2 remap_tablespace=usef_tbs:usef_tbs2
Master table “USEF”.”SYS_IMPORT_TABLE_01″ successfully loaded/unloaded
Starting “USEF”.”SYS_IMPORT_TABLE_01″: usef/******** directory=usef dumpfile=usef3.dmp tables=usef_test remap_table=usef_test:usef_test2 remap_tablespace=usef_tbs:usef_tbs2
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported “USEF”.”USEF_TEST2″ 28.72 MB 9982 rows
Job “USEF”.”SYS_IMPORT_TABLE_01″ successfully completed at 15:10:40
dbv file=/u01/oracle/11g/db1/dbs/USEF_TBS2.dbf
Total Pages Failing (Data) : 0
Total Pages Failing (Index): 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 2562
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Total Pages Encrypted : 0
Data Recovery Advisor (DRA) .9
ویژگی ها:
1.این ویژگی از اوراکل 11g برای کمک به dba ارائه شده است.
2.با استفاده از rman اجرا می شود و در صورت امکان، خطاهای مربوط به ریکاوری را در دیتابیس شناسایی می کند و توصیه هایی را به dba ارائه می دهد همچنین در بعضی از موارد، امکان رفع مشکل را هم فراهم می کند.
3.برای استفاده از DRA، سه مرحله list، advise و repair باید انجام شود و ترتیب اجرای آنها بسیار مهم است.
4.مرحله repair failure، تنها در صورتی که در مرحله دوم، Automated Repair Options ارائه شده باشد، قابل انجام خواهد بود.
6.DRA برای حل مشکل block corruption، از روشهای قبلی استفاده می کند.
RMAN> list failure;
using target database control file instead of recovery catalog
List of Database Failures
=========================
Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
10402 HIGH OPEN 31-AUG-15 Datafile 5: ‘/u01/oracle/11g/db1/dbs/USEF_TBS.dbf’ contains one or more corrupt blocks
RMAN> advise failure;
List of Database Failures
=========================
Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
10402 HIGH OPEN 31-AUG-15 Datafile 5: ‘/u01/oracle/11g/db1/dbs/USEF_TBS.dbf’ contains one or more corrupt blocks
analyzing automatic repair options; this may take some time
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=70 device type=DISK
analyzing automatic repair options complete
Mandatory Manual Actions
========================
- No backup of block 10246 in file 5 was found. Drop and re-create the associated object (if possible), or use the DBMS_REPAIR package to repair the block corruption
- No backup of block 10219 in file 5 was found. Drop and re-create the associated object (if possible), or use the DBMS_REPAIR package to repair the block corruption
Optional Manual Actions
=======================
- Shut down, mount the database and try flush redo using ALTER SYSTEM FLUSH REDO TO ‘standby name’ command. Then perform a Data Guard role change (failover). Available standbys: st.
Automated Repair Options
========================
Option Repair Description
—— ——————
1 Recover multiple corrupt blocks in datafile 5
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/oracle/diag/rdbms/bi/bi/hm/reco_1210447603.hm
RMAN> repair failure;
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/oracle/diag/rdbms/bi/bi/hm/reco_1210447603.hm
contents of repair script:
# block media recovery for multiple blocks
recover datafile 5 block 4643, 10219 to 10220, 10222, 10243 to 10247, 54387, 59499 to 59500, 59563
to 59565;
Do you really want to execute the above repair (enter YES or NO)? YES
executing repair script
Starting recover at 05-SEP-15
using channel ORA_DISK_1
channel ORA_DISK_1: restoring block(s)
channel ORA_DISK_1: specifying block(s) to restore from backup set
restoring blocks of datafile 00005
channel ORA_DISK_1: reading from backup piece /u01/oracle/databkp.bkp
channel ORA_DISK_1: piece handle=/u01/oracle/databkp.bkp tag=TAG20150905T144833
channel ORA_DISK_1: restored block(s) from backup piece 1
channel ORA_DISK_1: block restore complete, elapsed time: 00:00:07
starting media recovery
archived log for thread 1 with sequence 1123 is already on disk as file +BI/bi/archivelog/2015_09_05/thread_1_seq_1123.282.889614555
archived log for thread 1 with sequence 1124 is already on disk as file +BI/bi/archivelog/2015_09_05/thread_1_seq_1124.281.889614555
media recovery complete, elapsed time: 00:00:47
Finished recover at 05-SEP-15
repair failure complete
10.دیتاگارد
ویژگی ها:
در صورتی که بلاکهای خراب در دیتاگارد سالم باشند می توان با کمک یکی از روشهای زیر، ترمیم را صورت داد:
1.به دیتاگارد faileover کرد.
2.datafile موجود در دیتاگارد را به بانک اصلی منتقل نمود.
3.از دیتافایل backup rman گرفته و با استفاده از روشهای ارائه شده در قسمت “ابزار rman”، بلاکهای خراب را ترمیم کرد.
4. از ویژگی جدید اوراکل Active Standby Database Automatic Block Corruption Repair استفاده نمود. این کار با کمک پروسس پس زمینه ای به نام ABMR انجام می شود.
5. با کمک این روش، data lost نخواهیم داشت.
نکات پایانی:
1.در صورت وجود data guard سالم و فاقد هرگونه خرابی در سطح بلاک، پیشنهاد می شود که از دیتاگارد برای رفع خرابی بلاکها استفاده شود.
2.برای ترمیم جدول می توان از روشهای چون export سنتی، move و … نیز استفاده کرد منتها باید در ابتدا با روشی مثل event آن بلاک را skip کرد.