Block Corruption

block corruption در بانک اطلاعاتی اوراکل خطای بسیار معروفی است که ممکن است سبب از دست رفتن داده شود این خطا معمولا به خاطر مشکلات سخت افزاری یا سیستم عاملی رخ می دهد و در صورت نداشتن backup سالم از قسمت خراب شده به ناچار باید از اطلاعات ذخیره شده در آن قسمت، صرف نظر کنیم. این اتفاق به دو شکل ممکن است رخ دهد:

Physical corruption: در این صورت، اطلاعات بلاک غیرقابل فهم است و سبب می شود تا کاربر نتواند به اطلاعات ذخیره شده در آن، دسترسی پیدا کند. علت این اتفاق به خطای در i/o، خطای در حافظه، Server Controller  و … بر می گردد. همچنین بلاک می تواند به دلایل مختلفی مثل خرابی هدر، نامعتبری checksum بلاک و ناسازگاری ابتدای بلاک با دنباله آن، خراب محسوب شود. این خطا با ORA-01578 ظهور و بروز می کند.

Logical corruption: در این نوع خطا معمولا header و footer بلاک سالم هستند ولی در محتویات بلاک تناقض وجود دارد برای مثال، فضایی را که هدر بلاک نشان می دهد، با فضای واقعی یکسان نیست. این نوع خطا را می توانیم با ابزار dbv پیدا کنیم البته اگر پارامتر db_block_checking فعال شود، این خطا بصورت ORA-600 [kddummy_blkchk] و ORA-600 [kdBlkCheckError] و یا ORA-00600[3339] در alert log ثبت می شود.

خرابی بلاک ممکن است برای datafile،control file  و یا redo logها رخ دهد ولی در این مطلب روشهای شناسایی و رفع بلاکهای خراب شده data file را مورد بررسی قرار می دهیم. این خرابی ممکن است در چهار سطح Sort block، Undo header and Undo block، Data dictionary object، Fileheader 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، بلاک جدولی را خراب می کنیم(در ویندوزمی توان datafile را با یک ویرایشگر باز کرد و قسمتی از آن را دستکاری کرد) و با استفاده از روشهایی که آورده می شود، این بلاک، بازیابی یا skip می شود. پس از دستور 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 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’

با دستور زیر، دقیقا مشخص می کنیم که اطلاعات کدام 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. DBVERIFY

ویژگی ها:

  1. می تواند بلاکهای خالی را هم چک کند.

2.بررسی به صورت محدوده ای را هم ممکن می سازد.

  1. تنها برای دیتافایل قابل استفاده است.

مثال:

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)

  1. 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’

 

  1. خطای ORA-1578 و ALERT.LOG

ویژگی ها:

  1. هر گاه بخواهیم به شی با بلاک خراب شده دسترسی پیدا کنیم، با خطای ora-1578 مواجه خواهیم شد و این خطا در alert log هم ثبت می شود.

ORA-01578:ORACLE data block corrupted (file # string, block # string)

  1. برای soft corruption در alert log خطای ora-600 را خواهیم دید.
  2. همانطور که قبلا گفته شد، خطای ORA-1578 بیانگر یک Media Corrupt Block می باشد نه یک خطای corruption soft.
  3. RMAN

ویژگی ها:

  1. می تواند بدون اینکه backupای در کار باشد، با استفاده از بانک اطلاعاتی، کشف block corruption کرد.
  2. می توان به صورت موازی شناسایی را انجام داد.
  3. می توان به صورت محدوده ای بلاکها را مورد ارزیابی قرار داد.
  4. rman اطلاعاتش را در مورد خرابی بلاکها، در ویوی v$database_block_corruption, v$backup_corruption قرار می دهد.
  5. می توان دیتافایل، آرشیو لاگ و کنترل فایل را با این ابزار مورد بررسی قرار داد.
  6. تنها با داشتن بکاپ همان datafile هم می توان بلاک را ترمیم کرد.
  7. در صورتی که در هنگام بکاپ گیری، نخواهیم عملیات بخاطر block corruption متوقف شود، می توانیم از دستور زیر استفاده کنیم(البته باید در run{} قرار بگیرد):

set maxcorrupt for datafile 5 to 10246;

  1. با این روش، data lost نخواهیم داشت.

مثال(شناسایی):

برای قبل از 11g:

backup validate datafile 5;

Backup validate check logical database;

BACKUP VALIDATE DATABASE ;

BACKUP VALIDATE CHECK LOGICAL DATABASE ;

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;

  1. Event

ویژگی ها:

  1. با تنظیم این پارامتر در pfile می توان شناسایی و رفع block corruption را انجام داد.
  2. برای همه حالتها جواب نمی دهد.
  3. با این روش، 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″

***

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 datatype .
  2. Clusters در CHECK_OBJECT قابل ارزیابی نیست اما در REBUILD_FREELISTS و SKIP_CORRUPT_BLOCKS قابل استفاده است .
  3. Index-organized table و LOB indexپشتیبانی نمی شوند.

مثال(شناسایی):

برای اینکه بتوانیم عملیات تعمیر را با 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 می کنیم. همچنین باید جدول قبلی را حذف کنیم و جدول جدید را جایگزین آن کنیم.

1. با این روش، 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 هم می توان بلاکهای خراب را skip کرد.

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 ارائه شده باشد، قابل انجام است.
  5. برای حل مشکل 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

========================

  1. 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
  2. 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

=======================

  1. 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

 

  1. data guard

ویژگی ها:

در صورتی که بلاکهای خراب شده در استندبای سالم باشند می توان با استفاده از روشهای زیر، ترمیم را صورت داد:

  1. به استندبای faileover کرد.
  2. datafile موجود در استندبای را به بانک اصلی برد و بعد با آرشیوهای موجود، ریکاوری صورت داد تا بانک در مد کاملا سازگار باز شود.
  3. از دیتافایلbackup rman گرفت و با استفاده از روشهای ارائه شده در rman، بلاکها را ترمیم کرد.

4. از ویژگی جدید Active Standby Database Automatic Block Corruption Repair استفاده کرد. این کار با پروسس پس زمینه ای به نام ABMR انجام می شود(که البته از این روش تا به حال استفاده نکردم).

  1. 5. با این روش، data lost نخواهیم داشت.

 

نکات:

  1. در صورتی که یک data guard کاملا سالم دارید، پیشنهاد می شود که با استفاده از آن مشکل را مرتفع کنید.
  2. برای ترمیم جدول می توان از روشهایی به مثل export سنتی، move و … نیز استفاده کرد منتها باید در ابتدا با روشی مثل event آن بلاک را skip کرد.

 

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد.