Search This Blog

Friday, June 29, 2012

Active Transaction's


Clearing Active Transactions in Database:

I would like to share one of my experience on trouble shooting databases. I was working on a project database migration  to the newer and faster hardware on a different OS platform. During the migration it was required to check the compatibility of database to the new platform. While running the compatibility check we hit an error.

declare
db_ready   boolean;
begin
db_Ready :=dbms_tdb.check_db ('AIX-Based Systems (64-bit)');
end;
/

“There are active transactions in the database. Open the database in READ/WRITE mode and roll back the transactions. After the active transactions are rolled back, open the database in READ-ONLY mode and retry”.


We bounced the database to see if those active transactions got cleared from the database. And reran the compatibility check, No luck still the error/transaction persists in the database. Upon research on how there could be any transaction in the undo would be active even after the database bounce. We found these transactions are distributed transactions meaning the transactions involving more than one databases.

The distributed transactions in databases should comply with ACID properties of database transaction which guarantees all-or-nothing outcomes for the unit of work. In order to complete the distributed transaction correctly an algorithm is applied i.e. two phase commit protocol (2PC).

During the execution of distributed transaction the protocol completes the transaction in two phases.

 i) Commit Request Phase: A coordinator process (where the transaction is been initiated) attempts to prepare all the participating processes (the other DB’s involved) to take necessary steps for either commit or rollback the transaction.

 ii) Commit Phase: The coordinator decides whether to commit or rollback the transaction notifies the participating transactions of the decision to take necessary action on the local resources to complete the transaction.

In our case we some have had some segments in undo tablespace holding these transactions in active state waiting for acknowledgement from the coordinator process for the decision to commit or rollback. Since the database is no longer doing any sorts of distributed transactions with any database, we decided to get rid of these transactions.

So here are the brief steps to clear such transactions. Oracle provides two views DBA_2PC_PENDING, DBA_2PC_NEIGHBORS to identify the distributed transactions.


Steps to clear the active transaction in the undo segments:

Step 1:  Run the query to check status of the active transaction

SQL> select local_tran_id, state from dba_2pc_pending;

   LOCAL_TRAN_ID          STATE
   ----------------------         ----------------
    99.20.68809                  prepared
    111.12.10265                prepared

Step 2:  Run the query to determine the active transactions in the rollback segment

SQL>   select KTUXEUSN, KTUXESLT, KTUXESQN, KTUXESTA status
        2  from x$ktuxe
        3  where ktuxesta != 'INACTIVE'
        4  and ktuxeusn IN (99, 111);

KTUXEUSN  KTUXESLT  KTUXESQN  STATUS                 
 ----------         ----------      ---------- -----------  ----- ---------          
     99                20            68809      PREPARED             
    111               12           10265      PREPARED              

Step 3: Run the force commit statements

Commit force ‘99.20.68809’;

Commit force ‘111.12.10265’;

 Commit;

Step 4:  Repeat step2 to confirm the active transactions no longer exists. If they exist then run   step 5.
  
Step 5: Run the force rollback statements

Rollback force ‘99.20.68809’;

Rollback force ‘111.12.10265’;
 
Commit;

Step 6:  Repeat step2 to confirm the active transactions no longer exists. If they exist then run   step 7.

Step 7:  If the above commit and rollback statements failed then manually clear the transactions by running the following queries.

a)  delete from sys.pending_trans$
     where local_tran_id IN (‘99.20.68809’, ‘111.12.10265’);

b)  delete from sys.pending_sessions$
      where local_tran_id IN (‘99.20.68809’, ‘111.12.10265’);

c) delete from sys.pending_sub_sessions$
      where local_tran_id IN (‘99.20.68809’, ‘111.12.10265’);    

commit;

Step 8:  Repeat step2 to confirm the deletion of active transactions.



Tuesday, June 26, 2012

Block Corruption

Block Corruption in Oracle Database:

Corruption is Spiritual or Moral impurity in a system/organization causes the failure of system. Similarly block corruption in database causes failures in data read and write from/to the block. Block corruption could be Physical or logical.

 Physical Block Corruption:

If a block is bad header/Fractured/Incomplete/Bad checksum is invalid/Block is misplaced.

Bad header - the beginning of the block (cache header) is corrupt with invalid values.
Block is Fractured/Incomplete - Information from the block header does not match the block tail.
Block checksum is invalid -  DB_BLOCK_CHECKSUM init parameter are used to identify if the block was changed by something external to Oracle and after the block was last written by Oracle. Checksum is calculated by DBWR or direct loader before writing the block to disk and stored in the block header. Every time that the block is read and if db_block_checksum is different than false, Oracle calculates a checksum and compares it to the one stored in the block header.
Block is misplaced - When oracle detected that the content of the block being read  belongs to a different block and the checksum is valid. Normally physical block corruption reported as ORA-1578 and the detailed corruption description is printed in the alert log.


Logical Block Corruption:

When block contains a valid checksum and the structure below the beginning of the block is corrupt (Block content is corrupt). 

