How to Generate Block Corruption – Using dd

Block corruption rarely happen. This is a fact and a good fact. The only problem with this is that it will be difficult to get some experience with because is too rare (from my experience). The only option is to get some tools in our lab to ensure that we can do some corruption. This time i’ll use dd. Please note that this article is mainly a note for me (and for you, if you want) not really an innovative article.

Scenario

We need to create a tablespace, a user and a table to handle the experiments:

SQL> create tablespace ts_dbc datafile '+DATA/RAC/DATAFILE/ts_dbc.df' size 20m autoextend on next 10m extent management local segment space management auto;

Tablespace created.

SQL> create user user_dbc identified by user_dbc default tablespace ts_dbc;
User created.

SQL> grant connect, resource to user_dbc;
Grant succeeded.


[oracle@rac1 ~]$ sqlplus user_dbc/user_dbc@RAC_VMs

SQL> create table table_dbc as select dbms_random.value(0,100) N1 from dual connect by level <= 1000;
Table created.

SQL> column segment_name format a10;
SQL> select segment_name, tablespace_name from user_segments where segment_name='TABLE_DBC';

SEGMENT_NA TABLESPACE_NAME
---------- ------------------------------
TABLE_DBC  TS_DBC

Using dd

It will be just easy to generate some trash in the block to make corruption happen, but with ASM (AFAIK) dd can’t access directly to the ASM raw filesystem and we need to perform additional steps to get datafile out of ASM and in again after generate some noise in the block. To make task easier i’ll use RMAN:

Take datafile offline:


SQL> alter database datafile '+DATA/RAC/DATAFILE/ts_dbc.df' offline;
Database altered.

[oracle@rac1 ~]$ export ORACLE_SID=RAC1
[oracle@rac1 ~]$ rman target=/

RMAN> BACKUP AS COPY DATAFILE '+DATA/RAC/DATAFILE/ts_dbc.df' FORMAT '/tmp/ts_dbc_%f';
...
channel ORA_DISK_1: starting datafile copy
input datafile file number=00007 name=+DATA/rac/datafile/ts_dbc.df
output file name=/tmp/ts_dbc_7 tag=TAG20120303T111330 RECID=2 STAMP=776949222
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:16
..

After getting datafile out of ASM, we need to check the header_block:

SQL> select header_file, header_block from dba_segments where segment_name='TABLE_DBC';

HEADER_FILE HEADER_BLOCK
----------- ------------
          7          130

So the header of segment (table) is block 130, so if the block 131,132,133,… get some noise it will eventually end up as a datafile with corrupted blocks 🙂

[oracle@rac1 tmp]$ dd of=ts_dbc_7 bs=8192 conv=notrunc seek=131 << EOF
> #allglorytocorruption#
> EOF
0+1 records in
0+1 records out
23 bytes (23 B) copied, 0.0801337 seconds, 0.3 kB/s
[oracle@rac1 tmp]$ dd of=ts_dbc_7 bs=8192 conv=notrunc seek=132 << EOF
> #allglorytocorruption#
> EOF
0+1 records in
0+1 records out
23 bytes (23 B) copied, 0.0411593 seconds, 0.6 kB/s

Let’s make sure using dbv (DBVERIFY) that we have generated some corruption:


[oracle@rac1 bin]$ dbv file=/tmp/ts_dbc_7 blocksize=8192

DBVERIFY - Verification starting : FILE = /tmp/ts_dbc_7
Page 131 is marked corrupt
Corrupt block relative dba: 0x01c00083 (file 7, block 131)

Page 132 is marked corrupt
Corrupt block relative dba: 0x01c00084 (file 7, block 132)

Page 133 is marked corrupt
Corrupt block relative dba: 0x01c00085 (file 7, block 133)

Another way to verify corruption on block is dump the block and read the output generated. Trace will show that datafile header is corrupt, meaning that checksum present in header is not consistent:


SQL> alter system dump datafile 7 block 131

...
Read of datafile '+DATA/rac/datafile/ts_dbc.df' (fno 7) header failed with ORA-01210
Hex dump of (file 7, block 1)
...

After inject some noise in datafile using dd, we need to restore the corrupted datafile back to ASM filesystem using RMAN:

RMAN> RUN
2> {
3> RESTORE DATAFILE '+DATA/RAC/DATAFILE/ts_dbc.df' FROM TAG 'TAG20120303T111330';
4> RECOVER DATAFILE  '+DATA/RAC/DATAFILE/ts_dbc.df';
5> }

RMAN script will eventually fails with ORA-19566 [exceeded limit of 0 corrupt blocks for file /tmp/ts_dbc_7] because RMAN will not allow to restore any datafile with corrupted blocks. The workaround for this is to set parameter MAXCORRUPT

Note: You will need to remove the file directly in asmcmd to RMAN performs the restore and recovery otherwise you will end up with and ORA 01135: file n accessed for DML/query is offline.

RMAN> RUN
2> {
3> SET MAXCORRUPT FOR DATAFILE '+DATA/rac/datafile/ts_dbc.df' TO 3;
4> RESTORE DATAFILE '+DATA/RAC/DATAFILE/ts_dbc.df' FROM TAG 'TAG20120303T111330';
5> RECOVER DATAFILE  '+DATA/RAC/DATAFILE/ts_dbc.df';
6> }

After restore and recover datafile must be online:

SQL> alter database datafile '+DATA/RAC/DATAFILE/ts_dbc.df' ONLINE;
Database altered.

Finally we query v$database_block_corruption to unsure that Oracle is fully aware of corrupted blocks:

SQL> select * from v$database_block_corruption;

     FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
         7        131          3                  0 CORRUPT

Advertisements

2 thoughts on “How to Generate Block Corruption – Using dd

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s