Feeds:
Posts
Comments

Tingkat: Pemula
DB Version: 10.2.0.1 above

Database yang sudah ter-create dapat kita clone menggunakan DBCA. Hasil clone ini akan disimpan sebagai template.

Pertama, jalankan dbca:

dbca-001.jpg

Klik tombol Next, maka kita masuk ke step 1. Pastikan Manage Templates terpilih. Kemudian klik tombol Next:

blog-0002.jpg

Pada step 2, Pilih Create a database template dan From an existing database (structure as well as data), kemudian klik tombol Next:

blog-0003.jpg

Pada step 3, Pilih Database instance yang ingin kita clone, kemudian klik tombol Next:

blog-00041.jpg

Tentukan Nama template pada bagian Name, kemudian tentukan pula dimana kita akan menyimpannya, isi dibagian Template datafile, setelah itu klik tombol Next:

blog-0005.jpg

Step 5 akan ada pilihan, apakah lokasi file yang ada sekarang akan kita simpan atau akan menggunakan lokasi file standar dari oracle. Terakhir klik tombol Finish:

blog-00061.jpg

Klik tombol OK untuk memulai proses clone:

blog-0007.jpg

Tampak pada gambar proses clone sedang berjalan:

blog-0008.jpg

Proses clone selesai:

blog-0009.jpg

In this Document


This document is being delivered to you via Oracle Support’s Rapid Visibility (RaV) Rapid Visibility (RaV) process, and therefore has not been subject to an independent technical review.

Applies to:

Oracle Warehouse Builder – Version: 11.1
Information in this document applies to any platform.

Goal

How to start the Warehouse Builder Repository Listener ?

Solution

With Warehouse Builder 11g, the “Start and Stop OWB Browser Listener” were removed from the Windows Program Groups.
  1. To start the Warehouse Builder Browser Listener:
    1. Open a Command-box.
    2. Navigate to owb_homeowbbinwin32 (/owb_home/owb/bin/unix for Unix ).
    3. Run the startOwbbInst.bat (startOwbbInst.sh for Unix)
      The first time you invoke this listener, select and re-confirm a password for an oc4jadmin account
      D:Oracleowb11owbbinwin32>startOwbbInst.batD:Oracleowb11owbbinwin32>call setowbenv.bat
      2007-12-03 10:21:30.230 NOTIFICATION Auto-unpacking D:Oracleowb11owbj2eeowbb.war…
      2007-12-03 10:21:30.360 NOTIFICATION Unjar D:Oracleowb11owbj2eeowbb.war in D:Oracleowb11owbj2eeowbb
      2007-12-03 10:21:43.439 NOTIFICATION Finished auto-unpacking D:Oracleowb11owbj2eeowbb.war
      03-dec.-2007 10:21:43 com.evermind.server.XMLApplicationServerConfig randomizeJtaAdminPassword
      INFO: Updating JtaAdmin account
      07/12/03 10:21:44 Set OC4J administrator’s password (password text will not be displayed as it is entered)
      Enter password:
      Confirm password:
      The password for OC4J administrator “oc4jadmin” has been set.
      07/12/03 10:22:19 The OC4J administrator “oc4jadmin” account is activated.
      07/12/03 10:22:30 Oracle Containers for J2EE 10g (10.1.3.0.0) initialized

      Subsequent start will look like this :

      D:Oracleowb11owbbinwin32>startOwbbInst.batD:Oracleowb11owbbinwin32>call setowbenv.bat
      07/12/03 10:31:35 Oracle Containers for J2EE 10g (10.1.3.0.0) initialized
    4. The Command-box will remain open until the Warehouse Builder Browser Listener is stopped.
  2. To stop the Warehouse Builder Browser Listener:
    1. Open a Command-box.
    2. Navigate to owb_homeowbbinwin32 (/owb_home/owb/bin/unix for Unix ).
    3. Run stopOwbbInst.bat (stopOwbbInst.sh for Unix)
      Each time you stop this listener, the password has to match what was supplied in the first start.
      D:Oracleowb11owbbinwin32>stopOwbbInst.batD:Oracleowb11owbbinwin32>call setowbenv.bat
      Enter password:
      D:Oracleowb11owbbinwin32>

Additional steps are described in the Warehouse Builder Installation and Administration Guide 11g Release 1 (11.1) : Chapter 1 Installation Overview and Requirements – Launching Warehouse Builder Components – page 1-19 .

Measuring Disk I/O

James Koopmann, jkoopmann@pinehorse.com

Introduction

Do you know how your disk subsystem is actually performing? This article looks at extracting various I/O statistics so that you can monitor and determine just how well your disks are doing.

How can I separate Oracle I/O to maximize performance?

Should I separate data files from index files?

Should I separate redo logs

These question(s), AND many more, seem to flood our minds as database administrators. They are easy to answer with generalities but in practice can be very difficult to come to a conclusion on unless we look at how our disk subsystem is actually performing.

Many of us might stop reading this article right now, saying to ourselves that these questions and level of detail is only available to our system administrators or those that control the disk farm. All too often, I have seen two different methodologies when configuring Oracle on storage. The first is to use Oracle’s Flexible Architecture (OFA) approach where architects will separate Oracle object types (data, index, redo, archive, etc.) across a storage array. The second approach is to architect a JBOD (Just a Bunch Of Disks) configuration and throw everything on it. Both of these approaches lack the planning and configuration that ultimately produces a well-tuned database system. They are just taking a shot in the dark, hoping everything is going to work well because they followed a predefined methodology. Well, methodologies may not work in your case. Don’t look to your system administrators as they might not even know how to extract information themselves, and when they do it is usually at a higher level since they too can not relate the information to the Oracle stack.

So the DBA must begin to understand the application from a purely I/O perspective, relay that information to the Storage Administrator and then, together, develop a plan for configuring or altering a storage subsystem that will be able to service the application mix. For the storage, a key performance indicator of an OLTP environment is based on I/Os per second (IOPS) and latencies (I/O turn-around time). OLAP databases are your data warehouses or reporting systems and are categorized by moving large amounts of data that is mostly read only. For the storage array, the performance of an OLAP environment is based on Mega-bytes per second (MBPS). A database workload is often descriptive of its application mix. Understanding and translating an application mix into a database workload is critical for optimizing a storage system. The workload of an OLTP database is categorized by small random I/O while OLAP is categorized by large sequential or random I/O.

For the database administrator it is now time to get dirty and look at the internals of your database. Somewhere and somehow, you must extract some form of statistics that allow you to categorize the type of SQL and I/O requests at the database level. Oracle for instance has quite a few internal tables that allow for the interrogation of this information. For instance we can query the gv$sysstat view for (‘physical read total IO requests’ – ‘physical read total multi block requests’) to get the number of small reads in the system. Do this over a period of time, subtract the beginning value from the ending value and you quickly get IOPS for small reads over that period. This MUST be done for each statistic available to get a view of total IOPS and MBPS being requested by your particular database. These are the pertinent statistics you will need to extract. Basically, large reads and writes are used to calculate MBPS and small reads and writes are used for IOPS calculations.

