Thursday, 27 March 2014

Duplicating with rman

The assumption is to create a copy of the database on the same host in order to run 2 independent database instances. It can be done in many ways:

  • with RMAN 
  • with expdp and standard dump
  • with expdp and transportable tablespaces
  • with cp command and dbnewid tool - look here
I present here one of the possible ways with the RMAN utility:
  1. check if the database is set in ARCHIVELOG
    select log_mode from v$database;
    -- if the answer is NOARCHIVELOG then
    shutdown immediate; 
    startup mount
    alter database archivelog;
    alter database open;
    
  2. prepare auxiliary instance
    • create directories for the clone database
      Here I am not sure entirely at the moment how it works. I provided explicite in the parameter file the value for the control_files and am quite certain that have to create the directory myself. In case of datafiles and redologs, if one first sets new names to new, then the RMAN creates directories according to the OMF methodology.
      mkdir -p /oracle/oradata/NEWSID/controlfile
      mkdir -p /oracle/oradata/NEWSID/datafile #optional
      mkdir -p /oracle/oradata/NEWSID/onlinelog #optional
      
    • create spfile for the clone database (if this is not a standby then the only requirement is DB_NAME)
      export ORACLE_SID=NEWSID
      sqlplus / as sysdba
      
      All the OMF settings indicate the same location - it does not make sense to set both db_create_online_log_dest_1 and db_create_online_log_dest_2 to the same value unless one works on some kind of enterprise class storage.
      create pfile='NEWSID.pfile' from spfile;
      
      *.audit_file_dest='/home/oracle/admin/NEWSID/adump'
      *.compatible='11.2.0.3.0'
      *.control_files='/oracle/oradata/NEWSID/controlfile/control01.ctl'
      *.db_block_size=8192
      *.db_create_file_dest='/oracle/oradata/'
      *.db_create_online_log_dest_1='/oracle/oradata/' 
      *.db_create_online_log_dest_2='/oracle/oradata/'
      *.db_domain=example.com
      *.db_file_multiblock_read_count=16
      *.db_files=800
      *.db_name=NEWSID
      *.diagnostic_dest='/oracle'
      *.job_queue_processes=1000
      *.nls_language='POLISH'
      *.nls_territory='POLAND'
      *.open_cursors=300
      *.pga_aggregate_target=512M
      *.processes=1000
      *.remote_login_passwordfile='EXCLUSIVE'
      *.service_names='NEWSID'
      *.sessions=1105
      *.sga_target=800M
      *.undo_management='AUTO'
      *.undo_tablespace='UNDOTBS1'
      
      create spfile from pfile='NEWSID.pfile';
      
    • copy password file
      cp orapwOLDSID orapwNEWSID
    • add static definition of the clone database to listener.ora
      # static definitions
      SID_LIST_LISTENER =
        (SID_LIST =
          ## this part is not necessary
          (SID_DESC =
            (GLOBAL_DBNAME = OLDSID.dev.example.com)
            (ORACLE_HOME = /oracle/product/11.2.0.2)
            (SID_NAME = OLDSID)
          )
          ## this part is mandatory
          (SID_DESC =
            (GLOBAL_DBNAME = NEWSID.dev.example.com)
            (ORACLE_HOME = /oracle/product/11.2.0.2)
            (SID_NAME = NEWSID)
          )
        )
      
      # listener definition prepared for dynamic registration
      LISTENER=
        (DESCRIPTION=
            (ADDRESS=(PROTOCOL=tcp)(HOST=test-dbcluster-01)(PORT=1521)))
      
      
      After such changes in the listener definition it is not enough simply reload. One have to stop and start the listener.
    • run the clone instance
      startup mount
  3. run the duplicate command in RMAN
    connect target sys/sys01@OLDSID.example.com
    connect auxiliary sys/sys01@NEWSID.example.com
    run {
      ## this setting sets all the files to indicated directory
      ## and changes file names to %U format
      #SET NEWNAME FOR DATABASE TO '/oracle/oradata/%U';
      ## this setting is compatible with the OMF
      SET NEWNAME FOR DATABASE TO NEW; 
      DUPLICATE TARGET DATABASE to transpl
      FROM ACTIVE DATABASE;
    }
    

Tuesday, 28 January 2014

The pagination techniques with the Oracle RDBMS (external link)

Quite extensive overview of pagination techniques. And here an article from J. Lewis on the same subject.

ITL waits (external link)

A short and concise article on ITL waits in various versions of the Oracle RDBMS.

Tuesday, 14 January 2014

Parrallel execution (external link)

Understanding Parallel Execution - parts 1 and 2

LONG columns and scripts

