Sunday, October 20, 2013

How to disable flashback archiver process, introduced to support Oracle 11gR1 feature "Flashback Data Archive"

If you do not use the flashback data archive feature, and have no plans to do so, you might as well disable the process, even though it is defined as "lightweight".

First, confirm that the operating system process is running:

$ ps -ef | grep FBDA
oracle 18199 8264 0 13:22:12 pts/5 0:00 grep FBDA

--> The background proceess FBDA is running in the background

Check the setting
sqlplus / as sysdba:
select a.ksppinm  "Parameter", b.ksppstvl "Session Value", c.ksppstvl "Instance Value"
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx and a.indx = c.indx
and substr(ksppinm,1,1)='_'
and ksppinm like '%archiver%'
order by a.ksppinm;


Parameter                            Session Value  Instance Value
----------------------------------- --------------- --------------
_disable_flashback_archiver         0                0
_flashback_archiver_partition_size  0                0
by setting the parameter _disable_flashback_archiver and restarting your instance, you disable the flashback archiver process:

alter system set "_disable_flashback_archiver"=1 scope=spfile;

Saturday, October 19, 2013

How to instruct Oracle to use the flash recovery area as archive log destination


Find out what the current setting is:

sqlplus / as sysdba
SQL> show parameter db_recovery
NAME                         TYPE          VALUE
---------------------------- ------------- ------------------------
db_recovery_file_dest         string        /data/oracle/PRODDB/f01
db_recovery_file_dest_size    big integer   500G

show parameter log_archive
NAME                         TYPE             VALUE
--------------------------- -------------- --------------------------
log_archive_dest_1           string        LOCATION=/data/oracle/PRODDB/u01/newarchloc/

Then, switch to the flash recovery area:

alter system set log_archive_dest_1='location=use_db_recovery_file_dest' scope=both;

How to use the dbms_scheduler package to collect intermittent statistics on volatile tables

In the following example I am using the dbms_scheduler package to analyze certain volatile tables every hour:

BEGIN
  SYS.DBMS_SCHEDULER.CREATE_JOB
    (
       job_name        => 'GATHERSTATS'
      ,start_date      => TO_TIMESTAMP_TZ('2009/05/13 12:17:57.508450 +02:00','yyyy/mm/dd hh24:mi:ss.ff tzh:tzm')
      ,repeat_interval => 'FREQ=HOURLY;'
      ,end_date        => NULL
      ,job_class       => 'DEFAULT_JOB_CLASS'
      ,job_type        => 'PLSQL_BLOCK'
      ,job_action      => '
                            begin
                            dbms_stats.gather_table_stats( 
                            ownname=> ''TBR'', 
                            tabname=> ''LOGONS'' , 
                            estimate_percent=> DBMS_STATS.AUTO_SAMPLE_SIZE,  
                            cascade=> DBMS_STATS.AUTO_CASCADE, 
                            degree=> null,  
                            no_invalidate=> DBMS_STATS.AUTO_INVALIDATE, 
                            granularity=> ''AUTO'', 
                            method_opt=> ''FOR ALL COLUMNS SIZE AUTO'');
                            comments=>'your comment here'
END;
/

Oracle 11g enhanced partitioning options

Reference partitioning
======================
allows you to equi-partition related tables in the same database, even if the columns are not present in all the child tables.

Interval partitioning
======================
embodies that highly desirable fire-and-forget power. You define an interval and Oracle takes care of the maintenance, forever.

Extended composite partitioning
===============================
The extension of composite partitioning to range-range, list-range, list-hash, and list-list exposes new possibilities for better partitioning choices and manageability.

Transportable partitions
=========================
Data Pump now allows you to transport and plug-in a single partition, a feature that is guaranteed to be quite useful in archival and retention.

Virtual column partitioning
============================
You can design the best possible partitioning strategy that mimics business flow by partitioning on virtual columns.

System Partitioning
===================
If a table lacks a column that is candidate for partitioning, the table can still be partitioned by using system partitioning,
where oracle will create as many partitions as you like.

The partitions must be explicitly referenced by the developers and users.

So instead of the statement:
insert into sales3 values (1,101,1);
you will have to use:
insert into sales3 partition (p1) values (1,101,1);

Source: Arup Nanda

How to perform an online reorganization of a table - step by step



First, check that your user is eligeble for usage of the DBMS_REDEFINITION package. It requires generous privileges.

Step 1: determine if the table can be reorganized:

whenever sqlerror exit
accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept move_method prompt 'Move method (cons_use_pk or cons_use_rowid): '

set serveroutput on
EXEC DBMS_REDEFINITION.can_redef_table('&&owner','&&table_name',dbms_redefinition.&&move_method);
exit

Step 2: Create an interim table with the desirable layout:
If the outcome of step one was positive, you can proceed. You can for example create the interim table partitioned, while the original table is a normal table without partitions.

Important:
If you copy/paste DDL from SQL Developer, TOAD or similar tools, and use this as a template for your interim table, make sure *all* columns allow NULL values.
Otherwise, you will receive errors when running the COPY_TABLE_DEPENDENTS procedure in step 4

Step 3: start the redefinition:

set serveroutput on
set feedback off
set verify   off
accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept interim_table_name prompt 'Interim table name: '
accept move_method prompt 'Move method (cons_use_pk or cons_use_rowid): '

whenever sqlerror exit
set feedback off
set verify off
begin
DBMS_REDEFINITION.start_redef_table(uname=>'&&owner', 
orig_table=>'&&table_name', 
int_table=>'&&interim_table_name',
col_mapping=>NULL,
options_flag=>dbms_redefinition.&&move_method);
end;
/
exit
Step 4: Copy the dependent object to the interim table

If you want the indexes from the original table to be copied over along with triggers, constraints etc, use the directive
copy_indexes=>dbms_redefinition.cons_orig_params

If you prefer creating the indexes manuall after you have finished the redefinition, use
copy_indexes=>0

whenever sqlerror exit
set serveroutput on
set feedback off
set verify   off

accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept interim_table prompt 'Interim table name: '

DECLARE
l_num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(uname=>'&&owner',
orig_table=>'&&table_name', 
int_table=>'&&interim_table',
-- copy_indexes=>dbms_redefinition.cons_orig_params,
copy_indexes=>0,
copy_triggers=>TRUE,
copy_constraints=>TRUE,
copy_privileges=>TRUE,
ignore_errors=>FALSE,
num_errors => l_num_errors,
copy_statistics=>TRUE,
copy_mvlog=>TRUE);
DBMS_OUTPUT.put_line('l_num_errors=' || l_num_errors);
END;
/
exit

Step 5: synchronize the interim table with potential intermittent transactions:

whenever sqlerror exit
set serveroutput on
set feedback off
set verify   off
accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept interim_table prompt 'Interim table name: '
begin
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(uname=>'&&owner',orig_table=>'&&table_name',int_table=>'&&interim_table');
end;
/
exit

Step 6: finish the redefinition:

whenever sqlerror exit
set serveroutput on
set feedback off
set verify   off
accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept interim_table prompt 'Interim table name: '
begin
DBMS_REDEFINITION.FINISH_REDEF_TABLE(uname=>'&&owner',
orig_table=>'&&table_name', 
int_table=>'&&interim_table');
end;
/
exit

At any time before the execution of FINISH_REDEF_TABLE, you can chose to abort the procedure by calling the dbms_redefinition.abort_redef_table procedure:

whenever sqlerror exit
accept table_name prompt 'Table name: '
accept owner prompt 'Table owner: '
accept interim_table prompt 'Interim table name: '
set serverout on
exec dbms_redefinition.abort_redef_table(uname=>'&&owner',orig_table=>'&&table_name',int_table=>'&&interim_table');
exit
Tip: when you create your interim table, give it a short name, like MYTABLE.
I have had cases where longer names, even though they are below the 30 character limit, will create trouble during the execution of the DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS procedure.

Errors during the redefinition can be seen from the DBA_REDEFINITION_ERRORS view:
SET LONG 2000
SET LINES 300
COL OBJECT_TYPE FORMAT A20
COL OBJECT_OWNER FORMAT A10
COL OBJECT_NAME FORMAT A20
COL BASE_TABLE_NAME FORMAT A20
COL DDL_TXT FORMAT A50
COL ERR_TXT FORMAT A100
 

SELECT OBJECT_TYPE, OBJECT_OWNER, OBJECT_NAME,BASE_TABLE_NAME,DDL_TXT, ERR_TXT   
FROM DBA_REDEFINITION_ERRORS;

Some useful session views - short description

V$SESSION --> displays information about the current session

V$SESSION_EVENT --> shows all the wait events waited for by the session. Note that it will show the data only if the session is still active in the database

V$SESSTAT --> shows the resource usage for a session
Some useful statistics visible in the V$SESSTAT view:
- physical reads: the number of database blocks retrieved from disk
- db block changes: the number of database blocks changed in the session
- bytes sent via SQL*Net to client: the bytes received from the client over the network, which is used to determine the data traffic from the client

V$ACTIVE_SESSION_HISTORY --> shows historical session information

DBA_HIST_ACTIVE_SESS_HISTORY --> contains the same data as V$ACTIVE_SESSION_HISTORY, but with less granularity, only every 10th second sampling

How to use sqlerrm to reveal the meaning of audit information


As an example, the audit information may look like the following:

ALTER SESSION SET NLS_DATE_FORMAT='DD.MM.YYYY HH24:MI:SS';

SELECT
 os_username,
 userhost,
 timestamp,
 returncode
FROM  dba_audit_session
WHERE action_name = 'LOGON'
AND   returncode > 0
AND   trunc(timestamp) = to_date('08.07.2013', 'DD.MM.YYYY')
AND   username = 'TSF'
ORDER BY timestamp DESC;

Result:
OS_USERNAME USERHOST       TIMESTAMP            RETURNCODE
----------- -----------    -------------------  ---------- 
billyb      CHM06071130    08.07.2013 12:24:07  1017  
billyb      CHM06071130    08.07.2013 10:06:06  28000  
You can use the sqlerrm keyword to print the meaning of a return code, like this:

exec dbms_output.put_line(sqlerrm(-1017)) ;
exec dbms_output.put_line(sqlerrm(-28000)) ;
These commands will yield:

ORA-01017: invalid username/password; logon denied
ORA-28000: the account is locked