gv$sysstat (name, value) 

Total Reads :'physical read total IO requests'
Total Writes:'physical write total IO requests' 

Large Reads :'physical read total multi block requests'
Large Writes:'physical write total multi block requests' 

Total Bytes Read    :'physical read total bytes'
Total Bytes Written :'physical write total bytes' 

To calculate small reads:
Small Reads  = Total Reads - Large Reads
Small Writes = Total Writes - Large Writes

Coming up with these numbers allows us to make intelligent decisions in regards to our current database performance and storage requirements. Granted, the database may be experiencing contention and actual I/O requests may be lower then optimal so tuning may be in order. Regardless, it is the DBAs responsibility to take these IOPS and MBPS to the Storage Administrator, evaluate if the storage solution is being taxed, and if a reconfiguration is required. These reconfigurations may require moving data files around to use more disks, adding more disks for higher throughput, or reducing IOPS and MBPS through the application. Well, we have come full circle to the application again. I know you know what to do.

Below are two scripts that will get you started. I have spent quite a bit of time getting them easy to use and giving you the information quickly to understand how your disk subsystem is performing over time.

set echo     off
set feedback off
set heading  off
set linesize 40
set pagesize 55
set verify   off 

set termout off
column rpt new_value rpt
select instance_name||'_'||to_char(sysdate,'YYYYMMDDHH24MISS')||'_vsysstat_ioworkload.LST' rpt from v$instance;
set termout on
prompt
prompt
prompt ^^^^^^^^^^^^^
prompt Report Name : ../LST/&&rpt
prompt ^^^^^^^^^^^^^
spool ../LST/&&rpt 

column sr1  new_value sr1
column sw1  new_value sw1
column lr1  new_value lr1
column lw1  new_value lw1
column tbr1 new_value tbr1
column tbw1 new_value tbw1
set termout off
SELECT
sum(decode(name,'physical read total IO requests',value,0)- decode(name,'physical read total multi block requests',value,0)) sr1,
sum(decode(name,'physical write total IO requests',value,0)- decode(name,'physical write total multi block requests',value,0)) sw1,
sum(decode(name,'physical read total multi block requests',value,0)) lr1,
sum(decode(name,'physical write total multi block requests',value,0)) lw1,
sum(decode(name,'physical read total bytes',value,0)) tbr1,
sum(decode(name,'physical write total bytes',value,0)) tbw1
FROM v$sysstat;
set termout on 

prompt
prompt
prompt ^^^^^^^^^^^^
prompt First Sample
prompt ^^^^^^^^^^^^
prompt Number of Small Reads : &&sr1
prompt Number of Small Writes: &&sw1
prompt Number of Large Reads : &&lr1
prompt Number of Large Writes: &&lw1
prompt Total Bytes Read      : &&tbr1
prompt Total Bytes Written   : &&tbw1
prompt
prompt
prompt Enter the amount of time (in seconds) you would like this process to sleep for sampling data
prompt ^^^^^^^^^^^^^^^^^^
prompt Sleep Time (secs): &&sleeptime
prompt ^^^^^^^^^^^^^^^^^^
exec DBMS_LOCK.SLEEP (&&sleeptime); 

column sr2  new_value sr2
column sw2  new_value sw2
column lr2  new_value lr2
column lw2  new_value lw2
column tbr2 new_value tbr2
column tbw2 new_value tbw2
set termout off
SELECT
sum(decode(name,'physical read total IO requests',value,0)- decode(name,'physical read total multi block requests',value,0)) sr2,
sum(decode(name,'physical write total IO requests',value,0)- decode(name,'physical write total multi block requests',value,0)) sw2,
sum(decode(name,'physical read total multi block requests',value,0)) lr2,
sum(decode(name,'physical write total multi block requests',value,0)) lw2,
sum(decode(name,'physical read total bytes',value,0)) tbr2,
sum(decode(name,'physical write total bytes',value,0)) tbw2
FROM v$sysstat;
set termout on 

prompt
prompt
prompt ^^^^^^^^^^^^^
prompt Second Sample
prompt ^^^^^^^^^^^^^
prompt Number of Small Reads : &&sr2
prompt Number of Small Writes: &&sw2
prompt Number of Large Reads : &&lr2
prompt Number of Large Writes: &&lw2
prompt Total Bytes Read      : &&tbr2
prompt Total Bytes Written   : &&tbw2
prompt
prompt
prompt ^^^^^^^^^
prompt Results :
prompt ^^^^^^^^^ 

column sri new_value sri
column swi new_value swi
column tsi new_value tsi
column srp new_value srp
column swp new_value swp
column lri new_value lri
column lwi new_value lwi
column tli new_value tli
column lrp new_value lrp
column lwp new_value lwp
column tr  new_value tr
column tw  new_value tw
column tm  new_value tm
SELECT
ROUND((&&sr2-&&sr1)/&&sleeptime,3) sri,
ROUND((&&sw2-&&sw1)/&&sleeptime,3) swi,
ROUND(((&&sr2-&&sr1)+(&&sw2-&&sw1))/&&sleeptime,3) tsi,
ROUND((&&sr2-&&sr1)/DECODE(((&&sr2-&&sr1)+(&&sw2-&&sw1)),0,1,((&&sr2-&&sr1)+(&&sw2-&&sw1)))*100,3) srp,
ROUND((&&sw2-&&sw1)/DECODE(((&&sr2-&&sr1)+(&&sw2-&&sw1)),0,1,((&&sr2-&&sr1)+(&&sw2-&&sw1)))*100,3) swp,
ROUND((&&lr2-&&lr1)/&&sleeptime,3) lri,
ROUND((&&lw2-&&lw1)/&&sleeptime,3) lwi,
ROUND(((&&lr2-&&lr1)+(&&lw2-&&lw1))/&&sleeptime,3) tli,
ROUND((&&lr2-&&lr1)/DECODE(((&&lr2-&&lr1)+(&&lw2-&&lw1)),0,1,((&&lr2-&&lr1)+(&&lw2-&&lw1)))*100,3) lrp,
ROUND((&&lw2-&&lw1)/DECODE(((&&lr2-&&lr1)+(&&lw2-&&lw1)),0,1,((&&lr2-&&lr1)+(&&lw2-&&lw1)))*100,3) lwp,
ROUND(((&&tbr2-&&tbr1)/&&sleeptime)/1048576,3) tr,
ROUND(((&&tbw2-&&tbw1)/&&sleeptime)/1048576,3) tw,
ROUND((((&&tbr2-&&tbr1)+(&&tbw2-&&tbw1))/&&sleeptime)/1048576,3) tm
FROM dual; 