There are many ways to read a LONG column -  in general one have to use the PL/SQL code. The summary of those ways is provided here (http://www.oracle-developer.net/display.php?id=430). 
I focused only on one of those methods i.e. the one leveraging the XML processing features of the Oracle RDBMS. The main reason here is the convenience while trying to produce a kind of administration script (which a basic task is usually to generate another script, which in turn makes the final effect). Here an example - the script, which produces the script, which may recreate constraints from a chosen schema:
set pages 0 lin 300 trimspool on trimout on
define CONDITIONS='OWNER=''VPD_BPSS'''

-- check
SELECT 'alter table '
  || xs.owner
  ||'.'
  || xs.table_name
  ||' add constraint '
  || xs.constraint_name
  ||' '
  || ' check ('
  || xs.search_condition
  ||')'
  ||
  CASE xs.status
    WHEN 'ENABLED'
    THEN ' enable '
    WHEN 'DISABLED '
    THEN ' disable '
  END
  || ';' SQL1
FROM XMLTABLE('/ROWSET/ROW' PASSING
  (SELECT dbms_xmlgen.getxmltype(
    q'[SELECT * FROM dba_constraints c WHERE c.constraint_type in ('C') and &&CO
NDITIONS]' )
  FROM dual
  ) COLUMNS
  owner VARCHAR2(32) PATH 'OWNER',
  constraint_name VARCHAR2(32) path 'CONSTRAINT_NAME',
  constraint_type VARCHAR2(1) path 'CONSTRAINT_TYPE',
  table_name VARCHAR2(30) path 'TABLE_NAME',
  search_condition VARCHAR2(4000) path 'SEARCH_CONDITION',
  status VARCHAR2(30) path 'STATUS' ) xs
UNION ALL
-- pk and uniq
SELECT 'alter table '
  ||c.owner
  ||'.'
  ||c.table_name
  ||' add constraint '
  ||c.constraint_name
  ||
  CASE c.constraint_type
    WHEN 'P'
    THEN ' primary key'
    WHEN 'U'
    THEN ' unique'
  END
  || ' ('
  ||
  (SELECT LISTAGG(i.column_name, ',') WITHIN GROUP (
  ORDER BY i.position)
  FROM dba_cons_columns i
  WHERE c.owner         = i.owner
  AND c.constraint_name = i.constraint_name
  )
  ||') using index '
  ||c.index_owner
  ||'.'
  ||c.index_name
  ||' '
  || c.deferrable
  ||' '
  || c.deferred
  ||' '
  ||';' DDL1
FROM DBA_CONSTRAINTS C
WHERE c.constraint_type IN ('P','U')
AND
  &&CONDITIONS
UNION ALL
-- fk
SELECT 'alter table '
  ||c.owner
  ||'.'
  ||c.table_name
  ||' add constraint '
  ||c.constraint_name
  ||' foreign key('
  ||
  (SELECT LISTAGG(f.column_name, ',') WITHIN GROUP (
  ORDER BY f.position)
  FROM dba_cons_columns f
  WHERE c.owner        =f.owner
  AND c.constraint_name=f.constraint_name
  )
  ||') '
  ||' references '
  ||
  (SELECT p.owner
    ||'.'
    ||p.table_name
    ||'('
    || LISTAGG(p.column_name, ',') WITHIN GROUP (
  ORDER BY p.position)
    || ')'
  FROM dba_cons_columns p
  WHERE c.r_OWNER        =p.owner
  AND c.r_constraint_name = p.constraint_name
  GROUP BY p.owner,
    p.table_name
  )
  ||' '
  ||
  CASE
    WHEN c.delete_rule IS NOT NULL
    AND c.delete_rule!  ='NO ACTION'
    THEN 'ON DELETE '
      || c.delete_rule
      ||' '
  END
  || c.deferrable
  ||' '
  || c.deferred
  ||' '
  ||
  CASE status
    WHEN 'ENABLED'
    THEN 'ENABLE novalidate '
    WHEN 'DISABLED '
    THEN 'DISABLE '
  END
  ||';' ddl1
FROM DBA_CONSTRAINTS C
WHERE C.CONSTRAINT_TYPE IN ('R')
AND
  &&CONDITIONS ;

Friday, 20 December 2013

My own commandline FU

Shell

# changes the ownership for a particular user
# I use it mainly in cases the uid/gid differs between machines while it was intended
# to be the same 

find /oracle -uid 500 -exec chown oracle {} \;
find /oracle -gid 500 -exec chgrp oracle {} \;

Thursday, 19 December 2013

OT: Commandline Fu (external link)

This is not exactly bound with the Oracle RDBMS, but I am impressed by cleverness and flexibility of those oneliners - http://www.commandlinefu.com/commands/browse