Logical Corruptions are not normally printed in the alert.log. DBV verify will report what is logically corrupted in the block.

When db_block_checking is enabled, it may produce the internal error ORA-600 [kddummy_blkchk].

If db_block_checking is enabled and the block is already logically corrupt on disk, the next block update will mark the block as Soft Corrupt and future reads of this block will produce the error ORA-1578. In that case DBV verify reports this corruption with error "DBV-200: Block, dba , already marked corrupted".


To identify corrupted block segments in the database:

Oracle Provides two utilities to identify the corrupted blocks in database.
  • RMAN (Recovery Manager) 
  •  DBV (DBV verify utility)
 Using RMAN:

Below rman script checks the complete database for both corruptions without actually doing a backup: The database should be running in Archive log mode.

 run {
allocate channel ch1 type disk;
allocate channel ch2 type disk;
backup validate check logical database;
}


·         PARALLELISM using multiple channels to make the validation faster.
·         By Default RMAN backup validate command only detect Physical Block Corruptions without the CHECK LOGICAL option.

 Using DBV :

DBV verify identify Physical and Logical Intra Block Corruptions by default. DBV cannot be run for the whole database in a single command. It’s optional to use the db connection.


dbv userid=system/abcd1234 file= /ora10g/oradata/ORCL/users01.dbf blocksize=8192

DBVERIFY: Release 10.2.0.4.0 - Production on Tue Jun 26 11:21:04 2012

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

DBVERIFY - Verification starting : FILE = /dwtest/oradata/DWTEST/users01.dbf


DBVERIFY - Verification complete

Total Pages Examined         : 16512
Total Pages Processed (Data) : 3298
Total Pages Failing   (Data) : 0
Total Pages Processed (Index): 442
Total Pages Failing   (Index): 0
Total Pages Processed (Other): 2931
Total Pages Processed (Seg)  : 89
Total Pages Failing   (Seg)  : 0
Total Pages Empty            : 9752
Total Pages Marked Corrupt   : 0
Total Pages Influx           : 0
Highest block SCN            : 1804661127 (10.1804661127)



 RMAN vs DBV:
      
·       RMAN can be run with PARALLELISM option, making it faster than DBV which can't be run in   parallel.
·      DBV checks for empty blocks. So it will take more time to scan entire data file.
·        In 10g RMAN may not check blocks in free extents when Locally Managed Tablespaces are used.
·      In 11g RMAN checks for both free and used extents.
·      Both DBV and RMAN (11g) can check for a range of blocks. 

RMAN: VALIDATE DATAFILE 1 BLOCK 10 to 100
DBV: file=user01.dbf start=10 end=100

·         RMAN keeps corruption information in the control file (v$database_block_corruption, v$backup_corruption). DBV does not. 
·         RMAN may not report the corruption details like what is exactly corrupted in a block reported as a LOGICAL corrupted block. DBV reports the corruption details in the screen or in a log file.
·         DBV can scan blocks with a higher SCN than a given SCN.
·         DBV does not need a connection to the database.   


Note:  When we use RMAN validation, Oracle keeps the information on control file which we can query using  V$database_block_corruption and v$backup_corruption.

The statement below gets the corrupted block id & type of corruption.


Select * from v$database_block_corruption;


The statement below identifies the corrupted segment list (if we find db block corruption using dbv/rman, we can pass the data file_id and corrupted block id value).
  
select * from dba_extents
where file_id = &DATA_FILE_ID
and &CORRUPTED_BLOCK_ID between block_id AND block_id + blocks - 1;

(or)

SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file#
     , greatest(e.block_id, c.block#) corr_start_block#
     , least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block#
     , least(e.block_id+e.blocks-1, c.block#+c.blocks-1)
       - greatest(e.block_id, c.block#) + 1 blocks_corrupted
     , null description
  FROM dba_extents e, v$database_block_corruption c
 WHERE e.file_id = c.file#
   AND e.block_id <= c.block# + c.blocks - 1
   AND e.block_id + e.blocks - 1 >= c.block#
UNION
SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file#
     , header_block corr_start_block#
     , header_block corr_end_block#
     , 1 blocks_corrupted
     , 'Segment Header' description
  FROM dba_segments s, v$database_block_corruption c
 WHERE s.header_file = c.file#
   AND s.header_block between c.block# and c.block# + c.blocks - 1
UNION
SELECT null owner, null segment_type, null segment_name, null partition_name, c.file#
     , greatest(f.block_id, c.block#) corr_start_block#
     , least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block#
     , least(f.block_id+f.blocks-1, c.block#+c.blocks-1)
       - greatest(f.block_id, c.block#) + 1 blocks_corrupted
     , 'Free Block' description
  FROM dba_free_space f, v$database_block_corruption c
 WHERE f.file_id = c.file#
   AND f.block_id <= c.block# + c.blocks - 1
   AND f.block_id + f.blocks - 1 >= c.block#
order by file#, corr_start_block#;