SELECT
'Small Read  IOPS  = '||ROUND((&&sr2-&&sr1)/&&sleeptime,3)||' IOPS',
'Small Write IOPS  = '||ROUND((&&sw2-&&sw1)/&&sleeptime,3)||' IOPS',
'Total Small IOPS  = '||ROUND(((&&sr2-&&sr1)+(&&sw2-&&sw1))/&&sleeptime,3)||' IOPS',
'Small Read  I/O % = '||ROUND((&&sr2-&&sr1)/DECODE(((&&sr2-&&sr1)+(&&sw2-&&sw1)),0,1,((&&sr2-&&sr1)+(&&sw2-&&sw1)))*100,3)||' %',
'Small Write I/O % = '||ROUND((&&sw2-&&sw1)/DECODE(((&&sr2-&&sr1)+(&&sw2-&&sw1)),0,1,((&&sr2-&&sr1)+(&&sw2-&&sw1)))*100,3)||' %',
'Large Read  IOPS  = '||ROUND((&&lr2-&&lr1)/&&sleeptime,3)||' IOPS',
'Large Write IOPS  = '||ROUND((&&lw2-&&lw1)/&&sleeptime,3)||' IOPS',
'Total Large IOPS  = '||ROUND(((&&lr2-&&lr1)+(&&lw2-&&lw1))/&&sleeptime,3)||' IOPS',
'Large Read  I/O % = '||ROUND((&&lr2-&&lr1)/DECODE(((&&lr2-&&lr1)+(&&lw2-&&lw1)),0,1,((&&lr2-&&lr1)+(&&lw2-&&lw1)))*100,3)||' %',
'Large Write I/O % = '||ROUND((&&lw2-&&lw1)/DECODE(((&&lr2-&&lr1)+(&&lw2-&&lw1)),0,1,((&&lr2-&&lr1)+(&&lw2-&&lw1)))*100,3)||' %',
'Total Read        = '||ROUND(((&&tbr2-&&tbr1)/&&sleeptime)/1048576,3)||' MBPS',
'Total Written     = '||ROUND(((&&tbw2-&&tbw1)/&&sleeptime)/1048576,3)||' MBPS',
'Total MBPS        = '||ROUND((((&&tbr2-&&tbr1)+(&&tbw2-&&tbw1))/&&sleeptime)/1048576,3)||' MBPS'
FROM dual
; 

prompt Small Read  IOPS  = &&sri IOPS
prompt Small Write IOPS  = &&swi IOPS
prompt Total Small IOPS  = &&tsi IOPS
prompt Small Read  I/O % = &&srp %
prompt Small Write I/O % = &&swp %
prompt Large Read  IOPS  = &&lri IOPS
prompt Large Write IOPS  = &&lwi IOPS
prompt Total Large IOPS  = &&tli IOPS
prompt Large Read  I/O % = &&lrp %
prompt Large Write I/O % = &&lwp %
prompt Total Read        = &&tr MBPS
prompt Total Written     = &&tw MBPS
prompt Total MBPS        = &&tm MBPS 

spool off
undefine sleeptime

Get a complete history of IOPS & MBPS from workload repository history and graph it for you management. This allows you to see total database disk activity. Compare this against what your disk capacity is. Just remember these numbers are for ALL disks. You can get average IOPS/MBPS by dividing by your total number of disks used in servicing database requests. This is great information and once you graph the results you will really see how your I/O, and application performance, might be suffering during the day or at least determine where peak periods are.

set echo     off
set feedback off
set linesize 300
set pagesize 55
set verify   off 

set termout off
column rpt new_value rpt
select instance_name||'_wrh_sysstat_ioworkload_'||'.LST' rpt from v$instance;
set termout on
prompt
prompt
prompt ^^^^^^^^^^^^^
prompt Report Name : ../LST/&&rpt
prompt ^^^^^^^^^^^^^
spool ../LST/&&rpt 

column sri head "Small|Read|IOPS"
column swi head "Small|Write|IOPS"
column tsi head "Total|Small|IOPS"
column srp head "Small|Read|I/O%"
column swp head "Small|Write|I/O%"
column lri head "Large|Read|IOPS"
column lwi head "Large|Write|IOPS"
column tli head "Total|Large|IOPS"
column lrp head "Large|Read|I/O%"
column lwp head "Large|Write|I/O%"
column tr  head "Total|Read|MBPS"
column tw  head "Total|Written|MBPS"
column tm  head "Total|MBPS"
column begin_time for a25
column end_time for a25 

