<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The AppsDBA Blog</title>
	<atom:link href="http://www.appsdba.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.appsdba.com/blog</link>
	<description></description>
	<lastBuildDate>Sat, 14 Apr 2012 19:30:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>OLF: Configuration Settings</title>
		<link>http://www.appsdba.com/blog/?p=543</link>
		<comments>http://www.appsdba.com/blog/?p=543#comments</comments>
		<pubDate>Sat, 14 Apr 2012 19:30:11 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Logging]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=543</guid>
		<description><![CDATA[Configuration settings in the Oracle Logging Framework (OLF) consist of adding or modifying rows in the dblog_config table that correspond to the task and its logging options. The table has the following columns: There is a unique index on the columns: ( module_name, action_name, username, sid, inst_id ). This is done to try and prevent [...]]]></description>
			<content:encoded><![CDATA[<p>Configuration settings in the Oracle Logging Framework (OLF) consist of adding or modifying rows in the dblog_config table that correspond to the task and its logging options. The table has the following columns:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; desc dblog_config
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
CONFIG_ID                                 NOT NULL NUMBER
MODULE_NAME                                        VARCHAR2(30)
ACTION_NAME                                        VARCHAR2(30)
USERNAME                                           VARCHAR2(30)
SID                                                NUMBER
INST_ID                                            NUMBER
LOG_LEVEL                                 NOT NULL VARCHAR2(10)
TRACE_ENABLED                             NOT NULL CHAR(1)

SQL&gt;
</pre>
<p>There is a unique index on the columns: ( module_name, action_name, username, sid, inst_id ). This is done to try and prevent duplicate records. The logging level and whether to turn on trace are set by updating the log_level and trace_enabled columns.</p>
<p>The query of this table has an ORDER BY in it to attempt to get the most restrictive qualifying record. For example the following three records are valid:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; select * from dbamon.dblog_config;

CONFIG_ID MODULE_NAME ACTION_NAME USERNAME   SID INST_ID LOG_LEVEL TRACE_ENABLED
--------- ----------- ----------- -------- ----- ------- --------- -------------
        1 module      action                             DEBUG     Y
        3 module      action      dbamon                 INFO      N
        4 module      action      dbamon      42       1 ERROR     Y

SQL&gt; select user, SYS_CONTEXT('USERENV','SID'), SYS_CONTEXT('USERENV','INSTANCE') from dual;

USER
------------------------------
SYS_CONTEXT('USERENV','SID')
--------------------------------------------------------------------------------
SYS_CONTEXT('USERENV','INSTANCE')
--------------------------------------------------------------------------------
DBAMON
42
1

SQL&gt;
</pre>
<p>The most restrictive record is config_id 4. If we query dblog.get_current_level we should see a log_level of ERROR:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; select dblog.get_current_level from dual;

GET_CURRENT_LEVEL
--------------------------------------------------------------------------------
INFO

SQL&gt; exec ilo_task.begin_task('module','action');

PL/SQL procedure successfully completed.

SQL&gt; select dblog.get_current_level from dual;

GET_CURRENT_LEVEL
--------------------------------------------------------------------------------
ERROR

SQL&gt;
</pre>
<p>Note that our first attempt returned the default level of INFO. It wasn&#8217;t until we set our module and action, I had already verified the username, sid and inst_id above, that dblog picked up the most restrictive record and returned a log level of ERROR. The same holds true for dblog.is_trace_enabled:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; select dblog.is_trace_enabled from dual;

IS_TRACE_ENABLED
--------------------------------------------------------------------------------
Y

SQL&gt;
</pre>
<p>So now we can set the log_level and/or whether to trace on the fly for any Oracle process that matches our module and action and/or username and/or sid and instance id.</p>
<p>Next up we&#8217;ll talk about the integration with the <a title="Method-R Instrumentation Library for Oracle" href="http://sourceforge.net/projects/ilo/">Method-R Instrumentation Library for Oracle</a> and how together we have an Oracle Logging Framework.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=543</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OLF: Appenders</title>
		<link>http://www.appsdba.com/blog/?p=523</link>
		<comments>http://www.appsdba.com/blog/?p=523#comments</comments>
		<pubDate>Thu, 12 Apr 2012 05:36:46 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Logging]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=523</guid>
		<description><![CDATA[In keeping with a Log4j mode (i.e. levels from the last post) the Oracle Logging Framework (OLF) supplies two appenders or output modes. One outputs to a predefined table and the other to the console (i.e. dbms_output). This is done mainly to keep things simple. Other Oracle logging tools create more code to manage their [...]]]></description>
			<content:encoded><![CDATA[<p>In keeping with a Log4j mode (i.e. levels from the last post) the Oracle Logging Framework (OLF) supplies two appenders or output modes. One outputs to a predefined table and the other to the console (i.e. dbms_output). This is done mainly to keep things simple. Other Oracle logging tools create more code to manage their output modes than they do to manage the actual logging, and this was not something that I wanted to repeat.</p>
<p>The table based appender inserts all logging messages to a single database table.The table has the following format:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; desc dblog_log
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
LOGID                                     NOT NULL NUMBER
USERNAME                                  NOT NULL VARCHAR2(30)
SID                                       NOT NULL NUMBER
INST_ID                                   NOT NULL NUMBER
DATETIME                                  NOT NULL TIMESTAMP(6)
MODULE_NAME                                        VARCHAR2(30)
ACTION_NAME                                        VARCHAR2(30)
LOG_LEVEL                                          VARCHAR2(10)
TASKTIME                                           NUMBER
OBJECT_NAME                                        VARCHAR2(61)
LINE_NO                                            NUMBER
TEXT                                               CLOB
SQL_ERRNO                                          NUMBER
SQL_ERRMSG                                         VARCHAR2(100)
SQL_BACKTRACE                                      VARCHAR2(1000)

SQL&gt;
</pre>
<p>The key output fields include tasktime, object_name and line_no from the call stack, text, the SQL error number, message and backtrace if an error.</p>
<p>The second appender uses DBMS_OUTPUT which requires running the code interactively. This appender is primarily meant to facilitate debugging since most code is not run from SQL*Plus. The output is formatted into two lines of the format:</p>
<pre class="brush: plain; title: ; notranslate">

level:user:sid:inst_id:datetime:module:action
level:tasktime:owner.object_name:line_no:text
</pre>
<p>Errors include three additional lines for error number, message and the backtrace:</p>
<pre class="brush: plain; title: ; notranslate">

ERROR: Oracle error code: 100
ERROR: Oracle error message: ORA-01403: no data found
ERROR: Backtrace: ORA-06512: at line 8
</pre>
<p>The following anonymous PL/SQL block was run with a config level of INFO:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; set serveroutput on;
declare
l_num number;
begin
ilo_task.begin_task(
module =&gt; 'module',
action =&gt; 'action');
--
dblog.info('Before statement');
select 1 into l_num from dual;
dblog.info('After statement');
--
ilo_task.end_task;
end;
/SQL&gt;   2    3    4    5    6    7    8    9   10   11   12   13   14
INFO:DBAMON:38:1:12-APR-12 01.02.01.051535 AM:module:action
INFO:NULL:DBAMON.ANONYMOUS BLOCK:Line 8:Before statement

INFO:DBAMON:38:1:12-APR-12 01.02.01.054261 AM:module:action
INFO:NULL:DBAMON.ANONYMOUS BLOCK:Line 10:After statement

PL/SQL procedure successfully completed.

SQL&gt;
</pre>
<p>The database log table entries were:</p>
<pre class="brush: plain; title: ; notranslate">

USER   DATETIME                     MODULE ACTION LEVEL OBJECT_NAME            LINE TEXT
------ ---------------------------- ------ ------ ----- ---------------------- ---- ----------------
DBAMON 12-APR-12 01.02.01.053545 AM module action INFO  DBAMON.ANONYMOUS BLOCK    8 Before statement
DBAMON 12-APR-12 01.02.01.056147 AM module action INFO  DBAMON.ANONYMOUS BLOCK   10 After statement
</pre>
<p>For an error condition the error columns look like:</p>
<pre class="brush: plain; title: ; notranslate">

USER   MODULE ACTION LEVEL OBJECT_NAME            LINE TEXT                     errno errmsg                   backtrace
------ ------ ------ ----- ---------------------- ---- ------------------------ ----- ------------------------ --------------------
DBAMON module action ERROR DBAMON.ANONYMOUS BLOCK   13 dblog.error test message   100 ORA-01403: no data found ORA-06512: at line 8
</pre>
<p>So those are the two planned output modes for the Oracle Logging Facility. Next up we&#8217;ll talk a little bit more about the input configuration settings.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=523</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OLF: Logging Levels</title>
		<link>http://www.appsdba.com/blog/?p=506</link>
		<comments>http://www.appsdba.com/blog/?p=506#comments</comments>
		<pubDate>Tue, 10 Apr 2012 05:22:35 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Logging]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=506</guid>
		<description><![CDATA[Logging levels are available in many logging tools. Log4j, log4perl and log4plsql all have logging levels. The Oracle Logging Facility (OLF) follows the basic Log4j logging levels and values: FATAL &#8211; 50000 ERROR &#8211; 40000 WARN &#8211; 30000 INFO &#8211; 20000 DEBUG &#8211; 10000 Log4j also includes an ALL and an OFF level, and the [...]]]></description>
			<content:encoded><![CDATA[<p>Logging levels are available in many logging tools. Log4j, log4perl and log4plsql all have logging levels. The Oracle Logging Facility (OLF) follows the basic Log4j logging levels and values:</p>
<ul>
<li>FATAL &#8211; 50000</li>
<li>ERROR &#8211; 40000</li>
<li>WARN &#8211; 30000</li>
<li>INFO &#8211; 20000</li>
<li>DEBUG &#8211; 10000</li>
</ul>
<p>Log4j also includes an ALL and an OFF level, and the Oracle Logging Framework (OLF) includes these levels as well as a TIMED level that is used to insure that task timing is always logged. Each level is set so that ALL &lt; DEBUG &lt; INFO &lt; WARN &lt; ERROR &lt; FATAL &lt; TIMED &lt; OFF. A default level of INFO is assigned in the OLF code and can be overridden in the dynamic configuration or it can be explicitly set.</p>
<p>The log levels are hierarchical and a call to a level will only log messages that are of a level that is greater than or equal to the current level setting. In other words, if the current log level for the task has been set to INFO, then all dblog calls with a level of INFO or greater will be logged. DEBUG messages will not be logged. The level TIMED is not directly usable as it is set by the task time routine, and the ALL or OFF levels can only be set as the current configuration level.</p>
<p>Only the DEBUG, INFO, WARN, ERROR, FATAL levels can be used at the program level since there are no dblog.timed, dblog.all or dblog.off procedure calls.</p>
<p>The following table shows the output message hierarchy:</p>
<table width="80%" border="2" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td></td>
<td colspan="5">Will Output Messages</td>
</tr>
<tr>
<td>dblog level</td>
<td>DEBUG</td>
<td>INFO</td>
<td>WARN</td>
<td>ERROR</td>
<td>FATAL</td>
</tr>
<tr>
<td>DEBUG</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>INFO</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>WARN</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>ERROR</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>FATAL</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>TIMED</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>ALL</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>OFF</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
</tbody>
</table>
<p>The next topic will be about appenders.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=506</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OLF: Creating Dynamic Logging</title>
		<link>http://www.appsdba.com/blog/?p=459</link>
		<comments>http://www.appsdba.com/blog/?p=459#comments</comments>
		<pubDate>Mon, 09 Apr 2012 05:28:23 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Logging]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=459</guid>
		<description><![CDATA[One of the real benefits to using a logging tool is being able to dynamically set log levels. Whether it&#8217;s for a single user, program or task you don&#8217;t want to have to stop everything, reset a config file and then restart the application. You really want to be able to set the logging dynamically [...]]]></description>
			<content:encoded><![CDATA[<p>One of the real benefits to using a logging tool is being able to dynamically set log levels. Whether it&#8217;s for a single user, program or task you don&#8217;t want to have to stop everything, reset a config file and then restart the application. You really want to be able to set the logging dynamically on the fly. The problem with this approach is that to effectively do that means checking every time a logging call is made to see what the current log configuration is. This seems expensive since it usually means querying a table in the database for every call.</p>
<p>A new feature in Oracle 11g is the SQL Query Result Cache which stores the results of SQL queries in an area in the shared pool. By simply supplying a hint and having the result cache enabled, repetitive queries that return the same results are cached, causing almost no work for the database. The following is an example using code from the Oracle Logging Framework.</p>
<p>First a table to store our logging configuration data:</p>
<pre class="brush: plain; title: ; notranslate">

CREATE TABLE dblog_config
(
config_id       NUMBER        CONSTRAINT dblog_config_nn1 NOT NULL ENABLE,
module_name     VARCHAR2(30),
action_name     VARCHAR2(30),
username        VARCHAR2(30),
sid             NUMBER,
inst_id         NUMBER,
log_level       VARCHAR(10)   DEFAULT 'INFO' CONSTRAINT dblog_config_nn2 NOT NULL ENABLE,
trace_enabled   CHAR(1)       CONSTRAINT dblog_config_nn3 NOT NULL ENABLE,
CONSTRAINT dblog_config_ck1 CHECK(log_level IN ('ALL','DEBUG','INFO','WARN','ERROR','FATAL','TIMED','OFF')),
CONSTRAINT dblog_config_ck2 CHECK(trace_enabled IN ('Y','N')),
CONSTRAINT dblog_config_pk PRIMARY KEY (config_id) ENABLE
)
NOCOMPRESS
LOGGING;
--
</pre>
<p>I have added a single row for our testing:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; select * from dbamon.dblog_config;

CONFIG_ID MODULE_NAME ACTION_NAME USERNAME   SID INST_ID LOG_LEVEL TRACE_ENABLED
--------- ----------- ----------- -------- ----- ------- --------- -------------
        1 module      action                             INFO      Y

SQL&gt;
</pre>
<p>The following query can then be used by our logging code to determine the current configuration for &#8220;module&#8221; and &#8220;action&#8221;. This query also allows other fields in our configuration table to trigger actions, but for now we&#8217;ll focus on module and action:</p>
<pre class="brush: plain; title: ; notranslate">

SELECT /*+ RESULT_CACHE */ debugid,module_name,action_name,
username,sid,inst_id,UPPER(log_level) AS log_level,
UPPER(trace_enabled) AS trace_enabled
FROM  dbamon.dblog_config
WHERE (UPPER(module_name)=UPPER('&amp;&amp;module')
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND username IS NULL
AND sid IS NULL)
--
OR (UPPER(module_name)=UPPER('&amp;&amp;module')
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND UPPER(username)=UPPER(USER)
AND sid IS NULL)
--
OR ( UPPER(module_name)=UPPER('&amp;&amp;module')
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND username IS NULL
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')))
--
OR ( UPPER(module_name)=UPPER('&amp;&amp;module')
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND UPPER(username)=UPPER(USER)
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')))
--
--
OR ( module_name IS NULL
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND username IS NULL
AND sid IS NULL )
--
OR ( module_name IS NULL
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND UPPER(username)=UPPER(USER)
AND sid IS NULL )
--
OR ( module_name IS NULL
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND username IS NULL
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')) )
--
OR ( module_name IS NULL
AND UPPER(action_name)=UPPER('&amp;&amp;action')
AND UPPER(username)=UPPER(USER)
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')) )
--
--
OR ( module_name IS NULL
AND action_name IS NULL
AND username IS NULL
AND sid IS NULL )
--
OR ( module_name IS NULL
AND action_name IS NULL
AND UPPER(username)=UPPER(USER)
AND sid IS NULL )
--
OR ( module_name IS NULL
AND action_name IS NULL
AND username IS NULL
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')) )
--
OR ( module_name IS NULL
AND action_name IS NULL
AND (sid=SYS_CONTEXT('USERENV','SID')
AND inst_id=SYS_CONTEXT('USERENV','INSTANCE')) )
/
</pre>
<p>The cost to run this query the first time is shown below:</p>
<pre class="brush: plain; title: ; notranslate">

CONFIG_ID MODULE_NAME ACTION_NAME USERNAME   SID INST_ID LOG_LEVEL TRACE_ENABLED
--------- ----------- ----------- -------- ----- ------- --------- -------------
        1 module      action                             INFO      Y

Execution Plan
----------------------------------------------------------
Plan hash value: 2514110033

-------------------------------------------------------------------------------------------------
| Id  | Operation          | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                            |     1 |    24 |     3   (0)| 00:00:01 |
|   1 |  RESULT CACHE      | fq5ph52dq320u241n2r7pxkxn5 |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| DBLOG_CONFIG               |     1 |    24 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter(UPPER(&quot;MODULE_NAME&quot;)='MODULE' AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND
&quot;USERNAME&quot; IS NULL AND &quot;SID&quot; IS NULL OR UPPER(&quot;MODULE_NAME&quot;)='MODULE' AND
UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND UPPER(&quot;USERNAME&quot;)=UPPER(USER@!) AND &quot;SID&quot; IS NULL OR
UPPER(&quot;MODULE_NAME&quot;)='MODULE' AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND
&quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')) AND &quot;USERNAME&quot; IS NULL OR
UPPER(&quot;MODULE_NAME&quot;)='MODULE' AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND
UPPER(&quot;USERNAME&quot;)=UPPER(USER@!) AND &quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')) OR &quot;MODULE_NAME&quot; IS NULL AND
UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND &quot;USERNAME&quot; IS NULL AND &quot;SID&quot; IS NULL OR &quot;MODULE_NAME&quot;
IS NULL AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND UPPER(&quot;USERNAME&quot;)=UPPER(USER@!) AND &quot;SID&quot;
IS NULL OR &quot;MODULE_NAME&quot; IS NULL AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND
&quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')) AND &quot;USERNAME&quot; IS NULL OR
&quot;MODULE_NAME&quot; IS NULL AND UPPER(&quot;ACTION_NAME&quot;)='ACTION' AND
UPPER(&quot;USERNAME&quot;)=UPPER(USER@!) AND &quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')) OR &quot;MODULE_NAME&quot; IS NULL AND
&quot;ACTION_NAME&quot; IS NULL AND &quot;USERNAME&quot; IS NULL AND &quot;SID&quot; IS NULL OR &quot;MODULE_NAME&quot; IS NULL
AND &quot;ACTION_NAME&quot; IS NULL AND UPPER(&quot;USERNAME&quot;)=UPPER(USER@!) AND &quot;SID&quot; IS NULL OR
&quot;MODULE_NAME&quot; IS NULL AND &quot;ACTION_NAME&quot; IS NULL AND
&quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')) AND &quot;USERNAME&quot; IS NULL OR
&quot;MODULE_NAME&quot; IS NULL AND &quot;ACTION_NAME&quot; IS NULL AND
&quot;SID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','SID')) AND
&quot;INST_ID&quot;=TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')))

Result Cache Information (identified by operation id):
------------------------------------------------------

1 - column-count=8; dependencies=(DBAMON.DBLOG_CONFIG); parameters=(uid, nls, sys_context); name=&quot;SELECT /*+ RESULT_CACHE */ config_id,module_name,action_name,
username,sid,inst_id,UPPER(log_level) AS log_level,
UPPER(trace_en&quot;

Statistics
----------------------------------------------------------
127  recursive calls
0  db block gets
153  consistent gets
0  physical reads
0  redo size
887  bytes sent via SQL*Net to client
419  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
6  sorts (memory)
0  sorts (disk)
1  rows processed
</pre>
<p>Note that the explain plan contains a result cache operation so our hint was accepted. Subsequent runs show the advantage of the result cache. No logical I/Os are required once the results are cached:</p>
<pre class="brush: plain; title: ; notranslate">

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
0  consistent gets
0  physical reads
0  redo size
887  bytes sent via SQL*Net to client
419  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
</pre>
<p>The second query is almost &#8220;free&#8221;. What happens if we change a value in our &#8220;config&#8221; table? If we change the debug level from &#8220;INFO&#8221; to &#8220;DEBUG&#8221; then Oracle has to do a little more work:</p>
<pre class="brush: plain; title: ; notranslate">

CONFIG_ID MODULE_NAME ACTION_NAME USERNAME   SID INST_ID LOG_LEVEL TRACE_ENABLED
--------- ----------- ----------- -------- ----- ------- --------- -------------
        1 module      action                             DEBUG     Y

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
7  consistent gets
0  physical reads
0  redo size
888  bytes sent via SQL*Net to client
419  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
</pre>
<p>Note that I didn&#8217;t show it, but the execution plan stays the same, and the query now requires 7 logical I/Os. The database had to access the table to get the updated data. A subsequent query shows the use of the query result cache again:</p>
<pre class="brush: plain; title: ; notranslate">

CONFIG_ID MODULE_NAME ACTION_NAME USERNAME   SID INST_ID LOG_LEVEL TRACE_ENABLED
--------- ----------- ----------- -------- ----- ------- --------- -------------
        1 module      action                             DEBUG     Y

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
0  consistent gets
0  physical reads
0  redo size
888  bytes sent via SQL*Net to client
419  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
</pre>
<p>So if we use this technique to query our configuration table during each call from the framework the cost of being able to dynamically adjust logging is pretty low. This means we can easily change the logging level, or enable or disable logging or tracing on the fly for any session that uses the framework.</p>
<p>Note: I changed the name of the configuration table from what I had originally posted and this is now reflected in the examples. The configuration table will be called &#8220;dblog_config&#8221; in the first version of the OLF.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=459</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle Logging Framework</title>
		<link>http://www.appsdba.com/blog/?p=490</link>
		<comments>http://www.appsdba.com/blog/?p=490#comments</comments>
		<pubDate>Mon, 09 Apr 2012 05:10:45 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Logging]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=490</guid>
		<description><![CDATA[There is finally something to publish about the Oracle Logging Framework (OLF). This was a project that I have been thinking about for a long time. I even registered it as a SourceForge project back in 2008. Since then I&#8217;ve written about the framework in a paper title &#8220;Oracle Instrumentation&#8221; that was published in the [...]]]></description>
			<content:encoded><![CDATA[<p>There is finally something to publish about the Oracle Logging Framework (OLF). This was a project that I have been thinking about for a long time. I even registered it as a <a title="SourceForge project" href="http://sourceforge.net/projects/oraclelog/">SourceForge project</a> back in 2008. Since then I&#8217;ve written about the framework in a paper title &#8220;<a title="Oracle Instrumentation" href="http://appsdba.com/papers/Oracle%20Instrumentation_web.pdf">Oracle Instrumentation</a>&#8221; that was published in the IOUG SELECT magazine in 2009, and I spoke about the framework at last year&#8217;s Oracle Open World.  I&#8217;ve written about it on this blog, once about integrating with the Method-R ILO <a title="here" href="http://www.appsdba.com/blog/?p=262">here</a> and summarizing the Open World presentations <a title="here" href="http://www.appsdba.com/blog/?p=419">here</a>.</p>
<p>Well I&#8217;ve finally gotten around to almost finishing it, and I thought I would start to blog about the design of the code and then use the resulting posts to create the user guide. It will also give me a chance to document why some of the design decisions were made and generally what this logger has to offer that the other Oracle loggers out there don&#8217;t. I plan to follow/cover the requirements laid out in the original Oracle Instrumentation paper and how each of them were implemented. Along the way there will be plenty of examples and hopefully a compelling case to give it a try.</p>
<p>The following are the basic logging requirements of the framework:</p>
<ul>
<li>Debugging should be written to one or more “persistent” sources and preferably to a console for initial debugging.</li>
<li>Should be able to activate debugging remotely for one or more “users”.</li>
<li>Should be able to enable debugging for one or more “modules” in the code.</li>
<li>Provide logging levels (i.e. informational or error)</li>
<li>The ability to record errors and anomalies.</li>
<li>The ability to record runtime information.</li>
</ul>
<p>The first post will be about dynamic logging, which is really a requirement to being able to activate logging on the fly. Then we&#8217;ll cover logging levels. And after that we&#8217;ll have to see.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=490</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open World 2011 Presentations</title>
		<link>http://www.appsdba.com/blog/?p=419</link>
		<comments>http://www.appsdba.com/blog/?p=419#comments</comments>
		<pubDate>Tue, 04 Oct 2011 04:23:13 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Other Topics]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=419</guid>
		<description><![CDATA[I want to thank everyone for attending my two sessions yesterday. I also want to thank the OAUG Database SIG for the opportunity to present how we&#8217;re using DBFS HS at NIF and the IOUG for letting me speak about instrumenting applications for Oracle databases. Since I ran short on time in the instrumentation talk, [...]]]></description>
			<content:encoded><![CDATA[<p>I want to thank everyone for attending my two sessions yesterday. I also want to thank the OAUG Database SIG for the opportunity to present how we&#8217;re using DBFS HS at NIF and the IOUG for letting me speak about instrumenting applications for Oracle databases. Since I ran short on time in the instrumentation talk, I wanted to post the details of the logging and debugging examples.</p>
<p>The first example shows setting the level to INFO and then running two different anonymous PL/SQL blocks. The first doesn&#8217;t set the module and action and so it doesn&#8217;t output anything. The second block does set module and action and so the dblog calls output to the console and the log table.</p>
<pre class="brush: plain; title: ; notranslate">

INFO Level:

SQL&gt; !cat insert_info.sql
insert into dblog_settings values(1,'module','action',null,null,null,'INFO','N');
commit;

SQL&gt; @insert_info

1 row created.

Commit complete.

SQL&gt; @show_settings

USERNAME        SID    INST_ID module   action   level  trace
-------- ---------- ---------- -------- -------- ------ -----
                               module   action   INFO   N

SQL&gt; !cat dblog_info.sql
declare
  l_num number;
begin
  dblog.info('Before statement');
  select 1 into l_num from dual;
  dblog.info('After statement');
exception
  when others then
    dblog.error('Error message');
end;
/

SQL&gt; @dblog_info

PL/SQL procedure successfully completed.

SQL&gt; @show_log

no rows selected

SQL&gt; !cat dblog_info_task.sql
declare
  l_num number;
begin
  ilo_task.begin_task(
    module =&gt; 'module',
    action =&gt; 'action');
  --
  dblog.info('Before statement');
  select 1 into l_num from dual;
  dblog.info('After statement');
  --
  ilo_task.end_task;
end;
/

SQL&gt; @dblog_info_task.sql
INFO:DBAMON:51:1:03-OCT-11 02.36.40.269133 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 8:Before statement

INFO:DBAMON:51:1:03-OCT-11 02.36.40.275672 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 10:After statement

PL/SQL procedure successfully completed.

SQL&gt; @show_log

USERNAME        SID    INST_ID DATETIME           module   action   level    TASKTIME OBJECT_NAME               LINE_NO TEXT
-------- ---------- ---------- ------------------ -------- -------- ------ ---------- ---------------------- ---------- --------------------
DBAMON           51          1 03-OCT-11 02.36.40 module   action   INFO              DBAMON.ANONYMOUS BLOCK          8 Before statement
DBAMON           51          1 03-OCT-11 02.36.40 module   action   INFO              DBAMON.ANONYMOUS BLOCK         10 After statement

SQL&gt;
</pre>
<p>The next example shows how task times can be recorded using the ILO to mark the begin and end times:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; @clean_log

Table truncated.

SQL&gt; !cat dblog_info_tasktime.sql
declare
  l_num number;
begin
  ilo_task.begin_task(
    module =&gt; 'module',
    action =&gt; 'action',
    comment =&gt; 'Task1',
    begin_time =&gt; systimestamp);
  --
  dblog.info('Before statement');
  select 1 into l_num from dual;
  dblog.info('After statement');
  --
  ilo_task.end_task(
    end_time =&gt; systimestamp);
end;
/

SQL&gt; @dblog_info_tasktime.sql
INFO:DBAMON:60:1:03-OCT-11 02.41.48.059157 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 10:Before statement

INFO:DBAMON:60:1:03-OCT-11 02.41.48.107721 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 12:After statement

TASK_TIME:DBAMON:60:1:03-OCT-11 02.41.48.114385 PM:module:action
TASK_TIME:ILO.ILO_TIMER:Line 127:Task1

PL/SQL procedure successfully completed.

SQL&gt; @show_log

USERNAME        SID    INST_ID DATETIME           module   action   level    TASKTIME OBJECT_NAME               LINE_NO TEXT
-------- ---------- ---------- ------------------ -------- -------- ------ ---------- ---------------------- ---------- --------------------
DBAMON           60          1 03-OCT-11 02.41.48 module   action   INFO              DBAMON.ANONYMOUS BLOCK         10 Before statement
DBAMON           60          1 03-OCT-11 02.41.48 module   action   INFO              DBAMON.ANONYMOUS BLOCK         12 After statement
DBAMON           60          1 03-OCT-11 02.41.48 module   action             .057362 ILO.ILO_TIMER                 127 Task1

SQL&gt;
</pre>
<p>The third example shows how to invoke tracing when a task is matched and the trace_enabled flag has been set:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; !cat delete_info.sql
delete from dblog_settings;
commit;

SQL&gt; @delete_info.sql

1 row deleted.

Commit complete.

SQL&gt; !cat insert_trace.sql
insert into dblog_settings values(1,'module','action',null,null,null,'INFO','Y');
commit;

SQL&gt; @insert_trace.sql

1 row created.

Commit complete.

SQL&gt; @show_settings

USERNAME        SID    INST_ID module   action   level  trace
-------- ---------- ---------- -------- -------- ------ -----
                               module   action   INFO   Y

SQL&gt; !cat dblog_trace.sql
declare
  l_num number;
begin
  ilo_task.begin_task(
    module =&gt; 'module',
    action =&gt; 'action');
  --
  dblog.info('Before statement');
  select 1 into l_num from dual;
  dblog.info('After statement');
  --
  ilo_task.end_task;
end;
/

SQL&gt; @dblog_trace.sql
GET_CONFIG: tracing has been enabled
INFO:DBAMON:60:1:03-OCT-11 02.44.49.047982 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 8:Before statement

INFO:DBAMON:60:1:03-OCT-11 02.44.49.105359 PM:module:action
INFO:DBAMON.ANONYMOUS BLOCK:Line 10:After statement

PL/SQL procedure successfully completed.

SQL&gt;

SQL&gt; @dispusr
Enter value for 1: dbamon

User         Inst  Oracle  Serial OS      User          Client     Client                                               Service
Name           ID     SID  Number PID       ID Status   Identifier Info       Module               Action               Name
----------- ----- ------- ------- ------ ----- -------- ---------- ---------- -------------------- -------------------- ---------------
DBAMON          1      50     131 4585     262 INACTIVE                       SQL Developer                             SYS$USERS
DBAMON          1      60     473 5466     262 INACTIVE                       SQL*Plus                                  SYS$USERS
DBAMON          1      48     193 5526     262 ACTIVE                         SQL*Plus                                  SYS$USERS
SQL&gt;

[oracle@localhost debugging]$ cd /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace
[oracle@localhost trace]$ ls -lrt
total 3108
-rw-rw---- 1 oracle oracle     85 Sep  8 12:16 orcl_ora_2613.trm
-rw-rw---- 1 oracle oracle    828 Sep  8 12:16 orcl_ora_2613.trc
-rw-rw---- 1 oracle oracle     59 Sep  8 12:16 orcl_mman_2690.trm
-rw-rw---- 1 oracle oracle    874 Sep  8 12:16 orcl_mman_2690.trc

&lt; lines deleted &gt;

-rw-rw---- 1 oracle oracle   4021 Oct  3 12:52 orcl_lgwr_2660.trc
-rw-rw---- 1 oracle oracle 412070 Oct  3 12:55 alert_orcl.log
-rw-rw---- 1 oracle oracle    265 Oct  3 14:44 orcl_ora_5466.trm
-rw-rw---- 1 oracle oracle  31902 Oct  3 14:44 orcl_ora_5466.trc
-rw-rw---- 1 oracle oracle    506 Oct  3 14:46 orcl_mmon_2668.trm
-rw-rw---- 1 oracle oracle   5177 Oct  3 14:46 orcl_mmon_2668.trc
[oracle@localhost trace]$ more orcl_ora_5466.trc
Trace file /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_5466.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_2
System name:    Linux
Node name:      localhost.localdomain
Release:        2.6.18-194.17.1.0.1.el5
Version:        #1 SMP Wed Sep 29 15:40:03 EDT 2010
Machine:        i686
Instance name: orcl
Redo thread mounted by this instance: 1
Oracle process number: 40
Unix process pid: 5466, image: oracle@localhost.localdomain (TNS V1-V3)

*** 2011-10-03 14:44:49.029
*** SESSION ID:(60.473) 2011-10-03 14:44:49.029
*** CLIENT ID:() 2011-10-03 14:44:49.029
*** SERVICE NAME:(SYS$USERS) 2011-10-03 14:44:49.029
*** MODULE NAME:(SQL*Plus) 2011-10-03 14:44:49.029
*** ACTION NAME:() 2011-10-03 14:44:49.029

=====================
PARSING IN CURSOR #44032292 len=70 dep=1 uid=260 oct=47 lid=260 tim=1317678288954581 hv=3588952050 ad='3ad591d8' sqlid='2qkj5qvayq3zk'
BEGIN dbms_monitor.session_trace_enable (NULL, NULL, TRUE, TRUE); END;
END OF STMT
EXEC #44032292:c=0,e=771,p=0,cr=0,cu=0,mis=1,r=1,dep=1,og=1,plh=0,tim=1317678288954565
CLOSE #44032292:c=0,e=4,dep=1,type=3,tim=1317678289029614
ILO_TASK.BEGIN_TASK[][module][action][oracle~pts/1~sqlplus@localhost.localdomain (TNS V1-V3)~SYS$USERS][]

*** 2011-10-03 14:44:49.030
*** MODULE NAME:(module) 2011-10-03 14:44:49.030
*** ACTION NAME:(action) 2011-10-03 14:44:49.030

=====================
PARSING IN CURSOR #67389968 len=51 dep=1 uid=260 oct=47 lid=260 tim=1317678289030201 hv=3782099507 ad='3ad8fad0' sqlid='0dk9kgvhqwhjm'
BEGIN DBMS_SESSION.SET_IDENTIFIER(:client_id); END;
END OF STMT
BINDS #67389968:
Bind#0
oacdty=01 mxl=2000(255) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=01 csi=873 siz=2000 off=0
kxsbbbfp=03fdcd24  bln=2000  avl=64  flg=09
value=&quot;oracle~pts/1~sqlplus@localhost.localdomain (TNS V1-V3)~SYS$USERS&quot;
*** CLIENT ID:(oracle~pts/1~sqlplus@localhost.localdomain (TNS V1-V3)~SYS$USERS) 2011-10-03 14:44:49.047

EXEC #67389968:c=0,e=17330,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=0,tim=1317678289047514
CLOSE #67389968:c=0,e=5,dep=1,type=3,tim=1317678289047606

&lt; Truncated &gt;

[oracle@localhost trace]$
</pre>
<p>And finally calling the error level in an exception handler. Notice the backtrace information with the line number where the error occurred:</p>
<pre class="brush: plain; title: ; notranslate">

SQL&gt; @dblog_error.sql
FATAL:DBAMON:51:1:03-OCT-11 02.28.30.231192 PM:SQL*Plus:
FATAL:DBAMON.DBLOG:Line 861:Error message
FATAL Oracle error code: 100
FATAL Oracle error message: ORA-01403: no data found
FATAL Backtrace: ORA-06512: at line 4

PL/SQL procedure successfully completed.

SQL&gt; l
1  declare
2    l_num number;
3  begin
4    select 1 into l_num from dummy;
5  exception
6    when others then
7      dblog.error('Error message');
8* end;
SQL&gt; @show_error

USERNAME DATETIME           level  OBJECT_NAME               LINE_NO  SQL_ERRNO SQL_ERRMSG                SQL_BACKTRACE
-------- ------------------ ------ ---------------------- ---------- ---------- ------------------------- -------------------------
DBAMON   30-SEP-11 01.15.10 ERROR  DBAMON.ANONYMOUS BLOCK          7        100 ORA-01403: no data found  ORA-06512: at line 4

SQL&gt;
</pre>
<p>I hope this helps and I&#8217;ll post links to the presentations and the instrumentation paper shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=419</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The LAG Function</title>
		<link>http://www.appsdba.com/blog/?p=383</link>
		<comments>http://www.appsdba.com/blog/?p=383#comments</comments>
		<pubDate>Thu, 23 Jun 2011 05:05:16 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Oracle SQL]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=383</guid>
		<description><![CDATA[The Oracle LAG function gives the value of the previous row within a table without the need for a self join. The LAG and LEAD functions have been available since Oracle 8.1.6 when analytic functions were first introduced. Tom Kyte dedicated an entire chapter to analytic functions in his first book, &#8220;Expert One-on-One Oracle&#8221; and [...]]]></description>
			<content:encoded><![CDATA[<p>The Oracle LAG function gives the value of the previous row within a table without the need for a self join. The LAG and LEAD functions have been available since Oracle 8.1.6 when analytic functions were first introduced. Tom Kyte dedicated an entire chapter to analytic functions in his first book, &#8220;<a title="Expert One-on-One Oracle" href="http://www.amazon.com/Expert-One-One-Oracle-Thomas/dp/1590592433">Expert One-on-One Oracle</a>&#8221; and they have obviously been part of the Oracle documentation as well. Their adoption has not been as quick though, and I will admit to being slow when it comes to converting code from using a self join and subtracting n and n+1 values rather than using LAG. In the open source <a title="SYSMON" href="http://sourceforge.net/projects/orautil/files/orautil/">SYSMON</a> code many of the views used for interval summation used a function of the form:</p>
<pre class="brush: plain; title: ; notranslate">
  DECODE( SIGN(e.phyrds - b.phyrds),-1,0,
    (e.phyrds - b.phyrds) ),
</pre>
<p>This required a self join to get the begin and end values for each interval. This was done to insure that no negative values occurred when an instance restart occurred. The full SQL looked similar to this:</p>
<pre class="brush: sql; title: ; notranslate">
WITH g_fileio AS
(
  select
    fs.snap_id,
    fs.dbid,
    fs.instance_number,
    fs.tsname,
    fs.filename,
    fs.phyrds
  from
    dba_hist_filestatxs fs
)
SELECT
  b.begin_interval_time,
  e.begin_interval_time,
  e.snap_id,
  e.dbid,
  e.instance_number,
  e.tsname,
  e.filename,
  DECODE( SIGN(e.phyrds - b.phyrds),-1,0,
    (e.phyrds - b.phyrds) ),
  DECODE( SIGN(e.phyblkrd - b.phyblkrd),-1,0,
    (e.phyblkrd - b.phyblkrd) ),
  DECODE( SIGN(e.readtim - b.readtim),-1,0,
    (e.readtim - b.readtim) ),
  DECODE( SIGN(e.singleblkrds - b.singleblkrds),-1,0,
    (e.singleblkrds - b.singleblkrds) ),
  DECODE( SIGN(e.singleblkrdtim - b.singleblkrdtim),-1,0,
    (e.singleblkrdtim - b.singleblkrdtim) ),
  DECODE( SIGN(e.phywrts - b.phywrts),-1,0,
    (e.phywrts - b.phywrts) ),
  DECODE( SIGN(e.phyblkwrt - b.phyblkwrt),-1,0,
    (e.phyblkwrt - b.phyblkwrt) ),
  DECODE( SIGN(e.writetim - b.writetim),-1,0,
    (e.writetim - b.writetim) )
FROM
  g_fileio b,
  g_fileio e
WHERE
  e.snap_id = b.snap_id + 1
  AND b.tsname = e.tsname
  AND b.filename = e.filename
  AND b.dbid = e.dbid
  AND b.instance_number = e.instance_number
</pre>
<p>The following will compare the &#8220;old&#8221; way of using a self join with the LAG function.</p>
<p><strong>LAG Function Usage</strong></p>
<p>The following example will show how the LAG function can be used when accessing AWR tables in Oracle 11g. Initially just one &#8220;value&#8221; will be accessed to show how the LAG function works. The following SQL illustrates the example:</p>
<pre class="brush: sql; title: ; notranslate">
column filename format a50;
WITH g_fileio AS
(
  select
    fs.snap_id,
    fs.dbid,
    fs.instance_number,
    fs.tsname,
    fs.filename,
    fs.phyrds
  from
    dba_hist_filestatxs fs
)
SELECT
  e.snap_id,
  e.instance_number,
  e.filename,
  e.phyrds as curr_rds,
  LAG(e.phyrds,1,0) OVER(
    PARTITION BY e.dbid, e.instance_number, e.tsname, e.filename
    ORDER BY e.snap_id ) as prev_rds
FROM
  g_fileio e
WHERE
  e.snap_id between 83578 and 83590
  and e.tsname = 'DATA_TBS'
  and e.instance_number = 2
ORDER BY
  e.snap_id
/
</pre>
<p>This LAG function has been written in a manner that if the previous row is outside the scope of our result set it will return a zero, otherwise it will return the previous row&#8217;s value for phyrds. When this SQL is run we see that for the first interval that the &#8220;previous&#8221; value is 0. This makes sense since there is no previous row in our set, as constrained by &#8220;e.snap_id between 83578 and 83590&#8243;, and as we said previously our LAG function has been defined to return a zero in that case. The rest of the rows return the value of the previous row&#8217;s phyrds column. Notice that we&#8217;ve order by snap_id to make this easy to see in the example below:</p>
<pre class="brush: plain; title: ; notranslate">
   SNAP_ID INSTANCE_NUMBER FILENAME                                 CURRRDS    PREVRDS
---------- --------------- ------------------------------------- ---------- ----------
     83578               2 +ORADATA01/db11g/data_tbs_01.dbf           36477          0
     83579               2 +ORADATA01/db11g/data_tbs_01.dbf           36484      36477
     83580               2 +ORADATA01/db11g/data_tbs_01.dbf           36484      36484
     83581               2 +ORADATA01/db11g/data_tbs_01.dbf           36512      36484
     83582               2 +ORADATA01/db11g/data_tbs_01.dbf           36512      36512
     83583               2 +ORADATA01/db11g/data_tbs_01.dbf           36519      36512
     83584               2 +ORADATA01/db11g/data_tbs_01.dbf           36519      36519
     83585               2 +ORADATA01/db11g/data_tbs_01.dbf           36541      36519
     83586               2 +ORADATA01/db11g/data_tbs_01.dbf           36541      36541
     83587               2 +ORADATA01/db11g/data_tbs_01.dbf           36542      36541
     83588               2 +ORADATA01/db11g/data_tbs_01.dbf           36544      36542
     83589               2 +ORADATA01/db11g/data_tbs_01.dbf           36544      36544
     83590               2 +ORADATA01/db11g/data_tbs_01.dbf           36545      36544
</pre>
<p>This is an important observation that we will explore further in a subsequent section.</p>
<p><strong>Efficiency</strong></p>
<p>So an interesting question is how much better, if at all, is the LAG function over the original self join?</p>
<p>In order to make the &#8220;lag&#8221; example produce the same output as the &#8220;self-join&#8221; example the LAG function was moved into the &#8220;WITH&#8221; clause so that the row previous to the first row of the result set would be available. In our first example we didn&#8217;t do this to illustrate how the LAG function handles the situation where there is no previous row.</p>
<p>The &#8220;self-join&#8221; SQL:</p>
<pre class="brush: sql; title: ; notranslate">
column filename format a50;
SELECT
  e.snap_id,
  e.instance_number,
  e.filename,
  DECODE( SIGN(e.phyrds - b.phyrds),-1,0,
    (e.phyrds - b.phyrds) ) AS delta_phyrds
FROM
  dba_hist_filestatxs b,
  dba_hist_filestatxs e
WHERE
  e.snap_id = b.snap_id + 1
  AND b.filename = e.filename
  AND b.dbid = e.dbid
  AND b.instance_number = e.instance_number
  and e.snap_id between 83578 and 83590
  and e.tsname = 'DATA_TBS'
  and e.instance_number = 2
ORDER BY
  e.snap_id
/
</pre>
<p>The &#8220;lag&#8221; SQL:</p>
<pre class="brush: sql; title: ; notranslate">
column filename format a50;
WITH g_fileio AS
(
  select
    fs.snap_id,
    fs.dbid,
    fs.instance_number,
    fs.tsname,
    fs.filename,
    fs.phyrds - LAG(fs.phyrds,1,0)
    OVER( PARTITION BY fs.dbid, fs.instance_number, fs.tsname, fs.filename
      ORDER BY fs.snap_id ) as delta_phyrds
  from
    dba_hist_filestatxs fs
)
SELECT
  e.snap_id,
  e.instance_number,
  e.filename,
  e.delta_phyrds
FROM
  g_fileio e
WHERE
  e.snap_id BETWEEN 83578 AND 83590 AND
  e.tsname = 'DATA_TBS' AND
  e.instance_number = 2
ORDER BY
  e.snap_id
/
</pre>
<p>Using Tom Kyte&#8217;s &#8220;<a href="http://asktom.oracle.com/pls/apex/ASKTOM.download_file?p_file=6551378329289980701">runstats</a>&#8221; utility makes testing the difference between these two methods easy. The following will use a slightly modified version available <a href="http://appsdba.com/techinfo/runstats.htm">here</a> that summarizes the output into a &#8220;workload&#8221; format. This was used here because it shows just what is needed to see the difference between the two methods.</p>
<p>The test was run several times to try and filter out the affects of whether the data was cached or not. In fact, the &#8220;self-join&#8221; version is particularly sensitive to caching and can be expected to run much more slowly when the data is not if the buffer cache.</p>
<p><strong>Test Script</strong></p>
<pre class="brush: sql; title: ; notranslate">
exec runStats_pkg.rs_start;
column filename format a50;
SELECT
  e.snap_id,
  e.instance_number,
  e.filename,
  DECODE( SIGN(e.phyrds - b.phyrds),-1,0,
    (e.phyrds - b.phyrds) ) AS delta_phyrds
FROM
  dba_hist_filestatxs b,
  dba_hist_filestatxs e
WHERE
  e.snap_id = b.snap_id + 1
  AND b.filename = e.filename
  AND b.dbid = e.dbid
  AND b.instance_number = e.instance_number
  and e.snap_id between 83578 and 83590
  and e.tsname = 'CMSPUB_DATA_TBS'
  and e.instance_number = 2
ORDER BY
  e.snap_id
/

exec runStats_pkg.rs_middle;

column filename format a50;
WITH g_fileio AS
(
  select
    fs.snap_id,
    fs.dbid,
    fs.instance_number,
    fs.tsname,
    fs.filename,
    fs.phyrds - LAG(fs.phyrds,1,0) OVER( PARTITION BY fs.dbid, fs.instance_number, fs.tsname, fs.filename
      ORDER BY fs.snap_id ) as delta_phyrds
  from
    dba_hist_filestatxs fs
)
SELECT
  e.snap_id,
  e.instance_number,
  e.filename,
  e.delta_phyrds
FROM
  g_fileio e
WHERE
  e.snap_id between 83578 and 83590
  and e.tsname = 'CMSPUB_DATA_TBS'
  and e.instance_number = 2
ORDER BY
  e.snap_id
/

exec runStats_pkg.rs_stop(p_output=&gt;'WORKLOAD');
</pre>
<p><strong>Workload Results</strong></p>
<p>The following are the results from three tests run one right after another. In each case the LAG is faster and does less work. In the third run a I reversed the order just to see if running either one first made any difference.</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; Run1 ran in 118 hsecs
Run2 ran in 11 hsecs
run 1 ran in 1072.73% of the time

Name                                            Run1        Run2        Diff
STAT...sorts (memory)                              2           3           1
STAT...physical reads                             29           0         -29
STAT...physical reads cache                       29           0         -29
STAT...CPU used by this session                   89          13         -76
STAT...Elapsed Time                              121          14        -107
STAT...redo size                               4,568       4,816         248
STAT...sorts (rows)                            5,860      11,707       5,847
STAT...session logical reads                 170,866      19,517    -151,349

Run1 latches total versus runs -- difference and pct
Run1        Run2        Diff       Pct
1,793,976     135,443  -1,658,533  1,324.52%

PL/SQL procedure successfully completed.

SQL&gt;

SQL&gt; Run1 ran in 85 hsecs
Run2 ran in 24 hsecs
run 1 ran in 354.17% of the time

Name                                            Run1        Run2        Diff
STAT...recursive cpu usage                         3           2          -1
STAT...sorts (memory)                              2           3           1
STAT...physical reads cache                        8           0          -8
STAT...physical reads                              8           0          -8
STAT...CPU used by this session                   75          25         -50
STAT...Elapsed Time                               88          28         -60
STAT...redo size                               5,952       5,108        -844
STAT...sorts (rows)                            5,861      11,709       5,848
STAT...session logical reads                 170,942      19,546    -151,396

Run1 latches total versus runs -- difference and pct
Run1        Run2        Diff       Pct
1,895,158     701,188  -1,193,970    270.28%

PL/SQL procedure successfully completed.

SQL&gt;

SQL&gt; Run1 ran in 24 hsecs
Run2 ran in 88 hsecs
run 1 ran in 27.27% of the time

Name                                            Run1        Run2        Diff
STAT...sorts (memory)                              3           2          -1
STAT...recursive cpu usage                         2           4           2
STAT...Elapsed Time                               28          90          62
STAT...CPU used by this session                   25          90          65
STAT...redo size                               4,288       5,908       1,620
STAT...sorts (rows)                           11,709       5,861      -5,848
STAT...session logical reads                  19,500     170,948     151,448

Run1 latches total versus runs -- difference and pct
Run1        Run2        Diff       Pct
510,514   2,151,923   1,641,409     23.72%

PL/SQL procedure successfully completed.

SQL&gt;
</pre>
<p><strong>Caveats</strong></p>
<p>The biggest problem with using the LAG function is to insure that the row set that it operates on is complete. This means that the leading row prior to the first row used in the result set must be available. This usually means that an inline view or a with statement must be used to insure that the resulting query has a prior row to work with. The following example will try to illustrate this. In the first case the LAG function is calculated as part of a single query. The where clause restricts the data to a specific range of snap_ids and the resulting lag entry is incorrect for the first row:</p>
<pre class="brush: sql; title: ; notranslate">
select
  snap_id,
  wait_class,
  total_waits_fg AS waits_fg,
  total_waits_fg - LAG(total_waits_fg,1,0)
  OVER(PARTITION BY dbid, instance_number, event_id, wait_class_id
    ORDER BY snap_id) AS waits_fg_lag
from
  dba_hist_system_event
where
  snap_id between 28452 and 28462
  and wait_class = 'Commit'
  and instance_number = 1
order by
  snap_id
/
</pre>
<pre class="brush: plain; title: ; notranslate">
   SNAP_ID WAIT_CLASS                                         WAITS_FG WAITS_FG_LAG
---------- ------------------------------------------------ ---------- ------------
     28452 Commit                                              1241804      1241804
     28453 Commit                                              1244080         2276
     28454 Commit                                              1246347         2267
     28455 Commit                                              1248675         2328
     28456 Commit                                              1250995         2320
     28457 Commit                                              1253477         2482
     28458 Commit                                              1255821         2344
     28459 Commit                                              1258202         2381
     28460 Commit                                              1260383         2181
     28461 Commit                                              1262600         2217
     28462 Commit                                              1264982         2382

11 rows selected.

SQL&gt;
</pre>
<p>The next example uses an inline view to allow the LAG function to have the row prior to the first row available to operate on:</p>
<pre class="brush: sql; title: ; notranslate">
compute sum of waits_fg_lag on wait_class;
break on report;
select *
from (
  select
    snap_id,
    wait_class,
    total_waits_fg AS waits_fg,
    total_waits_fg - LAG(total_waits_fg,1,0)
      OVER(PARTITION BY dbid, instance_number, event_id, wait_class_id
      ORDER BY snap_id) AS waits_fg_lag
from
  dba_hist_system_event
where
  instance_number = 1
  and wait_class = 'Commit'
)
where
  snap_id between (28452 + 1) and 28462
order by
  snap_id
/
</pre>
<pre class="brush: plain; title: ; notranslate">
   SNAP_ID WAIT_CLASS                                         WAITS_FG WAITS_FG_LAG
---------- ------------------------------------------------ ---------- ------------
     28453 Commit                                              1244080         2276
     28454 Commit                                              1246347         2267
     28455 Commit                                              1248675         2328
     28456 Commit                                              1250995         2320
     28457 Commit                                              1253477         2482
     28458 Commit                                              1255821         2344
     28459 Commit                                              1258202         2381
     28460 Commit                                              1260383         2181
     28461 Commit                                              1262600         2217
     28462 Commit                                              1264982         2382

10 rows selected.

SQL&gt;
</pre>
<p>In this case the lag result for the first row is correct. Again, this is because the row prior to the first snap_id is available to the LAG function.</p>
<p><strong>Conclusion</strong></p>
<p>The LAG function is much more efficient in these tests than the self-join. The session logical reads average about 19,500 for the lag test and around 171,000 for the self-join test. The run time is always less for the lag test and the self-join test seems particularly sensitive to the benefits of caching when run continually. When initially run the time to run was significantly worse (see <a title="Full Runstats Test" href="http://www.appsdba.com/scripts/lag_runstats.txt">Full Runstats Test</a>):</p>
<pre class="brush: plain; title: ; notranslate">
Run1 ran in 8296 hsecs

Run2 ran in 1913 hsecs

run 1 ran in 433.66% of the time
</pre>
<p>The only disadvantage is the more care must be taken to code the query in such a way that the row prior to the first row wanted is available to the LAG function.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=383</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DBFS_HS &#8211; Database Hierarchical Storage, Part 2</title>
		<link>http://www.appsdba.com/blog/?p=340</link>
		<comments>http://www.appsdba.com/blog/?p=340#comments</comments>
		<pubDate>Tue, 21 Jun 2011 06:14:40 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Oracle DBA]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=340</guid>
		<description><![CDATA[In part 1 we set up a hierarchical store under the user hstest, created a table with SecureFile LOBs, and archived 30 SecureFiles. So what&#8217;s going on under the covers and how do we retrieve the data? Is the data even really out of the database? In this article I will try to answer these [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.appsdba.com/blog/?p=302">part 1</a> we set up a hierarchical store under the user hstest, created a table with SecureFile LOBs, and archived 30 SecureFiles. So what&#8217;s going on under the covers and how do we retrieve the data? Is the data even really out of the database? In this article I will try to answer these questions as we continue to explore our hierarchical store.</p>
<p><strong>How it all works</strong></p>
<p>At the simplest level the hierarchical store provides various APIs to accomplish a put, a get, and some informational queries. Intermixed in these functions are the ability to create &#8220;links&#8221; to archived data such that a query of an archived SecureFile LOB that is no longer in database storage will be retrieved without application intervention (i.e. application transparency). The mechanism of a put involves moving the SecureFile LOB to a cached staging area (i.e. the cache table) until it can be archived out to the store&#8217;s defined storage media. Once archived it may be eligible to be &#8220;flushed&#8221; from the cache table in the database and therefore no longer reside in database storage. Once SecureFile LOB&#8217;s are moved to a store cache, or really staging, table they are eventually written to the store&#8217;s storage media in batches or &#8220;tarballs&#8221;. The size of these tarballs is controlled by a property defined for the store in the DBFS_HS$_STOREPROPERTIES table. If a &#8220;get&#8221; is issued and the SecureFile LOB is in the cache table then it can be retrieved directly. If not then the SecureFile LOB must be recalled from the tarball and written back into the SecureFile LOB&#8217;s row in the cache table.</p>
<p>This raises a question about storage. Ideally you would expect to see the cache table steady state at some fairly constant size as the rate of archiving and retrieval evens out. But it seems pretty obvious that the cache table is a good candidate for a dedicated tablespace. Since its space usage is not necessarily predictable it would be nice to keep it separate from other objects so that it&#8217;s size could be capped and not allowed to grow uncontrollably. It&#8217;s not clear if the cache table could be partitioned, but this would probably only be practical if it was very large. The partitioning scheme would also need to be set in a way that new and old SecureFile LOBs were being read and written to from each partition in order to insure that space was reused. The cache table also seems to be a good candidate for a second tier of storage. If the source table(s) are on a primary storage tier then clearly the cache table is not going to need to meet the same performance criteria, otherwise why archive? Since the actual store will be on a media outside the database this raises the possibility of having at least three storage tiers.</p>
<p><strong>Database Objects</strong></p>
<p>Next let’s look at what objects have been created. The following SYS dictionary tables exist to support dbms_dbfs:</p>
<p><strong> </strong></p>
<ul>
<li>DBFS_HS$_BACKUPFILETABLE</li>
<li>DBFS_HS$_CONTENTFILEMAPTBL</li>
<li>DBFS_HS$_FS</li>
<li>DBFS_HS$_PROPERTY</li>
<li>DBFS_HS$_SFLOCATORTABLE</li>
<li>DBFS_HS$_STORECOMMANDS</li>
<li>DBFS_HS$_STOREID2POLICYCTX</li>
<li>DBFS_HS$_STOREIDTABLE</li>
<li>DBFS_HS$_STOREPROPERTIES</li>
<li>DBFS_SFS$_FS</li>
<li>DBFS_SFS$_FST</li>
<li>DBFS_SFS$_FSTO</li>
<li>DBFS_SFS$_FSTP</li>
<li>DBFS_SFS$_SNAP</li>
<li>DBFS_SFS$_TAB</li>
<li>DBFS_SFS$_VOL</li>
<li>DBFS$_MOUNTS</li>
<li>DBFS$_STATS</li>
<li>DBFS$_STORES</li>
</ul>
<p>Additionally for each store created the following tables are created in the SYS schema:</p>
<ul>
<li>HS$AT&lt;dbname&gt;&lt;seq&gt;</li>
<li>HS$CT&lt;dbname&gt;&lt;seq&gt;</li>
<li>HS$DB&lt;dbname&gt;&lt;seq&gt;</li>
<li>HS$DT&lt;dbname&gt;&lt;seq&gt;</li>
<li>HS$JT&lt;dbname&gt;&lt;seq&gt;</li>
<li>HS$TT&lt;dbname&gt;&lt;seq&gt;</li>
</ul>
<p>When a store is created running the dbms_dbfs_hs.createStore procedure a table is created from the &#8220;tblname&#8221; input parameter. This table is used as a metadata table and stores the SecureFile LOB in the &#8220;filedata&#8221; column. A second table is also created with the name in the format of SFS$_FSTP_&lt;seq&gt;. This table holds more information about how the SecureFile LOB is archived and provides the gateway into the SYS metadata tables.</p>
<p>A view is also created with the name in the format of VSFS$_&lt;seq&gt; which exposes store based metadata about the archived SecureFile LOB.</p>
<p>In my database the following tables and view have been created:</p>
<p><a href="http://www.appsdba.com/blog/wp-content/uploads/2011/06/tables.jpg"><img class="size-full wp-image-369 aligncenter" src="http://www.appsdba.com/blog/wp-content/uploads/2011/06/tables.jpg" alt="" width="261" height="304" /></a><strong>Store View</strong></p>
<p>The following view can be used to provide a mapping between the archived SecureFile LOB and it&#8217;s location in the store and cache. A separate view is required for each store due to the use of separate cache and metadata tables for each store.</p>
<pre class="brush: sql; title: ; notranslate">
create or replace force view hs_store_vas
select
  c.pathname AS path,
  c.item AS name,
  c.std_guid AS guid,
  sf2.propvalue AS file_size,
  dbms_lob.getlength(c.filedata) AS cache_size,
  sf1.propvalue AS contentid,
  l.tarballid,
  b.backupfilename,
  st.storeowner,
  st.storename
from
  hstest.hs_cache c,
  hstest.sfs$_fstp_12 sf1,
  hstest.sfs$_fstp_12 sf2,
  sys.dbfs_hs$_contentfnmaptbl m,
  sys.dbfs_hs$_sflocatortable l,
  sys.dbfs_hs$_backupfiletable b,
  sys.dbfs_hs$_storeidtable st
where
  c.std_guid = sf1.std_guid
  and c.pathtype = 1
  and sf1.propname = 'HS:CONTENTID'
  and sf1.propvalue = m.contentfilename(+)
  and sf1.std_guid = sf2.std_guid
  and sf2.propname = 'HS:FILESIZE'
  and m.archiverefid = l.archiverefid(+)
  and l.tarballid = b.tarballid(+)
  and b.storeid = st.storeid(+);
</pre>
<p><strong>Usage Examples</strong></p>
<p>Now that everything is setup let&#8217;s walk through some examples of how DBFS HS works. First let&#8217;s look at what we have. In part 1 of this series I archived 30 SecureFile LOBs and that created one &#8220;tarball&#8221; operating system file:</p>
<pre class="brush: plain; title: ; notranslate">
380:oracle@testvm:/ora_src/bkup [db11g]
$ ls -lrt
total 8212
-rw-r--r-- 1 oracle oinstall    2136 Jun  6 23:46 Oracle_Disk_SBT_Catalog
-rw-r--r-- 1 oracle oinstall 8388616 Jun  6 23:46 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
381:oracle@testvm:/ora_src/bkup [db11g]
</pre>
<p>Now we&#8217;ll archive 15 more SecureFile LOBs, but we&#8217;ll just start at the beginning to show that if the SecureFile LOB has already been archived then re-archiving it does not invoke an error:</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; SET SERVEROUTPUT ON;
DECLARE
  v_mountpoint         VARCHAR2(32) := '/hs_store/';
  v_LOB                BLOB;
  v_LOBsize            NUMBER;
  v_debug              CHAR(1) := 'N';
BEGIN
  FOR arch_rec IN
  (
    SELECT hs.* FROM hs_lobtable hs
    where dbms_lob.getlength(hs.lobcol) != 0
    and rownum &lt;= 45   )   LOOP     BEGIN       SELECT hs.lobcol       INTO v_LOB       FROM hs_lobtable hs       WHERE hs.id = arch_rec.id FOR UPDATE;       --       v_LOBsize := SYS.DBMS_LOB.GETLENGTH(v_LOB);       DBMS_OUTPUT.PUT_LINE('Archive ID: ' || arch_rec.id);       DBMS_OUTPUT.PUT_LINE('LOB size: ' || v_LOBsize);       --       -- Write the LOB to the store       --       DBMS_LOB.MOVE_TO_DBFS_LINK (         lob_loc =&gt; v_LOB,
        storage_path =&gt; v_mountpoint || arch_rec.id,
        flags =&gt; DBMS_LOB.DBFS_LINK_NOCACHE);
      --
      COMMIT;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
    END;
  END LOOP;
END;
/
SQL&gt;   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25

26   27   28   29   30   31   32   33   34   35   36   37   38   39

Archive ID: 1
LOB size: 16384
Archive ID: 2
LOB size: 16384
Archive ID: 3
LOB size: 16384
Archive ID: 4
LOB size: 16384
Archive ID: 5
LOB size: 16384
Archive ID: 6
LOB size: 16384
Archive ID: 7
LOB size: 16384
Archive ID: 8
LOB size: 16384
Archive ID: 9
LOB size: 16384
Archive ID: 10
LOB size: 16384
Archive ID: 11
LOB size: 16384
Archive ID: 12
LOB size: 16384
Archive ID: 13
LOB size: 16384
Archive ID: 14
LOB size: 16384
Archive ID: 15
LOB size: 16384
Archive ID: 16
LOB size: 16384
Archive ID: 17
LOB size: 16384
Archive ID: 18
LOB size: 16384
Archive ID: 19
LOB size: 16384
Archive ID: 20
LOB size: 16384
Archive ID: 21
LOB size: 16384
Archive ID: 22
LOB size: 16384
Archive ID: 23
LOB size: 16384
Archive ID: 24
LOB size: 16384
Archive ID: 25
LOB size: 16384
Archive ID: 26
LOB size: 16384
Archive ID: 27
LOB size: 16384
Archive ID: 28
LOB size: 16384
Archive ID: 29
LOB size: 16384
Archive ID: 30
LOB size: 16384
Archive ID: 31
LOB size: 16384
Archive ID: 32
LOB size: 16384
Archive ID: 33
LOB size: 16384
Archive ID: 34
LOB size: 16384
Archive ID: 35
LOB size: 16384
Archive ID: 36
LOB size: 16384
Archive ID: 37
LOB size: 16384
Archive ID: 38
LOB size: 16384
Archive ID: 39
LOB size: 16384
Archive ID: 40
LOB size: 16384
Archive ID: 41
LOB size: 16384
Archive ID: 42
LOB size: 16384
Archive ID: 43
LOB size: 16384
Archive ID: 44
LOB size: 16384
Archive ID: 45
LOB size: 16384

PL/SQL procedure successfully completed.

SQL&gt;
</pre>
<p>Now let&#8217;s run a store push and see if we&#8217;ve create another archive file:</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; DECLARE
  store_name varchar2(32) := 'HS_STORE';
BEGIN
  dbms_dbfs_hs.storePush(store_name) ;
  commit ;
END;
/  2    3    4    5    6    7

PL/SQL procedure successfully completed.

SQL&gt; !ls -lrt
total 16420
-rw-r--r-- 1 oracle oinstall 8388616 Jun  6 23:46 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
-rw-r--r-- 1 oracle oinstall    3204 Jun 20 09:17 Oracle_Disk_SBT_Catalog
-rw-r--r-- 1 oracle oinstall 8388616 Jun 20 09:17 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

SQL&gt;
</pre>
<p>OK, we&#8217;ve created a new archive file in the OS. Let&#8217;s look at what our metadata view says about our store and the cache for the store:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; select name, cache_size, backupfilename from hs_store_v;

NAME            CACHE_SIZE BACKUPFILENAME
--------------- ---------- ------------------------------------------------------------
LOB1                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB10                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB11                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB12                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB13                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB14                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB15                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB16                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB17                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB18                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB19                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB2                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB20                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB21                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB22                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB23                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB24                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB25                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB26                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB27                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB28                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB29                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB3                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB30                    0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB4                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB5                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB6                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB7                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB8                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
LOB9                     0 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
31                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
32                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
33                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
34                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
35                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
36                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
37                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
38                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
39                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
40                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
41                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
42                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
43                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
44                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2
45                       0 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

45 rows selected.

SQL&gt;
</pre>
<p>It looks like all 45 of our SecureFile LOBs have been archived to a file and are not currently in the cache. Now let&#8217;s see if we can access one of the SecureFile LOBs:</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; SET SERVEROUTPUT ON;
DECLARE
  l_LOB                BLOB;
  l_buffer             RAW(4000);
  l_ctr                NUMBER := 1;
  l_amount             NUMBER := 100;
  l_id                 NUMBER := 45;
BEGIN
  SELECT hs.lobcol
  INTO l_LOB
  FROM hs_lobtable hs
  WHERE hs.id = l_id;
  --
  dbms_lob.read(l_LOB, l_amount, l_ctr, l_buffer);
  dbms_output.put_line( RAWTOHEX(l_buffer) );
END;
/SQL&gt;   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16
45506C45676E4761545861514265575641797571534A77687A4F79634D5A6E765771484867736C456B634C6845587466566377747A7A4745646A6774
4E7456704E69596857485A6B6146585767704D567275564D5A74417A616F41746C4874784B6A5061

PL/SQL procedure successfully completed.

SQL&gt;
</pre>
<p>We were able to read the first 100 bytes of the SecureFile LOB with name or id of &#8217;45&#8242;. If we query our metadata we now see:</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; select name, cache_size, backupfilename from hs_store_v where name = '45';

NAME            CACHE_SIZE BACKUPFILENAME
--------------- ---------- ------------------------------------------------------------
45                   16384 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

SQL&gt;
</pre>
<p>And now the cache_size shows the size of the SecureFile LOB. For those doubters out there I&#8217;ll rename the backup file and we&#8217;ll try accessing another SecureFile LOB:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; !ls -lrt
total 16420
-rw-r--r-- 1 oracle oinstall 8388616 Jun  6 23:46 __DB11G_1_A5180F78E736D02AE040A8C057011B2C_1
-rw-r--r-- 1 oracle oinstall    3204 Jun 20 09:17 Oracle_Disk_SBT_Catalog
-rw-r--r-- 1 oracle oinstall 8388616 Jun 20 09:17 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

SQL&gt; !mv __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2.BAK

SQL&gt; DECLARE
  l_LOB                BLOB;
  l_buffer             RAW(4000);
  l_ctr                NUMBER := 1;
  l_amount             NUMBER := 100;
  l_id                 NUMBER := 44;
BEGIN
  SELECT hs.lobcol
  INTO l_LOB
  FROM hs_lobtable hs
  WHERE hs.id = l_id;
  --
  dbms_lob.read(l_LOB, l_amount, l_ctr, l_buffer);
  dbms_output.put_line( RAWTOHEX(l_buffer) );
END;
/  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16
DECLARE
*
ERROR at line 1:
ORA-19507: failed to retrieve sequential file, handle=&quot;__DB11G_2_A6248CC964C16A45E040A8C0570111A4_2&quot;, parms=&quot;&quot;
ORA-27029: skgfrtrv: sbtrestore returned error
ORA-19511: Error received from media manager layer, error text:
sbtpvt_open_input: file /ora_src/bkup/__DB11G_2_A6248CC964C16A45E040A8C0570111A4_2 does not exist or cannot be
accessed, errno = 2
ORA-06512: at &quot;SYS.DBMS_APBACKEND&quot;, line 60
ORA-06512: at &quot;SYS.DBMS_APBACKEND&quot;, line 1378
ORA-06512: at &quot;SYS.DBMS_DBFS_HS&quot;, line 1042
ORA-06512: at &quot;SYS.DBMS_DBFS_HS&quot;, line 1203
ORA-06512: at &quot;SYS.DBMS_DBFS_HS&quot;, line 1481
ORA-06512: at &quot;SYS.DBMS_DBFS_HS&quot;, line 1592
ORA-06512: at line 1
ORA-06512: at &quot;SYS.DBMS_DBFS_CONTENT&quot;, line 3108
ORA-06512: at &quot;SYS.DBMS_LOB_AM_PRIVATE&quot;, line 65
ORA-06512: at line 1
ORA-06512: at &quot;SYS.DBMS_LOB&quot;, line 1056
ORA-06512: at line 13
</pre>
<p>The access failed because the archive file could not be found. This proves that the database is capable of accessing secondary storage to transparently retrieve the SecureFile LOB. Now we&#8217;ll rename the file back and see if we can successfully retrieve the SecureFile LOB:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; !mv __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2.BAK __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

SQL&gt; DECLARE
  l_LOB                BLOB;
  l_buffer             RAW(4000);
  l_ctr                NUMBER := 1;
  l_amount             NUMBER := 100;
  l_id                 NUMBER := 44;
BEGIN
  SELECT hs.lobcol
  INTO l_LOB
  FROM hs_lobtable hs
  WHERE hs.id = l_id;
  --
  dbms_lob.read(l_LOB, l_amount, l_ctr, l_buffer);
  dbms_output.put_line( RAWTOHEX(l_buffer) );
END;
/  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16
6F4A6A796978784F576F54524261634979444256535747644772655952614D4E6646735657675545566B48577762596C43707162426F7975414F5841
594B6242754D6E5948784E546E49724F78664F4968564154504C4966555156757277475077757544

PL/SQL procedure successfully completed.

SQL&gt; select name, cache_size, backupfilename from hs_store_v where name = '44';

NAME            CACHE_SIZE BACKUPFILENAME
--------------- ---------- ------------------------------------------------------------
44                   16384 __DB11G_2_A6248CC964C16A45E040A8C0570111A4_2

SQL&gt;
</pre>
<p>And we see that we can indeed access the SecureFile LOB and that it has been retrieved back into the cache.</p>
<p>To wrap this up Oracle has made available a feature that can be used to move closer to an ILM environment. One that can transparently support multiple tiers of storage for SecureFile LOBs.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=340</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>DBFS_HS &#8211; Database Hierarchical Storage</title>
		<link>http://www.appsdba.com/blog/?p=302</link>
		<comments>http://www.appsdba.com/blog/?p=302#comments</comments>
		<pubDate>Tue, 07 Jun 2011 05:03:12 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Oracle DBA]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=302</guid>
		<description><![CDATA[Oracle delivered the database file system in 11gR2, but it also slipped in hierarchical storage as part of the feature. In 11.2.0.2 most of the bugs seem to have been worked out. The DBFS_HS package along with the DBMS_LOB package, and SecureFile LOBs delivers application transparent hierarchical storage. A sort of ILM if you will. [...]]]></description>
			<content:encoded><![CDATA[<p>Oracle delivered the database file system in 11gR2, but it also slipped in hierarchical storage as part of the feature. In 11.2.0.2 most of the bugs seem to have been worked out. The DBFS_HS package along with the DBMS_LOB package, and SecureFile LOBs delivers application transparent hierarchical storage. A sort of ILM if you will. This has been a while in coming but it finally seems to really work. I&#8217;ll walk through an example, and it&#8217;s sort of documented (not all quite there yet) in the Oracle documentation. So why is this important? Well there are some customers that have chosen to store a lot of unstructured data in SecureFiles and don&#8217;t want to keep it all in premium storage. DBFS_HS provides a mechanism to move that data to different storage tiers. Initially Oracle is supporting RMAN based archiving and Amazon S3.</p>
<p>The following will show the setup on a Linux VM running Oracle 11.2.0.2 using RMAN with disk based SBT (see the post <a href="http://www.appsdba.com/blog/?p=205">RMAN Tape Simulation</a>). In future posts I&#8217;ll explore how it works under the covers and what you can do with it.</p>
<p>I found the examples in the <a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e18294/adlob_hierarch.htm#g100">SecureFiles and Large Object&#8217;s Developer Guide</a> to be a little cryptic so hopefully this example will do better.</p>
<pre class="brush: sql; title: ; notranslate">
connect / as sysdba

create tablespace hs_tab
datafile
 '/ora_src/oradata/db11g/hs_tab01.dbf'
 size 10m autoextend on next 10m maxsize 2000m;

create user hstest identified by hstest
default tablespace hs_tab
temporary tablespace temp
quota unlimited on hs_tab;

grant create session to hstest;
grant alter session to hstest;
--
grant dbfs_role to hstest;
grant scheduler_admin to hstest;
--
grant create procedure to hstest;
grant create sequence to hstest;
grant create table to hstest;
grant create trigger to hstest;
grant create view to hstest;
--
grant select any dictionary to hstest;
grant select any table to hstest;
--
-- Run the following:
--
connect hstest/hstest
--
declare
 storename varchar2(32) ;
 tblname varchar2(30) ;
 tbsname varchar2(30) ;
 lob_cache_quota number := 0.8 ;
 cachesz number ;
 ots number ;
begin
 cachesz := (100 * 1048576);  -- Minimum size? 3 MB or less errors
 ots := (10 * 1048576);
 storename := 'HS_STORE' ;
 tblname := 'HS_CACHE' ;
 tbsname := 'HS_TAB' ; -- Substitute a valid tablespace name
 --
 -- Create the store.
 -- Here tbsname is the tablespace used for the store,
 -- tblname is the table holding all the store entities,
 -- cachesz is the space used by the store to cache content
 --   in the tablespace,
 -- lob_cache_quota is the fraction of cachesz allocated
 --   to level-1 cache and
 -- ots is minimum amount of content that will be accumulated
 --   in level-2 cache before being stored in AmazonS3
 --
 dbms_dbfs_hs.createStore(
 storename,
 dbms_dbfs_hs.STORETYPE_TAPE,
 tblname, tbsname, cachesz,
 lob_cache_quota, ots) ;
 --
 dbms_dbfs_hs.setstoreproperty(
 storename,
 dbms_dbfs_hs.PROPNAME_SBTLIBRARY,
 'oracle.disksbt, ENV=(BACKUP_DIR=/ora_src/bkup)' );
 --
 dbms_dbfs_hs.setstoreproperty(
 storename,
 dbms_dbfs_hs.PROPNAME_MEDIAPOOL,
 '0') ;  -- Substitute valid value
 --
 dbms_dbfs_hs.setstoreproperty(
 storename,
 dbms_dbfs_hs.PROPNAME_COMPRESSLEVEL,
 'NONE') ;
 --
 -- Insure that the store is streamable. According to Oracle
 -- this must be set to allow links to work correctly.
 --
 dbms_dbfs_hs.setstoreproperty(
 storename,
 dbms_dbfs_hs.PROPNAME_STREAMABLE,
 'TRUE') ;
 --
 -- Please refer to DBMS_DBFS_CONTENT documentation
 -- for details about this method
 --
 dbms_dbfs_content.registerstore(
 storename,
 'HS',
 'dbms_dbfs_hs') ;
 --
 -- Please refer to DBMS_DBFS_CONTENT documentation
 -- for details about this method
 --
 dbms_dbfs_content.mountstore(storename, 'hs_store') ;
 --
 commit;
end ;
/
</pre>
<p>That will get you a DBFS store that will archive to the backup directory /ora_src/bkup. You may want to change that to fit your system, but these examples use that directory. The next set of statements have to be run because the create store commands don&#8217;t properly insert the backup directory since we&#8217;re cheating and using the disk sbt for RMAN.</p>
<pre class="brush: sql; title: ; notranslate">
connect / as sysdba

INSERT INTO SYS.DBFS_HS$_STORECOMMANDS
SELECT STOREID, '''ENV=(BACKUP_DIR=/ora_src/bkup)''', 1
FROM SYS.DBFS_HS$_STOREIDTABLE WHERE STORENAME = 'HS_STORE';

INSERT INTO SYS.DBFS_HS$_STORECOMMANDS
SELECT STOREID, '''ENV=(BACKUP_DIR=/ora_src/bkup)''', 2
FROM SYS.DBFS_HS$_STOREIDTABLE WHERE STORENAME = 'HS_STORE';

COMMIT;
</pre>
<p>Now we&#8217;ll create a directory so we can use the store:</p>
<pre class="brush: sql; title: ; notranslate">
connect hstest/hstest
--
declare
 v_properties  dbms_dbfs_content_properties_t;
begin
 v_properties := NULL;
 dbms_dbfs_content.createDirectory(
 path =&gt; '/hs_store',
 properties =&gt; v_properties,
 store_name =&gt; 'HS_STORE' ) ;
 --
 commit;
end;
/
</pre>
<p>So we&#8217;ve got a hierarchical store defined for the user hstest and it will archive to the operating system directory /ora_src/bkup. Now we need a table with SecureFile LOB&#8217;s to test it out.</p>
<pre class="brush: sql; title: ; notranslate">
  CREATE TABLE HS_LOBTABLE
   (	&quot;ID&quot; NUMBER,
	&quot;LASTACCESSDATE&quot; DATE,
	&quot;CONTENTTYPE&quot; NUMBER,
	&quot;LOBCOL&quot; BLOB,
	 PRIMARY KEY (&quot;ID&quot;)
  USING INDEX COMPUTE STATISTICS
  TABLESPACE &quot;HS_TAB&quot;  ENABLE
   ) SEGMENT CREATION IMMEDIATE
  NOCOMPRESS LOGGING
  TABLESPACE &quot;HS_TAB&quot;
 LOB (&quot;LOBCOL&quot;) STORE AS SECUREFILE (
  TABLESPACE &quot;HS_TAB&quot; ENABLE STORAGE IN ROW CHUNK 32768 RETENTION AUTO
  CACHE LOGGING  NOCOMPRESS  KEEP_DUPLICATES
  ) ;
--
-- Add sequence
--
CREATE SEQUENCE hs_seq;

-
-- Load 100 16K LOBs
--
set serveroutput on;
declare
  v_buffer             RAW(16384);
  v_tmpLOB             BLOB;
  v_amount             NUMBER := 16384;
  --
  v_lobnum             NUMBER := 100;
begin
  FOR lobctr IN 1..v_lobnum LOOP
    DBMS_LOB.CREATETEMPORARY(
      lob_loc =&gt; v_tmpLOB,
      cache =&gt; TRUE,
      dur =&gt; DBMS_LOB.CALL);
    --
    DBMS_LOB.OPEN(
      lob_loc =&gt; v_tmpLOB,
      open_mode =&gt; DBMS_LOB.LOB_READWRITE);
    --
    v_buffer := NULL;
    --
    FOR i IN 1..v_amount LOOP
      v_buffer := v_buffer || utl_raw.cast_to_raw(dbms_random.string('a',1));
    END LOOP;
    --
    dbms_lob.write(v_tmpLOB, v_amount, 1, v_buffer);
    --
    dbms_output.put_line('New LOB length: ' || dbms_lob.getlength(v_tmpLOB));
    --
    INSERT INTO HS_LOBTABLE
    VALUES(hs_seq.nextval, SYSDATE, 1, v_tmpLOB);
    --
    COMMIT;
    DBMS_LOB.CLOSE(lob_loc =&gt; v_tmpLOB);
    --
  END LOOP;
END;
/
</pre>
<p>If you&#8217;ve made it this far then all that&#8217;s left is to archive some of the SecureFile LOBs. When I set this up I only archived 30 SecureFile LOBs so I had to run a &#8220;store push&#8221; to force the database to archive the &#8220;cached&#8221; LOBs to the /ora_src/bkup directory. I&#8217;ll spend some more time on what&#8217;s going on under the covers in Part 2.</p>
<pre class="brush: sql; title: ; notranslate">
SET SERVEROUTPUT ON;
DECLARE
 v_mountpoint         VARCHAR2(32) := '/hs_store/';
 --
 v_store              VARCHAR2(32) := 'HS_STORE';
 v_LOB                BLOB;
 v_LOBsize            NUMBER;
 --
 prop1                dbms_dbfs_content_properties_t ;
 newcontent           BLOB;
BEGIN
 FOR arch_rec IN
 (
 SELECT id FROM hs_lobtable
 WHERE rownum &lt;= 30
 )
 LOOP
 BEGIN
 SELECT lobcol
 INTO v_LOB
 FROM hs_lobtable
 WHERE id = arch_rec.id FOR UPDATE;
 --
 v_LOBsize := SYS.DBMS_LOB.GETLENGTH(v_LOB);
 DBMS_OUTPUT.PUT_LINE('Archive id: ' || arch_rec.id);
 DBMS_OUTPUT.PUT_LINE('LOB size: ' || v_LOBsize);
 --
 -- Write the LOB to the store
 --
 DBMS_LOB.MOVE_TO_DBFS_LINK (
 lob_loc =&gt; v_LOB,
 storage_path =&gt; v_mountpoint || 'LOB' || arch_rec.id,
 flags =&gt; DBMS_LOB.DBFS_LINK_NOCACHE);
 --
 COMMIT;
 EXCEPTION
 WHEN OTHERS THEN
 ROLLBACK;
 DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
 RAISE;
 END;
 END LOOP;
END;
/
--
-- This will archive LOBs in the &quot;stage table&quot; to the store. It will leave the LOB
-- in the staging table unless a flush is run.
--
--
DECLARE
 store_name varchar2(32) := 'HS_STORE';
BEGIN
 dbms_dbfs_hs.storePush(store_name) ;
 commit ;
END;
/
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=302</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ORACLE_UNQNAME</title>
		<link>http://www.appsdba.com/blog/?p=305</link>
		<comments>http://www.appsdba.com/blog/?p=305#comments</comments>
		<pubDate>Mon, 06 Jun 2011 04:02:31 +0000</pubDate>
		<dc:creator>Andy Rivenes</dc:creator>
				<category><![CDATA[Oracle DBA]]></category>

		<guid isPermaLink="false">http://www.appsdba.com/blog/?p=305</guid>
		<description><![CDATA[New in 11.2 is the environment variable ORACLE_UNQNAME and it is used with the OEM dbconsole. The following are some tests on an 11.2.0.2 Linux system: However, when working on an 11.2.0.2 DataGuard database with db_unique_name set I had to have ORACLE_UNQNAME set as well. Also note that in the message from the dbconsole that [...]]]></description>
			<content:encoded><![CDATA[<p>New in 11.2 is the environment variable ORACLE_UNQNAME and it is used with the OEM dbconsole. The following are some tests on an 11.2.0.2 Linux system:</p>
<pre class="brush: plain; title: ; notranslate">
$ echo $ORACLE_SID
db11g
314:oracle@testvm:/home/oracle [db11g]
$ echo $ORACLE_UNQNAME
db11g
315:oracle@testvm:/home/oracle [db11g]
$ emctl status dbconsole
Oracle Enterprise Manager 11g Database Control Release 11.2.0.2.0
Copyright (c) 1996, 2010 Oracle Corporation.  All rights reserved.

https://testvm:1158/em/console/aboutApplication

Oracle Enterprise Manager 11g is running.
------------------------------------------------------------------
Logs are generated in directory /app/local/oracle/product/11.2.0.2/db_1/testvm_db11g/sysman/log
316:oracle@testvm:/home/oracle [db11g]
$ unset ORACLE_SID
317:oracle@testvm:/home/oracle []
$ emctl status dbconsole
Oracle Enterprise Manager 11g Database Control Release 11.2.0.2.0
Copyright (c) 1996, 2010 Oracle Corporation.  All rights reserved.

https://testvm:1158/em/console/aboutApplication

Oracle Enterprise Manager 11g is running.
------------------------------------------------------------------
Logs are generated in directory /app/local/oracle/product/11.2.0.2/db_1/testvm_db11g/sysman/log
318:oracle@testvm:/home/oracle []
$ unset ORACLE_UNQNAME
319:oracle@testvm:/home/oracle []
$ emctl status dbconsole
Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name.
320:oracle@testvm:/home/oracle []
$ export ORACLE_SID=db11g
321:oracle@testvm:/home/oracle [db11g]
$ emctl status dbconsole
Oracle Enterprise Manager 11g Database Control Release 11.2.0.2.0
Copyright (c) 1996, 2010 Oracle Corporation.  All rights reserved.

https://testvm:1158/em/console/aboutApplication

Oracle Enterprise Manager 11g is running.
------------------------------------------------------------------
Logs are generated in directory /app/local/oracle/product/11.2.0.2/db_1/testvm_db11g/sysman/log
322:oracle@testvm:/home/oracle [db11g]
$
</pre>
<p>However, when working on an 11.2.0.2 DataGuard database with db_unique_name set I had to have ORACLE_UNQNAME set as well. Also note that in the message from the dbconsole that the OEM directory is $ORACLE_HOME/testvm_db11g which is the hostname and SID, but when using db_unique_name this won&#8217;t necessarily be the same. Hence I suspect, and will need to run some more tests to prove, that this was added to handle the situation where the SID and the unique name are different.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appsdba.com/blog/?feed=rss2&#038;p=305</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