SELECT end_time,
       ROUND(sr/inttime,3) sri,
       ROUND(sw/inttime,3) swi,
       ROUND((sr+sw)/inttime,3) tsi,
       ROUND(sr/DECODE((sr+sw),0,1,(sr+sw))*100,3) srp,
       ROUND(sw/DECODE((sr+sw),0,1,(sr+sw))*100,3) swp,
       ROUND(lr/inttime,3) lri,
       ROUND(lw/inttime,3) lwi,
       ROUND((lr+lw)/inttime,3) tli,
       ROUND(lr/DECODE((lr+lw),0,1,(lr+lw))*100,3) lrp,
       ROUND(lw/DECODE((lr+lw),0,1,(lr+lw))*100,3) lwp,
       ROUND((tbr/inttime)/1048576,3) tr,
       ROUND((tbw/inttime)/1048576,3) tw,
       ROUND(((tbr+tbw)/inttime)/1048576,3) tm
 FROM (
SELECT beg.snap_id beg_id, end.snap_id end_id,
       beg.begin_interval_time, beg.end_interval_time,
       end.begin_interval_time begin_time, end.end_interval_time end_time,
       (extract(day    from (end.end_interval_time - end.begin_interval_time))*86400)+
       (extract(hour   from (end.end_interval_time - end.begin_interval_time))*3600)+
       (extract(minute from (end.end_interval_time - end.begin_interval_time))*60)+
       (extract(second from (end.end_interval_time - end.begin_interval_time))*01) inttime,
       decode(end.startup_time,end.begin_interval_time,end.sr,(end.sr-beg.sr))    sr,
       decode(end.startup_time,end.begin_interval_time,end.sw,(end.sw-beg.sw))    sw,
       decode(end.startup_time,end.begin_interval_time,end.lr,(end.lr-beg.lr))    lr,
       decode(end.startup_time,end.begin_interval_time,end.lw,(end.lw-beg.lw))    lw,
       decode(end.startup_time,end.begin_interval_time,end.tbr,(end.tbr-beg.tbr)) tbr,
       decode(end.startup_time,end.begin_interval_time,end.tbw,(end.tbw-beg.tbw)) tbw
  FROM
(SELECT dba_hist_snapshot.snap_id, startup_time, begin_interval_time, end_interval_time,
 sum(decode(stat_name,'physical read total IO requests',value,0)-
 	decode(stat_name,'physical read total multi block requests',value,0)) sr,
 sum(decode(stat_name,'physical write total IO requests',value,0)-
 	decode(stat_name,'physical write total multi block requests',value,0)) sw,
 sum(decode(stat_name,'physical read total multi block requests',value,0)) lr,
 sum(decode(stat_name,'physical write total multi block requests',value,0)) lw,
 sum(decode(stat_name,'physical read total bytes',value,0)) tbr,
 sum(decode(stat_name,'physical write total bytes',value,0)) tbw
   FROM wrh$_sysstat, wrh$_stat_name, dba_hist_snapshot
  WHERE wrh$_sysstat.stat_id = wrh$_stat_name.stat_id
    AND wrh$_sysstat.snap_id = dba_hist_snapshot.snap_id
  group by dba_hist_snapshot.snap_id, startup_time, begin_interval_time, end_interval_time) beg,
(SELECT dba_hist_snapshot.snap_id, startup_time, begin_interval_time, end_interval_time,
 sum(decode(stat_name,'physical read total IO requests',value,0)-
 	decode(stat_name,'physical read total multi block requests',value,0)) sr,
 sum(decode(stat_name,'physical write total IO requests',value,0)-
 	decode(stat_name,'physical write total multi block requests',value,0)) sw,
 sum(decode(stat_name,'physical read total multi block requests',value,0)) lr,
 sum(decode(stat_name,'physical write total multi block requests',value,0)) lw,
 sum(decode(stat_name,'physical read total bytes',value,0)) tbr,
 sum(decode(stat_name,'physical write total bytes',value,0)) tbw
   FROM wrh$_sysstat, wrh$_stat_name, dba_hist_snapshot
  WHERE wrh$_sysstat.stat_id = wrh$_stat_name.stat_id
    AND wrh$_sysstat.snap_id = dba_hist_snapshot.snap_id
  group by dba_hist_snapshot.snap_id, startup_time, begin_interval_time, end_interval_time) end
 WHERE beg.snap_id + 1 = end.snap_id
)
order by 1
/ 

spool off

Understanding an application from a purely I/O perspective is a key aspect of configuring storage. Oracle has a variety of I/O types that ultimately need to be mapped, sampled, and related to storage. In Oracle’s case, there is I/O generated by server processes on behalf of users, multiple database writers, checkpoint activity, logging facilities that not only write as updates are being done but also the reading from online logs and writing to archive logs by the archive process, plus a few more and some internals that determine size and frequency of the I/Os. Oracle is a very complex system of processes that without understanding your disk I/O patterns is nearly impossible to configure properly.

Author: Burleson

It is very frustrating when you find your database hang. It is even more frustrating when there are no messages in the alert log and still you are unable to connect to the database. We hear complains when one tries to connect to Oracle with Enterprise Manager and it just hangs. Sometimes one is unable to cannot connect via SQL*Plus either. Oracle can hang for many reasons. In this article I will give some effective tips that can help you fix the hung databases.

Logs and Files:

Alert Log:

First of all analyze the alert log for any errors or messages.

Server-side Logs:

In addition to the alert log, you need to check server-side logs as well.

/etc/syslog, /var/adm/syslog

Listener Log:

Check the listener log files.

Trace Files:

Check the bdump, cdump and pfile directories for trace files.

Instance Availability:

You might not see an entry in the alert log if the instance is unavailable due to a crash. You can check that the instance is running and hence available by using below statement.

ps -ef|grep ora|grep pmon

Server Resources:

Databases mostly hang if server resources are over allocated and there is not enough RAM to spawn another connection to Oracle.

External issues:

There are some external issues that can make your database hang. The network being down, Kerberos security issues, SSO or a firewall issue can cause an Oracle connection to hang. You can test this by setting

sqlnet.authentication_services=(none)

in your sqlnet.ora file and then retry connecting.

Listener:

Sometimes Oracle gets hang if listener is not running. Make sure that the listener is running. Check the lsnrctl statistics.

Oracle Hanging:

Oracle sets locks in order to manage concurrent updates and ensure that the database maintains its internal integrity. In some cases Oracle use hanging and no users can connect to the database. In such scenarios you have no choice other than bouncing the instance.

Shared Data:

Mostly the end-user session hangs when a shared data resource held by another end-user is accessed. The information about when Oracle has a session waiting on a resource can be found in the v$session view in the row_wait_file# and row_wait_block#. The file number and block number can then be cross-referenced into the dba_extents view to see the name of the table where the session is waiting on a block.

Column host format a6;
Column username format a10;
Column os_user format a8;
Column program format a30;
Column tsname format a12;

select
b.machine host,
b.username username,
b.server,
b.osuser os_user,
b.program program,
a.tablespace_name ts_name,
row_wait_file# file_nbr,
row_wait_block# block_nbr,
c.owner,
c.segment_name,
c.segment_type
from
dba_data_files a,
v$session b,
dba_extents c
where
b.row_wait_file# = a.file_id
and
c.file_id = row_wait_file#
and
row_wait_block# between c.block_id and c.block_id + c.blocks – 1
and
row_wait_file# <> 0
and
type=’USER’
;

ANALYZE command hanging:

The ANALYZE command may hang if there is not enough space in the Temp Tablespace. Create a big Temporary Tablespace to avoid this problem.

The ANALYZE command may also hang if the table is partitioned and a utility (imp or loader) is inserting rows in the table, and at the same time ANALYZE command starts working on the table. You can fix this problem by analyze be done in night when there is a low DML activities.

Author: Burleson

TNS or Transparent Network Substrate is Oracle’s networking architecture. Oracle typically relies on TNS to provide generic network connectivity to and between Oracle databases. TNS provides a uniform application interface to enable network applications to access the underlying network protocols transparently.

It is very critical for Oracle professional to understand the affect of network configuration on database performance. The network administrator is able to control much of the network performance tuning and hence Oracle administrator has little control over the network settings that can affect overall database performance.

Performance Improvement by Setting Parameters:

The parameters within the sqlnet.ora , tnsnames.ora , and protocol.ora files can be set to improve the performance of distributed transactions. These parameters can be used to change the configuration and size of TCP packets. Adjusting these parameters can have a profound impact on the underlying network transport layer to improve the throughput of all Oracle transactions.

Oracle Net:

Oracle Net is a layer in the OSI model that resides above the network-specific protocol stack. Oracle Net Services provides methods for understanding and resolving network problems through the use of log and trace files. Since Oracle Net does not allow to tune the underlying network layer and therefore majority of network traffic cannot be tuned from within the Oracle environment.

Controlling Packet Frequency and Size:

Oracle provides a number of tools to change packet frequency and size. This enables Oracle database administrators to control the frequency and size of network packets. For example you can change the refresh interval for a snapshot to ship larger amounts at less frequent intervals.

Tuning Oracle Net connections:

Oracle Net connections between servers can be tuned using several parameters however only qualified network administrator should be consulted for tuning the network. The frequency and size of packet shipping across the network can be affected by using settings contained in the following below files. These tuning parameters will affect only the performance of the Oracle Net layer.

File

Parameter

protocol.ora

tcp.nodelay parameter

sqlnet.ora client file

break_poll_skip parameter

sqlnet.ora server file

automatic_ipc parameter

tnsnames.ora and listener.ora

SDU and TDU parameters

 

 

Controlling Buffer Flushing Delays:

The requests are not always sent immediately to their destinations as by default Oracle Net waits until the buffer is filled before transmitting data. This is most common when large amounts of data are streamed from one end to another, and Oracle Net does not transmit the packet until the buffer is full. However this problem can be solved if you add a protocol.ora file and specify a tcp.nodelay to stop buffer flushing delays.

tcp.nodelay parameter:

  • Setting tcp.nodelay can cause a huge improvement in performance when there is high-volume traffic between database servers.
  • tcp.nodelay parameter can be used on both the client and server.
  • The tcp.nodelay parameter should be used only if TCP timeouts are encountered.
  • You can specify tcp.nodelay = yes to indicate no data buffering for all TCP/IP implementations.
  • Specifying tcp.nodelay = yes causes TCP buffering to be skipped so that every request is sent immediately. However network traffic can increase due to smaller and more frequent packet transmission causing slowdowns in the network.

Bypassing the Network Layer:

The automatic_ipc parameter speeds local connections to the database by bypassing the network layer.

automatic_ipc parameter:

  • When automatic_ipc=on , Oracle Net checks to see if a local database is defined by the same alias. If so, network layers are bypassed as the connection is translated directly to the local IPC connections. This is useful on database servers, but it’s absolutely useless for Oracle Net clients.
  • The automatic_ipc parameter should be used only on the database server when an Oracle Net connection must be made to the local database.
  • If local connections are not needed or required then all Oracle Net clients can improve performance by setting automatic_ipc= off;

Data Units:

The session data unit (SDU) and transport date unit (TDU) parameters are located in the tnsnames.ora and listener.ora files.

Session Data Unit (SDU)

Transport Date Unit (TDU)

SDU specifies the size of the packets to send over the network.

The TDU is the default packet size used within Oracle Net to group data together.

Oracle recommends that SDU be set equal to MTU.

The TDU parameter should ideally be a multiple of the SDU parameter.

The default value for both SDU and TDU is 2,048, and the maximum value is 32,767 bytes.

The SDU should never be set greater than TDU because you’ll waste network resources by shipping wasted space in each packet.

Set SDU and TDU to smaller values if users are connecting via modem lines. This is recommended because of the frequent resends that occur over modem lines.

Set SDU and TDU equal to the MTU for your network on fast network connections (T1 or T3 lines). The default MTU size is set to 1,514 bytes on standard Ethernet networks. The default MTU size is 4,202 on standard token ring networks.

Set the mts_dispatchers with the proper MTU TDU configuration if the Multi-threaded Server (MTS) is used.

Oracle recommends increasing the SDU to 32k for Streams replication and for using Oracle in a WAN environment.

 

Increasing SDU for Streams propagation:

Include DEFAULT_SDU_SIZE parameter in the receiving side of sqlnet.ora file in order to take advantage of an increased SDU for Streams propagation. The receiving side listener.ora file must indicate the SDU change for the system identifier (SID). The sending side tnsnames.ora file connect string must also include the SDU modification for the particular service.

Increasing Propagation Performance:

The performance of propagation on your system can be increased by SEND_BUF_SIZE and RECV_BUF_SIZE parameters in the listener.ora file. Network throughput can be significantly improved by using the SQLNET.SEND_BUF_SIZE and SQLNET.RECV_BUF_SIZE parameters to increase the size of the network TCP send and receive I/O buffers.

Determining number of requests:

You can determine the number of requests the listener can store while Oracle is working to establish a connection. This is determined by the undocumented queuesize parameter.

queuesize parameter:

  • The queuesize parameter is used only for very high-volume databases, where the listener spawns thousands of connections per hour.
  • The number of expected simultaneous connections should be equal to the size of the queuesize parameter.

LISTENER =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = marvin)
(PORT = 1521)
(QUEUESIZE = 32)
)
)

  • A disadvantage of queuesize parameter is that it uses more system memory and resources by pre-allocating resources for anticipated requests.
  • You can use MTS and pre-spawned Oracle connections if you have high-volume connections into a dedicated listener. Some versions of UNIX do not allow queues greater than five and there are some restrictions of the MTS queue size.

Conclusion:

To conclude I would say that an Oracle professional must fully understand and optimize Oracle Net parameters as they can have a great impact on the performance of distributed systems.

 

Author: Burleson

Locking is a very important part of any database system. Database table locks are coordinated through global inter-instance communication for RAC. It is the fact that properly designed applications need not to lock entire tables and therefore table locks can be disabled to improve locking efficiency with minimal adverse side effects.

Disabling Oracle Table Locks:

There are two methods for disabling table locks.

  1. Disabling table locks for individual tables.
  2. Setting dml_locks to zero.

Individual Oracle Table Locks:

You can enable or disable the ability to acquire individual table locks. You can use below command to prevent users from acquiring individual table locks. When users attempt to lock tables with disabled locks, they will receive an error.

ALTER TABLE table_name DISABLE TABLE LOCK

You can use below statement to re-enable table locking after a transaction.

ALTER TABLE table_name ENABLE TABLE LOCK

This forces all currently executing transactions to commit before enabling the table lock. The statement does not wait for new transactions to start after issuing the ENABLE statement. The disadvantage of using this statement is that it must be executed for all tables that may experience improper locking.

Oracle table_lock column:

The table_lock column can be queried to determine whether a table in the schema has its table lock enabled or disabled. The table_lock column lies in the user_tables data dictionary table.

The table lock state of other user’s tables can be queried as well if SELECT privilege is on dba_tables. The all_tables views can be used to see the locking state of tables for which a user has been granted SELECT privileges.

Table Locks for entire instance:

The table locks can be set for an entire instance by using the dml_locks initialization parameter. This will disable the DROP TABLE, CREATE INDEX and LOCK TABLE commands.

If the DROP TABLE, CREATE INDEX and LOCK TABLE commands are not needed then dml_locks should be set to zero to minimize lock conversions and achieve maximum performance. DDL statements cannot be executed against tables with disabled locks.

SQL*Loader checks the flag to ensure that there is not a non-parallel direct load running against the same table. Oracle is forced to create new extents for each session by using direct load.

If dml_locks are set to zero on one instance then it must be set it to zero on all instances. If non-zero values are used with the dml_locks parameter then the values need not be identical on all instances.

DDL Statements for maintenance tasks:

In any Oracle database, DDL statements should be used for maintenance tasks not during normal system operations. This will make the frequency of DDL statements should low. You can use global temporary tables or PL/SQL tables instead of permanent tables for reports.

RAC Performance Degradation:

Performance degradation to RAC environment will occur if the application has to create objects frequently. This is because the object creation requires inter-instance coordination. A large ratio of dlm_conflicts to dlm_requests on the dc_object_ids row cache in v$rowcache along with excessive wait times for the row cache lock event in v$system_event indicates that multiple instances in the cluster are issuing excessive amounts of concurrent DDL statements.

Improving Concurrent Object Creation:

In such cases you can improve the object creation performance by setting event 10297 so that it caches object_id values. This will improve concurrent object creation by eliminating the recursive DDL and some of the intra-instance pinging. Add below line to initialization parameter file in order to set event 10297.

event=”10297 trace name context forever, level 1″

Adjusting Caching behavior:

The caching behavior is automatically adjustable internally if the additional level argument is set to one. Otherwise the level can be set to the desired cache size.

Author: Burleson

With every release of Oracle we see many configuration and manageability enhancements. Many issues have been rectified and many facilities are provided to make the life of database administrator easier.

RMAN utility can be used to copy the database structures and metadata when you instantiate an entire database for Oracle Streams. The database cloning method is employed when you use RMAN. The RMAN DUPLICATE command is used to create a valid destination database. In this article I will discuss the steps involved in this process.

Create Backup with RMAN:

First of all you will create a backup with RMAN. Using the valid backup enables you to set up a destination database without interrupting the source database operations.

Create Database Link:

Now create a database link on the source database pointing to the destination database. The propagation process will use the database link.

Define Propagation:

Define propagation to the destination queue. You can use the add_global_propagation_rule procedure of dbms_streams_adm to create the propagation. This propagation will be created at the destination database. It will be kept disabled as the destination is not yet ready.

Capture Process:

Configure and start a capture process at the source database. add_global_rule procedure of dbms_streams_adm can be used for this purpose. This will allow you to capture all supported changes in the database. However this will not include the SYS and SYSTEM schemas.

Instantiation:

Now prepare the database for instantiation by executing the dbms_capture_adm.prepare_global_instantiation procedure. The effect of this procedure execution is to put the data dictionary information for all objects in the database into the redo logs, enabling the information to be propagated to all destination sites. This procedure also sets the instantiation SCN at the source database, so it can be read by the export utility.

EXEC DBMS_CAPTURE_ADM.PREPARE_GLOBAL_INSTANTIATION();

Current SCN:

Use the dbms_flashback package to get the current SCN. This value will be used during instantiation at the destination site, as well as by RMAN when duplicating the database.

SET SERVEROUTPUT ON
DECLARE
until_scn NUMBER;
BEGIN
until_scn:=
DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER;

DBMS_OUTPUT.PUT_LINE(’Until SCN: ‘ || until_scn);
END;

Archiving:

Now archive the current redo log by using below statement

ALTER SYSTEM ARCHIVE REDO LOG CURRENT;

RMAN:

Now start RMAN and issue the duplicate command. When you execute the duplicate command, RMAN performs an incomplete recovery, using all available incremental backups and archived logs. You also need to do a log switch on the source site, so the log containing the instantiation SCN can be archived. Once this log file is archived, make it available for RMAN to use when performing the duplicate command. Then, use the RMAN command as shown:

RUN {
SET UNTIL SCN xxxxxxx
DUPLICATE TARGET DATABASE TO DBSITE2.world
NOFILENAME CHECK OPEN RESTRICTED;}

Before running the RMAN DUPLICATE command, you must configure your system to support the database duplication. When you use the UNTIL SCN clause, RMAN recovers the database up to, but not including the specified SCN value. So, specify a value of until_scn + 1 for the ‘xxxxxxx’ shown in the example.

Destination Database:

Now connect to the destination database. Once RMAN creates the destination database then change the global name of this database to be different from the name of the source database.

ALTER DATABASE RENAME GLOBAL_NAME TO DBNEW.world;

Streams Configuration:

Now execute the remove_streams_configuration procedure in the dbms_streams_adm package at the destination site. This is needed because the duplicate database at the destination site has the entire old streams configuration. You can drop the details by executing below command. You must enable restricted session in order to run this command.

EXEC DBMS_STREAMS_ADM.REMOVE_STREAMS_CONFIGURATION();

Disable Restricted Session:

At the end you need to disable the restricted session.

ALTER SYSTEM DISABLE RESTRICTED SESSION;

 

Author: Mike Mortensen

In this article I will give some useful tips that will help you avoid PL/SQL performance problems. Most of work in PL/SQL programs is done by SQL statements and hence slow SQL statements are the main reason for slow execution. The loops and inside code must be optimized to gain performance boost. Badly written subprograms can also harm performance of your application.

Indexing:

Use appropriate indexes depending on the sizes of various tables in a query, the distribution of data in each query, and the columns used in the WHERE clauses.

Statistics:

There should be up-to-date statistics on all the tables. You can use the subprograms in the DBMS_STATS package for this purpose.

Function-based Index:

You can create a function-based index on the table in the query if a function is called within a SQL query. The CREATE INDEX statement might take a while but it can make your queries much faster.

Filtering:

The query cannot use regular indexes on that column and the function might be called for every row in a potentially very large table if a column is passed to a function within an SQL query. You can nest one query inside another to do the filtering and sorting in multiple stages. Instead of calling a PL/SQL function in the inner WHERE clause you can filter the result set to a small set of rows in the inner query, and call the function in the outer query.

Inefficient Approach

Efficient Approach

Calls function for every row Only calls function once for each distinct value.

BEGIN
FOR item IN (SELECT DISTINCT(SQRT(department_id)) col_alias FROM employees)
LOOP
DBMS_OUTPUT.PUT_LINE(item.col_alias);
END LOOP ;

FOR item IN
( SELECT SQRT(department_id) col_alias FROM
( SELECT DISTINCT department_id FROM employees)
)
LOOP
DBMS_OUTPUT.PUT_LINE(item.col_alias);
END LOOP ;
END;
/

Analysis:

You can analyze the execution plans and performance of the SQL statements using EXPLAIN PLAN statement and SQL Trace facility with TKPROF utility.

Query Hints:

Rewrite the SQL statements if necessary. Query hints can avoid problems such as unnecessary full-table scans.

Enhanced query for exact results:

You can enhance the original query to give you exactly the results you want by using UNION , INTERSECT , MINUS , and CONNECT BY clauses when you have to loop through a result set more than once or issue other queries as you loop through a result set.

Built-In String Functions:

PL/SQL provides many highly optimized string functions such as REPLACE , TRANSLATE , SUBSTR , INSTR , RPAD , and LTRIM that are more efficient than regular PL/SQL.

Regular Expressions:

Regular Expressions are an efficient tool for string matching. You can use PL/SQL string functions to search for regular expressions. You can search for regular expressions using the SQL operator REGEXP_LIKE . You can test or manipulate strings using the built-in functions REGEXP_INSTR , REGEXP_REPLACE , and REGEXP_SUBSTR .

Oracle Database regular expression features use characters like ‘.’, ‘*’, ‘^’, and ‘$’. There are also extensions such as ‘[:lower:]‘ to match a lowercase letter, instead of ‘[a-z]‘ which does not match lowercase accented letters.

FORALL Statement:

You can use FORALL statement as a way to replace loops of INSERT , UPDATE , and DELETE statements.

BULK COLLECT Clause:

You can bring the entire result set into memory in a single operation by using BULK COLLECT clause of the SELECT INTO statement while using looping through the result set of a query.

NOCOPY keyword:

PL/SQL adds some performance overhead to ensure correct action in case of exceptions if you use OUT or IN OUT parameters. If your program does not depend on OUT parameters then you can add the NOCOPY keyword to the parameter declarations so the parameters are declared OUT NOCOPY or IN OUT NOCOPY . This technique can give significant speedup if you are passing back large amounts of data in OUT parameters such as collections, big VARCHAR2 values, or LOBs.

SELF IN OUT NOCOPY:

You can explicitly declare the first parameter of the member method as SELF IN OUT NOCOPY instead of SELF IN OUT . This will avoid the overhead when the methods modify attributes of the object type and all the attributes are copied when the method ends.

Short-Circuit Evaluation:

PL/SQL uses functionality called short-circuit evaluation which stops evaluating a logical expression as soon as the result can be determined. When evaluating multiple conditions separated by AND or OR , put the least expensive ones first. For example, check the values of PL/SQL variables before testing function return values, because PL/SQL might be able to skip calling the functions.

Use Packages:

When you call a packaged subprogram for the first time, the whole package is loaded into the shared memory pool. Subsequent calls to related subprograms in the package require no disk I/O, and your code executes faster. If the package is aged out of memory, it must be reloaded if you reference it again. You can improve performance by sizing the shared memory pool correctly. Make sure it is large enough to hold all frequently used packages but not so large that memory is wasted.

Pinning the Packages:

You can pin frequently accessed packages in the shared memory pool using the supplied package DBMS_SHARED_POOL . When a package is pinned, it is not aged out by the least recently used (LRU) algorithm and remains in memory no matter how full the pool gets or how frequently you access the package.

Minimize Implicit Data Type Conversions:

PL/SQL converts between different data types automatically at run time. Assigning a PLS_INTEGER variable to NUMBER variable results in a conversion as their internal representations are different.

The data types must be chosen carefully to minimize implicit conversions. Use literals of the appropriate types. Character literals must be used in character expressions and decimal numbers in number expressions. The conversion from INTEGER to PLS_INTEGER data type might improve performance because of the use of more efficient hardware arithmetic.

Integer Arithmetic:

Use the data type PLS_INTEGER if the value of a local integer variable might be NULL or if the variable needs overflow checking. If the value of the variable will never be NULL , and the variable does not need overflow checking then use the data type SIMPLE_INTEGER .

Avoid constrained subtypes such as INTEGER , NATURAL , NATURALN , POSITIVE , POSITIVEN , and SIGNTYPE in performance-critical code. Variables of these types require extra checking at run time each time they are used in a calculation.

Floating-Point Arithmetic:

The BINARY_FLOAT and BINARY_DOUBLE types can use native hardware arithmetic instructions and are more efficient for applications such as scientific processing. They also require less space in the database.

If the value of the variable will never be NULL then use the subtype SIMPLE_FLOAT or BINARY_FLOAT instead of the base type SIMPLE_DOUBLE or BINARY_DOUBLE . Without the overhead of checking for nullness, SIMPLE_FLOAT and SIMPLE_DOUBLE provide significantly better performance than BINARY_FLOAT and BINARY_DOUBLE when PLSQL_CODE_TYPE=’NATIVE’ , because arithmetic operations on SIMPLE_FLOAT and SIMPLE_DOUBLE values are done directly in the hardware. When PLSQL_CODE_TYPE=’INTERPRETED’ , the performance improvement is smaller. However these types are less suitable for financial code where accuracy is critical.

Memory Conservation:

You can conserve memory by declaring VARCHAR2 variables with large sizes such as 32000 rather than estimating just a little on the high side 256 or 1000. PL/SQL has an optimization that makes it easy to avoid overflow problems and still conserve memory. PL/SQL waits until you assign the variable and then only allocates as much storage as needed.

Follow Compiler Warnings:

The PL/SQL compiler issues warnings. These warnings are about the issues that might lead to poor performance. Follow such warnings and change the code accordingly to be more efficient.

Author: Adrian Billington

Oracle 10g enables PL/SQL developers to trap AND log exceptions accurately. The DBMS_UTILITY.FORMAT_ERROR_BACKTRACE function provides the flexibility and information that DBMS_UTILITY.FORMAT_ERROR_STACK function simply didn’t provide.

Low Level of Information:

Many PL/SQL developers become satisfied with the level of information described below. They take screen scrapes of their scheduling systems’ output as application logs or perhaps their front-end applications display the error stack. Below PL/SQL block demonstrates where a procedure, function or anonymous block hit an exception.

SQL> BEGIN
EXECUTE IMMEDIATE ‘garbage’;
END;
/
BEGIN
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 2

Logging:

Many systems have requirement to write application logs to files or tables. Many developers follow the pseudo-approach as below in order to ensure that the exception is logged. In the below example DBMS_OUTPUT.PUT_LINE refers to an application logging package.

SQL> BEGIN
EXECUTE IMMEDIATE ‘garbage’;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( SQLERRM );
RAISE;
END;
/
ORA-00900: invalid SQL statement
BEGIN
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 6

The point in the code where the exception is raised moves to the explicit RAISE call. The application logs would now record the fact that an ORA-00900 was raised but in a scaled-up application it wouldn’t know which statement hit the exception. This can be a major problem. Consider a scenario where out of 98 separate UPDATE statements one in the middle somewhere fail with an invalid number exception. The only way to identify the actual statement will be by removing the others so Oracle could tell the correct line number.
The DBMS_UTILITY.FORMAT_ERROR_STACK function provides no information over and above the SQLERRM function used in the previous example. It only appends a line feed.

SQL> BEGIN
EXECUTE IMMEDIATE ‘garbage’;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( DBMS_UTILITY.FORMAT_ERROR_STACK );
RAISE;
END;
/
ORA-00900: invalid SQL statement

BEGIN
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 6

DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:

Oracle 10g DBMS_UTILITY.FORMAT_ERROR_BACKTRACE provides the error stack all the way back to source. Below example output is very simple and provides the accurate information.

SQL> BEGIN
EXECUTE IMMEDIATE ‘garbage’;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE );
RAISE;
END;
/
ORA-06512: at line 2

BEGIN
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 6

DBMS_UTILITY.FORMAT_ERROR_BACKTRACE function supplies the error propagation path not the error message. Therefore we need to include a call to SQLERRM

SQL> BEGIN
EXECUTE IMMEDIATE ‘garbage’;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( SQLERRM );
DBMS_OUTPUT.PUT_LINE( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE );
RAISE;
END;
/
ORA-00900: invalid SQL statement
ORA-06512: at line 2

BEGIN
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 7

We now have sufficient information for our application logs, while the error stack generated from the RAISE call can be discarded as it is included to send the necessary failure signal to the calling program / scheduler / shell.

Nesting of Application Blocks:

As the nesting of exception blocks increases, so does the amount of information the new function provides.

SQL> CREATE PROCEDURE will_error AS
BEGIN
RAISE PROGRAM_ERROR;
END;
/

Procedure created.

SQL> BEGIN
will_error();
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( SQLERRM );
DBMS_OUTPUT.PUT_LINE( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE );
END;
/
ORA-06501: PL/SQL: program error
ORA-06512: at “SCOTT.WILL_ERROR”, line 3
ORA-06512: at line 2

Now we have a full propagation record of our exception from its origin through to the outermost caller. Reading the stack from top to bottom, the exact points at which the exceptions were encountered are preserved. Be cautious if we go back to procedure WILL_ERROR and re-raise the exception in a WHEN OTHERS or such-like then we will once again lose the correct line.
To conclude I would say that an important distinction needs to be made between application code that needs to be logged and that which doesn’t. Various utility packages in an overall application will not handle unexpected exceptions in any way. These will be captured and logged by the business-rule packages that process data and need to write to application log files. These processing packages will each contain a call to the new DBMS_UTILITY.FORMAT_ERROR_BACKTRACE function to enable them to log the precise origins and propagation path of an exception.

Author: R. Nyffenegger

In this article I will discuss some great tips about Oracle flashback. You can use the as of clause in a select statement to see the data as of a past SCN or past point in time. This makes it possible to compare the current data in a table with a previous data set.

Comparing Data from two different times:

You can compare data from two different times by using the AS OF clause in self-joins, or in set operations such as INTERSECT and MINUS . The results can be stored by preceding a Flashback Query with a CREATE TABLE AS SELECT or INSERT INTO TABLE SELECT statement.

Below query re-inserts the rows that were present an hour ago in the table.

INSERT INTO employee
(SELECT * FROM employee AS OF
TIMESTAMP (SYSTIMESTAMP – INTERVAL ‘60′ MINUTE))
MINUS SELECT * FROM employee);

Creating View:

A view referring to past data can be created by using the AS OF clause in the SELECT statement that defines the view. The past time is recalculated for each query if you specify a relative time by subtracting from SYSDATE . After a change in daylight savings time, SYSDATE – 1 might refer to either 23 or 25 hours ago instead of 24.

CREATE VIEW hour_ago AS
SELECT * FROM employee AS OF
TIMESTAMP (SYSTIMESTAMP - INTERVAL ‘60′ MINUTE );

SCN vs. TIMESTAMP:

Oracle Database uses SCNs internally and maps these to timestamps at a granularity of 3 seconds. Use an SCN instead of a timestamp if a possible 3-second error (maximum) is important to a Flashback Query in your application.

Flashback for DDL and DML Operations:

The AS OF clause for each table can be specified or omitted and different times for different tables can be specified. AS OF clause can be used in a query to perform DDL operations such as creating and truncating tables or DML operations such as inserting and deleting) in the same session as the query.

AS OF clause can be used inside an INSERT or CREATE TABLE AS SELECT statement in order to use the results of a Flashback Query in a DDL or DML statement that affects the current state of the database.

Finding changed values in a table:

Consider a table say flashback_ex. If you apply the as of clause on a table within the first five minutes after its creation then Oracle reports an ORA-01466 unable to read data – table definition has changed error .

create table flashback_ex (
id number not null,
txt varchar2(7)
);
exec dbms_lock .sleep(5*60 + 1)

Now we insert some records into above table.

insert into flashback_ex values (1,’one’ );
insert into flashback_ex values (2,’two’ );
insert into flashback_ex values (3,’three’);
insert into flashback_ex values (4,’four’ );
insert into flashback_ex values (5,’five’ );
insert into flashback_ex values (6,’six’ );
insert into flashback_ex values (7,’seven’);
insert into flashback_ex values (8,’eight’);
insert into flashback_ex values (9,’nine’ );
commit;

At this stage a bind variable is created and assigned the current SCN. The value of this variable could now be printed with print v_scn .

variable v_scn number
… exec :v_scn := dbms_flashback .get_system_change_number
Now we will update a few records
insert into flashback_ex values (10, ‘ten’ );
insert into flashback_ex values (20, ‘twenty’);
update flashback_ex set id = 40, txt=’fourty’ where id = 4;
update flashback_ex set id = 50, txt=’fifty’ where id = 5;
delete from flashback_ex where id = 7;
delete from flashback_ex where id = 8;
commit;

Now in order to find changed values in the table use full join on the values as of now with the values that were valid at the SCN stored in the variable v_scn . The where conditions makes sure only those records are returned that have changed.

set numf 99999
select
case when prv_id is null then ‘deleted’
when cur_id is null then ‘inserted’
else ‘updated’
end operation,
prv_id, cur_id,
prv_txt, cur_txt
from (
select rowid r, id prv_id, txt prv_txt from flashback_ex
as of scn :v_scn
) full join (
select rowid r, id cur_id, txt cur_txt from flashback_ex
) using (r)
where prv_id != cur_id or
prv_txt != cur_txt or
prv_id is null or
cur_id is null ;

OPERATIO PRV_ID CUR_ID PRV_TX CUR_TX
——– —— —— —— ——
updated 4 40 four fourty
updated 5 50 five fifty
inserted 8 eight
inserted 7 seven
deleted 20 twenty
deleted 10 ten