<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Oracle database internals by Riyaj</title>
	<atom:link href="http://orainternals.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://orainternals.wordpress.com</link>
	<description>Discussions about Oracle performance tuning, Oracle internal &#38; E-business suite.</description>
	<lastBuildDate>Tue, 24 Nov 2009 20:47:04 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='orainternals.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/6d0a441ee61965db96ebb17e7bb69bff?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Oracle database internals by Riyaj</title>
		<link>http://orainternals.wordpress.com</link>
	</image>
			<item>
		<title>UKOUG 2009</title>
		<link>http://orainternals.wordpress.com/2009/11/24/ukoug-2009/</link>
		<comments>http://orainternals.wordpress.com/2009/11/24/ukoug-2009/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 20:46:25 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[Presentations]]></category>
		<category><![CDATA[RAC]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=617</guid>
		<description><![CDATA[
  Well, it is that time of the year !

  Few Presentations 

  I will be presenting two papers in Birmingham,  UK Oracle User Group Technology conference . My sessions are :

    Tuesday 10:55-11:55: Battle of the nodes: RAC Performance myths . 
    Wednesday 15:15-16:00: [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=617&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>
  Well, it is that time of the year !
</p>
<p><b>  Few Presentations </b></p>
<p>
  I will be presenting two papers in Birmingham, <a href="http://techandebs.ukoug.org/"> UK Oracle User Group Technology conference </a>. My sessions are :</p>
<p><OL><br />
  <LI> <a href="http://techandebs.ukoug.org/default.asp?p=3227&amp;dlgact=shwprs&amp;prs_prsid=3718&amp;day_dayid=33"> Tuesday 10:55-11:55: Battle of the nodes: RAC Performance myths </a>. </LI><br />
  <LI> <a href="http://techandebs.ukoug.org/default.asp?p=3227&amp;dlgact=shwprs&amp;prs_prsid=3717&amp;day_dayid=34"> Wednesday 15:15-16:00: Advanced performance issues: A close encounter with real world performance issues </a>.<br />
  </LI><br />
</OL></p>
<p>
   I will upload new versions of these presentations in this blog, few days after the conference. See you in Birmingham.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/617/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=617&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/11/24/ukoug-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>Is plan_hash_value a final say?</title>
		<link>http://orainternals.wordpress.com/2009/09/13/is-plan_hash_value-a-final-say/</link>
		<comments>http://orainternals.wordpress.com/2009/09/13/is-plan_hash_value-a-final-say/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 00:18:28 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[CBO]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[RAC]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gc traffic]]></category>
		<category><![CDATA[global cache CR]]></category>
		<category><![CDATA[global cache CUR]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[plan_hash_value]]></category>
		<category><![CDATA[scientific tuning]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=577</guid>
		<description><![CDATA[
  I was reviewing a performance issue with a client recently. Problem is that increased global cache waits causing application slowdown affecting few critical business functions. Using one of my script  gc_traffic.sql &#62; and graphing the results with Excel spreadsheet, it is established that there is a marked increase in GC traffic today [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=577&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>
  I was reviewing a performance issue with a client recently. Problem is that increased global cache waits causing application slowdown affecting few critical business functions. Using one of my script <a href="http://www.orainternals.com/viewfile.php?id=34"> gc_traffic.sql &gt;</a> and graphing the results with Excel spreadsheet, it is established that there is a marked increase in GC traffic today compared to week earlier. Similar jobs runs every day and so comparing two week days is sufficient to show the GC traffic increase. Graph is between total blocks and AWR snap time in 30 minutes interval. [Click the picture below to review the graph clearly.]
</p>

<a href='http://orainternals.wordpress.com/2009/09/13/is-plan_hash_value-a-final-say/gc-comparison/' title='gc comparison'><img width="150" height="102" src="http://orainternals.files.wordpress.com/2009/09/gc-comparison2.jpg?w=150&#038;h=102" class="attachment-thumbnail" alt="" title="gc comparison" /></a>

<p>
 Identifying the object creating this increased GC traffic is essential to identify root cause. We were able to quickly determine that this increase in GC traffic was localized around few SQL statements using ADDM and AWR reports. We decided to focus on one SQL with an obvious increase in elapsed time compared to prior week. So, first question asked, is there a change in the plan? plan_hash_value was reviewed and quickly determined that there is no change in the plan_hash_value.
</p>
<p>
Little bit of history, there were few changes performed by the vendor over the weekend as a part of few bug fixes. Vendor&#8217;s argument was that since there is no change to the plan_hash_value, SQL access plan did not change and so, this can&#8217;t be due to vendor changes. My Client&#8217;s argument was that there were no changes to the environment and problem started after the application changes.
</p>
<p>
  There are many different things that can go wrong without changes to the execution plan. We can ignore those conditions for now since (a) there has been no changes to the environment (b) no visible changes to the data (c) no error message and average CR recv time is consistent with prior weeks. Well, Let&#8217;s cut to the chase. It boiled down to a question &#8220;Can SQL plan change without a change in plan_hash_value?&#8221;. What do you think? Please answer in the poll below. <a name="pd_a_1986363"></a><div class="PDS_Poll" id="PDI_container1986363" style="display:inline-block;"></div><script type="text/javascript" language="javascript" charset="utf-8" src="http://static.polldaddy.com/p/1986363.js"></script>
		<noscript>
		<a href="http://answers.polldaddy.com/poll/1986363/">View This Poll</a><br/><span style="font-size:10px;"><a href="http://www.polldaddy.com">polls</a></span>
		</noscript>
</p>
<p><b> plan_hash_value and hash_value </b></p>
<p>
  Hash_value of a SQL statement is generated from the text of an SQL statement and plan_hash_value is generated from the execution plan of that SQL statement[ More accurately, from that child cursors' execution plan and exactly what is involved in generating plan_hash_value is not published]. It is a general belief that plan_hash_value will change even if there is a slightest change in the execution plan. But, that is not always the case!
</p>
<p><b> Test case </b></p>
<p> We will use a small table to explore this issue. </p>
<pre>
prompt Test case #1: Initial test case with index on columns (n1, n2).
prompt ==========
create table t1 (n1 number, n2 number, v1 varchar2(100));
create index t1_n1 on t1(n1,n2);

explain plan for select * from t1 where n1=:b1 and n2=:b2;
select * from table (dbms_xplan.display);
prompt plan hash value in this case is 626762252

Plan hash value: <b>626762252</b>
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |     1 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("N1"=TO_NUMBER(:B1) AND "N2"=TO_NUMBER(:B2))
</pre>
<p> So, we got the plan_hash_value as highlighted above. In the following test case we will recreate the index reordering the columns as (n2, n1).  </p>
<pre>
prompt Test case #2: Index with re-ordered columns
prompt ==========
drop index t1_n1;
create index t1_n1 on t1(n2,n1);

Plan hash value: <b>626762252</b>

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |     9   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |     9   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |  5298 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("N2"=TO_NUMBER(:B2) AND "N1"=TO_NUMBER(:B1))
</pre>
<p>
  Notice that in the test result above filter predicate changed reflecting index column reordering. But the plan_hash_value did not change. Point is that execution plan can change without a change in plan_hash_value (due to change in the underlying tables).
</p>
<p>
  Let&#8217;s modify that index dropping a column from the index in the next test case.
</p>
<pre>
prompt Test case #3: dropping a column from index t1_n1.

drop index t1_n1;
create index t1_n1 on t1(n1);

explain plan for select * from t1 where n1=:b1 and n2=:b2;

Plan hash value: 626762252

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |    41   (3)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |    41   (3)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |  2119 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("N2"=TO_NUMBER(:B2))
   2 - access("N1"=TO_NUMBER(:B1))
</pre>
<p>
  We see that predicates changed but the plan_hash_value did not change. In the test case below, we will modify index to be a function based index and test this SQL statement. There are also few more self-evident test cases below.
</p>
<pre>
prompt Test case #3: Index is a function based index. Still, no change in the plan_hash_value.

create index t1_n1 on t1(to_char(n1));
explain plan for select * from t1 where to_char(n1)=:b1 and n2=:b2;

Plan hash value: 626762252
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |   127   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |   127   (1)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |  2119 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("N2"=TO_NUMBER(:B2))
   2 - access(TO_CHAR("N1")=:B1)

prompt Test case #4: Different schema and same SQL. plan_hash_value did not change.

Plan hash value: 626762252
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |    78 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| T1    |     1 |    78 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |     3 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("N2"=TO_NUMBER(:B2))
   2 - access("N1"=TO_NUMBER(:B1))
</pre>
<p>
  plan_hash_value is also case sensitive for index names. In the test cases below, we will create case sensitive indices.
</p>
<pre>
prompt Test case #5: Lower case index_name.. plan_hash_value changed.
create index "t1_n1" on t1(n1,n2);
explain plan for select * from t1 where n1=:b1 and n2=:b2;

Plan hash value: 2252949961
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | t1_n1 |     1 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

prompt Test case #6: Upper case index_name.. plan_hash_value did not change.
create index "T1_N1" on t1(n1,n2);
explain plan for select * from t1 where n1=:b1 and n2=:b2;
Plan hash value: 626762252

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    53 |  4134 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1    |    53 |  4134 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1 |     1 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

prompt Test case #7: Space in the index name changes plan_hash_value though.
create index "T1_N1 " on t1(n1,n2);
explain plan for select * from t1 where n1=:b1 and n2=:b2;
Plan hash value: 1377541522
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |    53 |  4134 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1     |    53 |  4134 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_N1  |     1 |       |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
</pre>
<p><b> Summary </b></p>
<p>
   In summary, plan_hash_value is a very good indicator to see if the plan changed or not. Don&#8217;t get me wrong, I also use plan_hash_value, but in addition to comparing CPU time and elapsed time. Execution plan can change even when there is no change to the plan_hash_value. Salient points from these test cases are:</p>
<ol>
<li> Plan_hash_value is dependent upon partial execution plan not on complete execution plan. </li>
<li> If a predicate is moved from filter_predicate to access_predicate or vice-versa, it doesn&#8217;t affect plan_hash_value. </li>
<li> Changes in the parallelism of the queries does not affect plan_hash_value. For example, if a query used 4 parallel slaves today and 16 parallel slaves yesterday, that change is not visible through plan_hash_value. This behavior is expected as parallel_adaptive_multiuser can allocate slaves depending upon the state of that instance. </li>
<li> Plan_hash_value is case-sensitive to index/table names. Also sensitive to white-space characters. </li>
<li> Plan_hash_value is not sensitive to index types. For example, if the index type is a function based index as in our test case #4, as long as, index name did not change plan_hash_value will remain the same. </li>
<li> Plan_hash_value is not sensitive to schema either. SQL statement accessing different schemas can have same plan_hash_value too.</li>
</ol>
<p>
  Back to our problem. One of the index was recreated removing a column and caused optimizer to apply filter predicates at table level increasing number of accesses to table block tremendously, leading to more logical reads, more Global cache waits etc. This problem was amplified since this SQL was executed very frequently and concurrently from all RAC instances.
</p>
<p>
   In my client&#8217;s defense, this application change was tested thoroughly. But, alas, test data chosen for this performance test was not probing this specific issue. This performance issue did not show up in development. Essentially, chosen data in the performance benchmark suite was not an excellent choice.
</p>
<p>
   As they say in Gaelic language &#8220;Go raimh maith agat&#8221; to my client for allowing me to post this blog.<br />
   This can be read in traditional format in<br />
        <a href='http://orainternals.files.wordpress.com/2009/09/plan_hash_value_and_gc.pdf'>plan_hash_value_and_gc</a><br />
Update 1: Added the document and also corrected a typo.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/577/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/577/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/577/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/577/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/577/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/577/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/577/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/577/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/577/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/577/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=577&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/09/13/is-plan_hash_value-a-final-say/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>Exciting seminars in Dallas arena</title>
		<link>http://orainternals.wordpress.com/2009/08/21/exciting-seminars-in-dallas-arena/</link>
		<comments>http://orainternals.wordpress.com/2009/08/21/exciting-seminars-in-dallas-arena/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 14:54:52 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[CBO]]></category>
		<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[Presentations]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=566</guid>
		<description><![CDATA[   If you live in Dallas area, there are two very important seminars coming up:

 Tanel Poder is presenting his  Advanced Oracle troubleshooting seminar  on September 9-11, 2009.  . 
 Jonathan Lewis presenting two day seminar  cost based optimization and writing efficient SQL   on Oct 28 and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=566&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>   If you live in Dallas area, there are two very important seminars coming up:</p>
<ol>
<li> Tanel Poder is presenting his <a href="http://blog.tanelpoder.com/seminar/"> Advanced Oracle troubleshooting seminar </a> on September 9-11, 2009.  </b>. </li>
<li> Jonathan Lewis presenting two day seminar <a href="http://www.speak-tech.com/seminars"> cost based optimization and writing efficient SQL </a>  on Oct 28 and Oct 29 2009</li>
<p>.
 </ol>
<p>   These two gentlemen needs no introduction. <a href="http://www.tanelpoder.com"> Tanel Poder </a> is an expert in Oracle internals and <a href="http://www.jlcomp.demon.co.uk/"> Jonathan Lewis </a> is a Guru in Cost based optimization and writing efficient SQL.</p>
<p>   Tell them I sent ya <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Update: I just heard from Tanel and he is unable to make it to Dallas this September. He is rescheduling his seminar and I can&#8217;t wait for his seminar. I will update this blog with his rescheduled dates.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/566/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/566/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/566/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/566/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/566/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/566/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/566/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/566/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/566/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/566/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=566&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/08/21/exciting-seminars-in-dallas-arena/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>Shared pool freelists (and durations)</title>
		<link>http://orainternals.wordpress.com/2009/08/09/shared-pool-freelists-and-durations/</link>
		<comments>http://orainternals.wordpress.com/2009/08/09/shared-pool-freelists-and-durations/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 20:28:35 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[11g]]></category>
		<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[shared_pool]]></category>
		<category><![CDATA[bucket]]></category>
		<category><![CDATA[durations]]></category>
		<category><![CDATA[heapdump_freelist.ksh]]></category>
		<category><![CDATA[ksmchdur]]></category>
		<category><![CDATA[ksmchidx]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[performance logfile dump]]></category>
		<category><![CDATA[sga heap]]></category>
		<category><![CDATA[shared_pool_free_lists_9i.sql]]></category>
		<category><![CDATA[x$ksmsp]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=541</guid>
		<description><![CDATA[
  My earlier blog about shared pool duration got an offline response from one of my reader:
 &#8221; So, you say that durations aka mini-heaps have been introduced from 10g onwards. I have been using Steve Adams&#8217; script  shared_pool_free_lists.sql. Is that not accurate anymore?&#8221;
 Shared pool free lists 

  I have a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=541&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>
  My earlier blog about shared pool duration got an offline response from one of my reader:<br />
 &#8221; So, you say that durations aka mini-heaps have been introduced from 10g onwards. I have been using Steve Adams&#8217; script <a href="http://www.ixora.com.au/scripts/sql/shared_pool_free_lists.sql"> shared_pool_free_lists.sql</a>. Is that not accurate anymore?&#8221;</p>
<p><b> Shared pool free lists </b></p>
<p>
  I have a great respect for <a href="http://www.ixora.com.au"> Steve Adams </a>. In many ways, he has been a great virtual mentor and his insights are so remarkable.
</p>
<p>
  Coming back to the question, I have used Steve&#8217;s script before and it is applicable prior to Oracle version 9i. In 9i, sub-heaps were introduced. Further, <a href="http://orainternals.wordpress.com/2009/08/06/ora-4031-and-shared-pool-duration/"> shared pool durations</a> were introduced in Oracle version 10g. So, his script may not be applicable from version 9i onwards. We will probe this further in this blog. </p>
<p>
This is the problem with writing anything about internals stuff, they tend to change from version to version and In many cases, our work can become obsolete in future releases(including this blog!).
</p>
<p>
  In version 9i, each sub-heap of the shared_pool has its own free list. In version 10g and 11g, each <b>duration </b>in sub-heap has its own free list. This is visible through x$ksmsp and column x$ksmsp.ksmchdur indicates the duration that chunk belongs to. In 9i, that column always has a value of  1 (at least, that I have experimented so far). In 10g &amp; 11g (up to 11.1.0.7), there are exactly 4 durations in each sub-heap and values range from 1-4 for this column ksmchdur. Each duration has its own free list.
</p>
<p><b> Shared_pool_free_list.sql script </b></p>
<p>
   I couldn&#8217;t find any script depicting shared pool free list accurately for versions 9i and above. So, I wrote a small script to print shared pool free list information from x$ksmsp. [Warning: Accessing x$ksmsp would add more pressure on shared pool latches.] Complete script can be downloaded from orainternals.com script archive <a href="http://www.orainternals.com/viewfile.php?id=31"> shared_pool_free_lists_9i.sql </a>.
</p>
<pre>
SQL&gt; @"shared_pool_free_lists_9i.sql"
  KSMCHIDX   KSMCHDUR     BUCKET FREE_SPACE FREE_CHUNKS AVERAGE_SIZE    BIGGEST
---------- ---------- ---------- ---------- ----------- ------------ ----------
         1          1          1       1320          33           40         40
                               2       2160          45           48         48
                               3       1400          25           56         56
                               4       2240          35           64         64
                               5       2448          34           72         72
                               6       3360          42           80         80
                               7        792           9           88         88
                               8        672           7           96         96
                               9       1664          16          104        104
                              10       2352          21          112        112
                              11       1680          14          120        120
                              12       1792          14          128        128
                              13       4896          36          136        136
                              14       2016          14          144        144
                              15       3040          20          152        152
                              16       2880          18          160        160
                              88        736           1          736        736
                             252      45824           2        22912      22928
                             253  528212104          41     12883222   15597568
...
</pre>
<p>
  Above output shows shared pool free list for sub-heap 1 (ksmchidx=1), duration 1(ksmchdur=1) more technically sga heap (1, 1). In a free list, free Chunks are attached to a bucket classified by chunk size. This facilitates chunk search so that a chunk of a specific size can be easily found. For example, bucket 7 holds chunks bigger than 88 bytes but smaller than 96 bytes. Bucket 8 has chunks bigger than 96 and smaller than 104. Say, for example, for an allocation request of chunk with size of 96 bytes, code can quickly look up bucket 8 and after to find a chunk of size at least 96 bytes. Above script is an excellent indicator to see if the shared pool is fragmented (In this case, shared pool is not fragmented since number of chunks are few).
</p>
<p>
  Problem is that this script also does not depict free list information accurately 10g or 11g. In version 9i, bucket size between two adjacent buckets are 8 until size is less than 1672 bytes and then increases to 48, followed by near 8K difference and so the script works fine in 9i.
</p>
<pre>
...
 case
        when ksmchsiz &lt; 1672 then trunc((ksmchsiz-32)/8)
        when ksmchsiz &lt; 4120 then trunc((ksmchsiz+7928)/48)
        when ksmchsiz &lt; 8216 then 250
        when ksmchsiz &lt; 16408 then 251
        when ksmchsiz &lt; 32792 then 252
        when ksmchsiz = 65560 then 253
   end bucket,...
</pre>
<p>
  But, in 10g and 11g, that is not true anymore (at least that I can observe). For example, in the output below, after bucket 239, difference between two adjacent buckets went down to 8. So, the script method is not dependable. Still, I must insist, that script output is a pretty good indicator of shared pool free space fragmentation.
</p>
<pre>
...
 Bucket 239 size=4024 48
 Bucket 240 size=4096 72
 Bucket 241 size=4104 8
 Bucket 242 size=4120 16
 Bucket 243 size=8216 4096
 Bucket 244 size=16408 8192
 Bucket 245 size=16888 480
 Bucket 246 size=16896 8
 Bucket 247 size=16904
...
</pre>
<p><b> heapdump_freelist.ksh </b></p>
<p>
  Must we need more accurate picture, we can parse heapdump trace file to print it. I wrote another korn shell based awk script <a href="http://www.orainternals.com/viewfile.php?id=32">  heapdump_freelist.sh </a>. This script parses heapdump level 2 trace files and prints the shared pool free list information more accurately. This script works correctly in Oracle versions 9i,10g and 11g. This script accepts an heapdump level 2 trace file as an argument.
</p>
<pre>
./heapdump_freelists.ksh DEV11g_ora_553.trc

-- Heapdump freelist v1.00 by Riyaj Shamsudeen @OraInternals

 This script prints shared pool freelists details
   1. /tmp/shared_pool_freelist.lst - Freelist information for various heaps

Few lines from /tmp/shared_poool_freelist.lst shows that freelist information is printed at more granular level.

------------------------------------------
       sga heap(1,1)
------------------------------------------
Bucket                    1              size=40  Count=        75 Sum=      3000
Bucket                    2              size=48  Count=       176 Sum=      8448
Bucket                    3              size=56  Count=        72 Sum=      4032
Bucket                    4              size=64  Count=        86 Sum=      5504
Bucket                    5              size=72  Count=       173 Sum=     12456
...
Bucket                   42             size=368  Count=         1 Sum=       368
Bucket                   51             size=440  Count=         1 Sum=       440
...
Bucket                  243            size=8216  Count=         3 Sum=     29904
Bucket                  248           size=16912  Count=         1 Sum=     17208
Bucket                  252           size=20552  Count=         2 Sum=     45152
Bucket                  253           size=32792  Count=         1 Sum=     47064
Bucket                  254           size=65560  Count=         6 Sum=  52860352
------------------------------------------
       sga heap(1,2)
------------------------------------------
Bucket                    1              size=40  Count=         1 Sum=        40
Bucket                    3              size=56  Count=         2 Sum=       112
Bucket                    5              size=72  Count=         1 Sum=        72
..
</pre>
<p><b> Summary </b></p>
<p>
  In summary, shared_pool_free_lists.sql is immensely helpful, but alas internal working details changes from version to version. We have added two scripts to print shared pool free list more accurately:</p>
<ol>
<li> shared_pool_free_lists.sql to show freespace fragmentation through SQL.</li>
<li> heapdump_freelist.ksh to parse heapdump trace file and print free list information more accurately. </li>
</ol>
<p>This blog is available in pdf format <a href="http://orainternals.files.wordpress.com/2009/08/shared_pool_free_list_and_durations.pdf">shared_pool_free_lists_and_duration.pdf </a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/541/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/541/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/541/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/541/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/541/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/541/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/541/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/541/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/541/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/541/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=541&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/08/09/shared-pool-freelists-and-durations/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>ORA-4031 and Shared Pool Duration</title>
		<link>http://orainternals.wordpress.com/2009/08/06/ora-4031-and-shared-pool-duration/</link>
		<comments>http://orainternals.wordpress.com/2009/08/06/ora-4031-and-shared-pool-duration/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 15:01:01 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[RAC]]></category>
		<category><![CDATA[durations]]></category>
		<category><![CDATA[heapdump]]></category>
		<category><![CDATA[KGH:NO ACCESS]]></category>
		<category><![CDATA[ORA-4031]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[sga heap]]></category>
		<category><![CDATA[shared pool heapdump]]></category>
		<category><![CDATA[_enable_shared_pool_durations]]></category>
		<category><![CDATA[_ksmg_granule_size]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=511</guid>
		<description><![CDATA[
After reading my earlier post on shared pool  A stroll through shared pool heap , one of my client contacted me with an interesting ORA-4031 issue. Client was getting ORA-4031 errors and shared pool size was over 4GB ( in a RAC environment). Client DBA queried v$sgastat to show that there is plenty of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=511&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>
After reading my earlier post on shared pool <a href="http://orainternals.wordpress.com/2009/01/15/a-stroll-through-shared-pool-heaps/"> A stroll through shared pool heap </a>, one of my client contacted me with an interesting ORA-4031 issue. Client was getting ORA-4031 errors and shared pool size was over 4GB ( in a RAC environment). Client DBA queried v$sgastat to show that there is plenty of free memory in the shared pool. We researched the issue and it is worth blogging. Client DBA was confused as to how there can be ORA-4031 errors when the shared pool free memory is few GBs.
</p>
<p><b> Heapdump Analysis </b></p>
<p>
At this point, it is imperative to take heapdump in level 2 and Level 2 is for the shared pool heap dump. [ Please be warned that it is not advisable to take shared pool heap dumps excessively, as that itself can cause performance issue. During an offline conversation, Tanel Poder said that heapdump can freeze instance as his clients have experienced.]. This will create a trace file in user_dump_dest destination and that trace file is quite useful in analyzing the contents of shared pool heap. <a href="http://blog.tanelpoder.com/"> Tanel Poder </a> has an excellent script <a href="http://www.tanelpoder.com/files/scripts/heapdump_analyzer"> heapdump_analyzer </a>. I modified that script adding code for aggregation at heap, extent and type levels to debug this issue further and it is available as <a href="http://www.orainternals.com/viewfile.php?id=30"> heapdump_dissect.ksh </a>.  ( with a special permission from Tanel to publish this script.)
</p>
<p><b> Shared pool review  </b></p>
<p>
  You can read much more about shared pool in my earlier blog entry posted above. Just as a cursory review, shared pool is split in to multiple sub heaps. In  10g, each of those sub heaps are divided in to even smaller sub heaps, let&#8217;s call it mini-heaps. For example, in this specific database, there are three sub heaps. Each of those sub heaps are further split in to four mini-heaps (1,0), (1,1), (1,2) and (1,3) each. </p>
<pre>
	sga heap(1,0)
	sga heap(1,1)
	sga heap(1,2)
	sga heap(1,3)

	sga heap(2,0)
	sga heap(2,1)
	sga heap(2,2)
	sga heap(2,3)

	sga heap(3,0)
	sga heap(3,1)
	sga heap(3,2)
	sga heap(3,3)
</pre>
<p>
  One or more extents are allocated to these mini-heaps dynamically as these areas grow over the course of instance life until there is no more free memory to allocate. In this blog entry, let&#8217;s focus on the contents of these sub-heaps.<br />
  Following shows output of heapdump_dissect script at extent level aggregation. As you can see sga heap (1,0) is allocated with 34 extents of 16M each. [ 16M comes from _ksmg_granule_size.]
</p>
<pre>
Extent level summary
------------------
Sub heap          Extent             Type              Allocation cmt   Size
---------------- -----------------   ---------------   --------------  --------
   sga heap(1,0)          EXTENT 0              free                   1792
   sga heap(1,0)          EXTENT 0              perm   perm            15096064
   sga heap(1,0)          EXTENT 0            R-free                   616
   sga heap(1,0)          EXTENT 0            R-perm   perm            1678560
   sga heap(1,0)          EXTENT 0        R-freeable   reserved stoppe 96
   sga heap(1,0)          EXTENT 1              free                   808
   sga heap(1,0)          EXTENT 1              perm   perm            15097048
   sga heap(1,0)          EXTENT 1            R-free                   1248
   sga heap(1,0)          EXTENT 1            R-perm   perm            1677928
   sga heap(1,0)          EXTENT 1        R-freeable   reserved stoppe 96
   sga heap(1,0)          EXTENT 2              free                   456
   sga heap(1,0)          EXTENT 2              perm   perm            15097400
   sga heap(1,0)          EXTENT 2            R-free                   1679176
   sga heap(1,0)          EXTENT 2        R-freeable   reserved stoppe 96
 ...
   sga heap(1,0)         EXTENT 34              free                   160
   sga heap(1,0)         EXTENT 34              perm   perm            15097696
   sga heap(1,0)         EXTENT 34            R-free                   1679176
   sga heap(1,0)         EXTENT 34        R-freeable   reserved stoppe 96
</pre>
<p><b> Duration: A KGH policy </b></p>
<p>
  It gets interesting here. Notice that all &#8220;sga heap(1,0)&#8221; chunks has allocation comment as &#8220;perm&#8221;. Allocation comment &#8220;perm&#8221; is passed for permanent chunks. In a nutshell, all permanent chunks are allocated from first mini-heap in each of these sub heaps i.e. sga heap(1,0), sga heap(2,0) and sga heap(3,0) and so on. They are only allocated in the first mini-heap and not in any other mini-heap in these sub-heaps. Another example: PL/SQL DIANA type chunks are allocated only in fourth mini-sub-heap (1,3) (2,3) and (3,3) [in this instance].
</p>
<pre>
   sga heap(1,3)          freeable   PL/SQL DIANA    1318912
...
   sga heap(2,3)          freeable   PL/SQL DIANA    1675296
...
   sga heap(3,3)          freeable   PL/SQL DIANA    1458176
</pre>
<p>
  Point is that there is a new KGH policy based upon duration of a chunk. All chunks are classified based upon their type ( or more formally based upon the duration of that chunk) and the chunks with the same duration is allocated from the same shared pool mini-heaps. I think, this is a great idea, especially since only few heaps of shared pool tend to be over worked and that should not unnecessarily flush other parts of the sub-heap. Another important thing to consider is that shared pool extents can be de-allocated and allocated to other parts of SGA. For example, shared pool extents can be deallocated from shared pool and allocated to buffer cache to increase buffer cache size [ These reallocated chunks will be marked with a comment KGH:NO ACCESS ]. By keeping the perm chunks in the first mini-heap, extents can be deallocated quite easily, without the need to move the perm chunks to different areas.
</p>
<p><b> So, What&#8217;s the problem? </b></p>
<p>
  Drawback is that these chunks are contained in that mini-heap. For example, let&#8217;s say that chunks with permanent duration must be allocated and there is no free space in the first mini-heap ( say sga heap(1,0) ) and if a new extent can&#8217;t be added to that mini-heap then ORA-4031 error is thrown even if there is plenty of free space in some other mini-heap ( say sga heap(1,1), sga heap(1,2) etc). So permanent chunks will be allocated only from sga heap(N, 0) [ where N is sub-heap id 1, 2,3... ] and if that mini-heap runs out of space, ORA-4031 will be thrown.
</p>
<p>
  This is why client encountered ORA-4031 errors. Even though there was plenty of free memory in other pools, simply permanent chunks can not be allocated in the first mini-heap leading to ORA-4031 errors. Of course, other chunks in that mini-heap can not be deallocated either since those chunks are also permanent chunks. Chances of these errors occurring in other sub-heaps such as  sga heap(N,1), sga heap(N,2) etc are less since recreatable/freeable chunks can be flushed to accommodate incoming requests. Quick resolution was to increase shared pool_size temporarily (until we can reduce perm chunk usage due to another issue, which will be resolved soon).
</p>
<p><b> Parameter:_enable_shared_pool_durations </b></p>
<p> Above undocumented parameter controls this specific KGH policy and default is true. [Note that setting an undocumented parameter needs Oracle support blessing in a production database]. I tested this in my test database setting parameter _enable_shared_pool_durations=false and mini-heaps disappeared. If this parameter is false, then duration of a chunk is not considered. Following example shows that EXTENT 0 in sga heap(1,0) contains non-perm allocations if this parameter is set to FALSE.
</p>
<pre>
EXTENT 0 addr=3CC00000
...
  Chunk 3cfdf23c sz=     4096    freeable  "sql area       "  ds=3CFE4E0C
  Chunk 3cfe023c sz=      540    recreate  "KQR PO         "  latch=41AE8FD4
...
</pre>
<p><b> Summary </b></p>
<p>
  In essence, duration enabled chunk allocation policy has been introduced in 10g [ I don't know exact version]. This is usually beneficial and ORA-4031 errors are possible even if there is plenty of free space in other mini-heaps.
</p>
<p> This can be read in pdf format from <a href="http://orainternals.files.wordpress.com/2009/08/ora-4031_and_shared_pool_duration.pdf"> Investigations:ORA-4031 and shared pool duration</a>. </p>
<p> Also, there is a patent documents &#8220;duration based memory management&#8221; available in the web (patent US 6,253,226). Those documents provides in-depth analysis. </p>
<p>
 Update 1: Looks like these mini-heaps are formally called duration from an Oracle internal resource. There are exactly 4 durations in each sub-heap and each duration has its own free list. x$ksmsp.ksmchdur column indicates the duration of that chunk.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/511/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/511/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/511/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/511/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/511/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/511/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/511/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/511/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/511/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/511/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=511&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/08/06/ora-4031-and-shared-pool-duration/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>RAC, parallel query and udpsnoop</title>
		<link>http://orainternals.wordpress.com/2009/06/20/rac-parallel-query-and-udpsnoop/</link>
		<comments>http://orainternals.wordpress.com/2009/06/20/rac-parallel-query-and-udpsnoop/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 22:37:36 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[RAC]]></category>
		<category><![CDATA[battle of the nodes]]></category>
		<category><![CDATA[external table]]></category>
		<category><![CDATA[gv$px_session]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[parallel query]]></category>
		<category><![CDATA[parallel_instance_group]]></category>
		<category><![CDATA[RAC interconnect traffic]]></category>
		<category><![CDATA[RAC performance myths]]></category>
		<category><![CDATA[UDP]]></category>
		<category><![CDATA[udpsnoop.d]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=495</guid>
		<description><![CDATA[
I presented about various performance myths in my &#8216;battle of the nodes&#8217; presentation. One of the myth was that how spawning parallel query slaves across multiple RAC instances can cause major bottleneck in the interconnect. In fact, that myth was direct result of a  lessons learnt presentation from a client engagement. Client was suffering [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=495&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>
I presented about various performance myths in my &#8216;battle of the nodes&#8217; presentation. One of the myth was that how spawning parallel query slaves across multiple RAC instances can cause major bottleneck in the interconnect. In fact, that myth was direct result of a  lessons learnt presentation from a client engagement. Client was suffering from performance issues with enormous global cache waits running in to 30+ms average response time for global cache CR traffic and crippling application performance. Essentially, their data warehouse queries were performing hundreds of parallel queries concurrently with slaves spawning across three node RAC instances.
</p>
<p>
 Of course, I had to hide the client details and simplified using a test case to explain the myth. Looks like either a)my test case is bad or b) some sort of bug I encountered in 9.2.0.5 version c) I made a mistake in my analysis somewhere. Most likely it is the last one <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> .  <a href="http://structureddata.org/">Greg Rahn</a>  questioned that example and this topic deserves more research to understand this little bit further. At this point, I don&#8217;t have 9.2.0.5 and database is in 10.2.0.4 and so we will test this in 10.2.0.4.
</p>
<p><b> udpsnoop </b></p>
<p>
 UDP is one of the protocol used for cache fusion traffic in RAC and it is the Oracle recommended protocol. In this article, UDP traffic size must be measured. Measuring Global cache traffic using AWR reports was not precise. So, I decided to use a dtrace tool kit tool:udpsnoop.d to measure the traffic between RAC nodes. There are two RAC nodes in this setup. You can read more about udpsnoop.d.  That tool udpsnoop.d can be downloaded from  <a href="http://www.brendangregg.com/dtrace.html#DTraceToolkit">dtrace toolkit</a> . Output of this script is of the form:
</p>
<pre>
PID        LADDR           LPORT           DR         RADDR           RPORT                 SIZE
---------- --------------- --------------- ---------- --------------- --------------- -----------
15393      1.1.59.192      38395           -&gt;         2.1.59.192      40449                 8240
...
</pre>
<p>
  In the output above, PID 15393 sent an UDP packet of size 8240 from IP address 192.59.1.1 to 192.59.1.2 with local port as 38395 and remote port as 40449. As UDP traffic is flying between nodes, udpsnoop.d will print UDP traffic in to a file. So, I start collecting udpsnoop output before and end that collection immediately after our script is complete. Of course, we need to aggregate this data and play with it little bit, and so, will create an external table based upon this output file too.
</p>
<pre>
- This is to read the file as an external table
drop table  external_udpsnoop;

create table external_udpsnoop
(
  c_uid varchar2(10),
  pid varchar2(10),
  laddr varchar2(15),
  lport varchar2(15),
  dr   varchar2(10),
  raddr varchar2(15),
  rport varchar2(15),
  c_size   varchar2(10),
  cmd  varchar2(15)
)
organization external (
  type oracle_loader
  default directory UTL_FILE_DIR
  access parameters (
      records delimited by newline
     badfile APPS_DATA_FILE_DIR:'xtern_rpt.bad'
      logfile APPS_DATA_FILE_DIR:'xtern_rpt.log'
      discardfile APPS_DATA_FILE_DIR:'xtern_rpt.dsc'
      fields terminated by whitespace
      missing field values are null
   )
  location ('udpsnoop_ra_join_2_8th_iter.lst')
 )
  reject limit 1000
/
REM Reject limit is high since there are few packets with some junk outputs, might be due unstable fbt in dtrace.
</pre>
<p><b> Test case #1: Hash join &#8211; slaves from all instances </b></p>
<p>
  First, let&#8217;s test for an hash join to show how UDP traffic is flowing between these ports. In this test case below, we use a big table and join a 10 Million rows to another 10 Million rows table. rownum is used so that script will complete in decent time, other wise, this ran for few hours before running in to errors. This selects few non-indexed columns so that SQL must do full table scan. SQL also has hint for 16 slaves from 2 instances.
</p>
<p>
  Both instances will participate in this PQ operation as parallel_instance_group is set to ALL at session level. </p>
<pre>
alter session set parallel_instance_Group='ALL';
select /*+ parallel ( t1, 8,2)   parallel (t2, 8, 2)  */
min (t1.CUSTOMER_TRX_LINE_ID +t2.CUSTOMER_TRX_LINE_ID ) , max ( t1.SET_OF_BOOKS_ID+t2.set_of_books_id  ), avg(t1.SET_OF_BOOKS_ID +t2.set_of_books_id),
	avg( t1.QUANTITY_ORDERED + t2.QUANTITY_ORDERED ), max(t1.ATTRIBUTE_CATEGORY  ), max(t2.attribute1) , max(t1.attribute2)
from
  (select * from BIG_TABLE where rownum &lt;=100000000)t1 ,
  (select * from BIG_TABLE where rownum &lt;=100000000)t2
where t1.CUSTOMER_TRX_LINE_ID = t2.CUSTOMER_TRX_LINE_ID
;
</pre>
<p><b> PQ in operation </b></p>
<p> We will also use yet another script to make sure that SQL is indeed getting 8 slaves in each instance. I don&#8217;t remember, where I got this SQL to pull slaves information (may be Doug burns, Thanks!), but anyway, I modified that little bit for RAC.</p>
<pre>
   select
      s.inst_id,
      decode(px.qcinst_id,NULL,s.username,
            ' - '||lower(substr(s.program,length(s.program)-4,4) ) ) "Username",
      decode(px.qcinst_id,NULL, 'QC', '(Slave)') "QC/Slave" ,
      to_char( px.server_set) "Slave Set",
      to_char(s.sid) "SID",
      decode(px.qcinst_id, NULL ,to_char(s.sid) ,px.qcsid) "QC SID",
      px.req_degree "Requested DOP",
     px.degree "Actual DOP", p.spid
   from
     gv$px_session px,
     gv$session s, gv$process p
   where
     px.sid=s.sid (+) and
     px.serial#=s.serial# and
     px.inst_id = s.inst_id
     and p.inst_id = s.inst_id
     and p.addr=s.paddr
  order by 5 , 1 desc
SQL&gt; /
   INST_ID Username     QC/Slave   Slave Set  SID    QC SID Requested DOP Actual DOP SPID
---------- ------------ ---------- ---------- ------ ------ ------------- ---------- ------------
         1 SYS          QC                    10931  10931                           7366
         1  - p000      (Slave)    1          10925  10931             16         16 24762
         1  - p001      (Slave)    1          10956  10931             16         16 24764
         1  - p002      (Slave)    1          10955  10931             16         16 24766
         1  - p003      (Slave)    1          10918  10931             16         16 24768
         1  - p004      (Slave)    1          10941  10931             16         16 24778
         1  - p005      (Slave)    1          10916  10931             16         16 24781
         1  - p006      (Slave)    1          10945  10931             16         16 24787
         1  - p007      (Slave)    1          10922  10931             16         16 24795
         2  - p000      (Slave)    1          10943  10931             16         16 16920
         2  - p001      (Slave)    1          10961  10931             16         16 16923
         2  - p002      (Slave)    1          10920  10931             16         16 16970
         2  - p003      (Slave)    1          10946  10931             16         16 16972
         2  - p004      (Slave)    1          10935  10931             16         16 16974
         2  - p005      (Slave)    1          10934  10931             16         16 16976
         2  - p006      (Slave)    1          10899  10931             16         16 16988
         2  - p007      (Slave)    1          10940  10931             16         16 16991

         1 SYS          QC                    10927  10927                           9476
         2  - pz99      (Slave)    1          10890  10927              2          2 17723
         1  - pz99      (Slave)    1          10912  10927              2          2 25875
20 rows selected.
</pre>
<p>
  From the output above 8 slaves are from instance 1 and 8 are from instance 2 allocated, with query coordinator ( 7366) running instance 1. Above sample also captured my own session accessing gv$ views ( Notice pz99, slaves for gv$ access use different PQ slave naming conventions from 10.2 onwards).
</p>
<p><b> Results </b></p>
<p>
  We have established that slaves were allocated from multiple instances and udpsnoop is capturing UDP packet size between these instances. We also have external table mapping to that udpsnoop output file so as to query this data. Script completed in 1500 seconds. I mapped output of px slaves query above with UDP external table and here is the table I put together to show PQ slaves and their UDP size.
</p>
<pre>
  INST Username     QC/Slave   Slave SID   QC SID Req. Actual   SPID  LADDR      RADDR      RPORT SIZE
                                 Set              DOP  DOP
------ ------------ ---------- ----- ----  ------ ---  ------- ------ ---------- ---------- ----- ---------
     1 SYS          QC               10931  10931               7366
     1  - p000      (Slave)    1     10925  10931  16       16 24762
     1  - p001      (Slave)    1     10956  10931  16       16 24764
     1  - p002      (Slave)    1     10955  10931  16       16 24766
     1  - p003      (Slave)    1     10918  10931  16       16 24768
     1  - p004      (Slave)    1     10941  10931  16       16 24778
     1  - p005      (Slave)    1     10916  10931  16       16 24781
     1  - p006      (Slave)    1     10945  10931  16       16 24787
     1  - p007      (Slave)    1     10922  10931  16       16 24795
     2  - p000      (Slave)    1     10943  10931  16       16 16920  2.1.59.192 2.1.59.192 62783 127068484
     2  - p001      (Slave)    1     10961  10931  16       16 16923  2.1.59.192 2.1.59.192 62783 126904080
     2  - p002      (Slave)    1     10920  10931  16       16 16970  2.1.59.192 2.1.59.192 62783 127767353
     2  - p003      (Slave)    1     10946  10931  16       16 16972  2.1.59.192 2.1.59.192 62783 128154145
     2  - p004      (Slave)    1     10935  10931  16       16 16974  2.1.59.192 2.1.59.192 62783 128096875
     2  - p005      (Slave)    1     10934  10931  16       16 16976  2.1.59.192 2.1.59.192 62783 126057311
     2  - p006      (Slave)    1     10899  10931  16       16 16988  2.1.59.192 2.1.59.192 62783 128228830
     2  - p007      (Slave)    1     10940  10931  16       16 16991  2.1.59.192 2.1.59.192 62783 127471579
</pre>
<p>
	Few important points to make here:</p>
<ol>
<li> In this case, all slaves running in node 2 were talking to one UDP port in node 1 (Port 62783). lsof shows that PID 7366 (Query co-ordinator) was listening on that UDP port. Point is that these slaves from node 2 were sending packats to the co-ordinator.</li>
<li> Interestingly, there is no UDP traffic from instance 1 to 2. I think, that looks due to the nature of aggregation in the SQL. </li>
</ol>
<p><b> Few minutes later.. </b></p>
<p>
 Interestingly, few minutes later, while I was watching UDP traffic, few other processes kicked in and started generating UDP traffic. Re-queried the database again to see what these processes are. Query has allocated 16 more slaves, 8 more running from node 1 and 8 more running in node 2 [processes p008-p015 below]. These slaves were talking to a different UDP port 62789 which was also listened by coordinator process 7366 in node 1.
</p>
<pre>
  INST Username     QC/Slave   Slave SID   QC SID Req. Actual   SPID  LADDR      RADDR      RPORT SIZE
                                 Set              DOP  DOP
------ ------------ ---------- ----- ----  ------ ---  ------- ------ ---------- ---------- ----- ---------
     1 SYS          QC               10931  10931               7366
     1  - p000      (Slave)    1     10925  10931  16       16 24762
     1  - p001      (Slave)    1     10956  10931  16       16 24764
     1  - p002      (Slave)    1     10955  10931  16       16 24766
     1  - p003      (Slave)    1     10918  10931  16       16 24768
     1  - p004      (Slave)    1     10941  10931  16       16 24778
     1  - p005      (Slave)    1     10916  10931  16       16 24781
     1  - p006      (Slave)    1     10945  10931  16       16 24787
     1  - p007      (Slave)    1     10922  10931  16       16 24795

     1  - p008      (Slave)    1     10958  10931  16       16 24798
     1  - p009      (Slave)    1     10938  10931  16       16 24818
     1  - p010      (Slave)    1     10965  10931  16       16 24836
     1  - p011      (Slave)    1     10953  10931  16       16 24838
     1  - p012      (Slave)    1     10946  10931  16       16 24841
     1  - p013      (Slave)    1     10929  10931  16       16 24843
     1  - p014      (Slave)    1     10919  10931  16       16 24853
     1  - p015      (Slave)    1     10942  10931  16       16 24855

     2  - p000      (Slave)    1     10943  10931  16       16 16920  2.1.59.192 2.1.59.192 62783 127068484
     2  - p001      (Slave)    1     10961  10931  16       16 16923  2.1.59.192 2.1.59.192 62783 126904080
     2  - p002      (Slave)    1     10920  10931  16       16 16970  2.1.59.192 2.1.59.192 62783 127767353
     2  - p003      (Slave)    1     10946  10931  16       16 16972  2.1.59.192 2.1.59.192 62783 128154145
     2  - p004      (Slave)    1     10935  10931  16       16 16974  2.1.59.192 2.1.59.192 62783 128096875
     2  - p005      (Slave)    1     10934  10931  16       16 16976  2.1.59.192 2.1.59.192 62783 126057311
     2  - p006      (Slave)    1     10899  10931  16       16 16988  2.1.59.192 2.1.59.192 62783 128228830
     2  - p007      (Slave)    1     10940  10931  16       16 16991  2.1.59.192 2.1.59.192 62783 127471579

     2  - p008      (Slave)    1     10911  10931  16       16 16993  2.1.59.192 2.1.59.192 62989 182053370
     2  - p009      (Slave)    1     10949  10931  16       16 16995  2.1.59.192 2.1.59.192 62989 182490908
     2  - p010      (Slave)    1     10951  10931  16       16 17000  2.1.59.192 2.1.59.192 62989 181899025
     2  - p011      (Slave)    1     10890  10931  16       16 17007  2.1.59.192 2.1.59.192 62989 181858294
     2  - p012      (Slave)    1     10972  10931  16       16 17009  2.1.59.192 2.1.59.192 62989 182104499
     2  - p013      (Slave)    1     10950  10931  16       16 17011  2.1.59.192 2.1.59.192 62989 182334705
     2  - p014      (Slave)    1     10902  10931  16       16 17013  2.1.59.192 2.1.59.192 62989 181611641
     2  - p015      (Slave)    1     10955  10931  16       16 17023  2.1.59.192 2.1.59.192 62989 181816693
</pre>
<p><b> In real life.. </b></p>
<p>
  Summing this up, approximately, 2.4GB of UDP traffic was generated with one parallel query. Can you imagine what will happen if this inter-instance parallelism is allowed in data warehouse queries scanning many tables and partitions with many hash joins? Obviously, this has the effect of saturating Interconnect quickly and so performance will suffer. Our solution was to disallow parallel queries spawning multiple instances. All of them will be running within an instance boundary and effect of this change was immediately visible in the client environment. Back to our test, parallel_execution_message_size was set to 8192. Increasing this parameter will decrease elapsed time little bit, but we are worried about saturating interconnect traffic not just elapsed time of that query.
</p>
<p>
  Further, I ran this query with parallel_instance_group set to one instance and then all instances, few times. Spawning across multiple instances, in fact, increases elapsed time too. </p>
<pre>
Parallel_instance_group :ALL
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.20       0.26          0         76          0           0
Fetch        2   1481.76    1509.95     701158         76          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4   1481.96    1510.22     701158        152          0           1

parallel_instance_group :INST1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.20       0.23          0         76          0           0
Fetch        2   1321.05    1331.67     701344         76          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4   1321.25    1331.90     701344        152          0           1
</pre>
<p><b> What about tha original example ?</b></p>
<p>
   Of course, let&#8217;s talk about that original example also. In this example, there was just one table and data was aggregated.
</p>
<pre>
select /*+ parallel ( t1, 8,2)  */
min (t1.CUSTOMER_TRX_LINE_ID +t1.CUSTOMER_TRX_LINE_ID ) , max ( t1.SET_OF_BOOKS_ID+t1.set_of_books_id  ), avg(t1.SET_OF_BOOKS_ID +t1.set_of_books_id),
        avg( t1.QUANTITY_ORDERED + t1.QUANTITY_ORDERED ), max(t1.ATTRIBUTE_CATEGORY  ), max(t1.attribute1) , max(t1.attribute2)
from
  BIG_TABLE t1
;
</pre>
<p>
  Measuring, UDP traffic, It is visible that for this huge table, Interconnect traffic is kept minimal. It looks like, there are some optimization techniques for this single table aggregation query minimizing cache fusion traffic to a minimal level, just 2152. This convinces that, just the SQL in that myth is a bad example, but that myth is still a myth. I should have used original SQL joining multiple tables with hash join for my presentation, but as a consultant, I have a responsibility to keep clients information confidential and protect. At the end of the day, they pay for my bread.
</p>
<pre>
   INST_ID Username     QC/Slave   Slave Set  SID    QC SID Requested DOP Actual DOP SPID		  Size
---------- ------------ ---------- ---------- ------ ------ ------------- ---------- ------------ -------
         1 SYS          QC                    10933  10933                           3314
         1  - p000      (Slave)    1          10958  10933             16         16 24762
         1  - p001      (Slave)    1          10948  10933             16         16 24764
         1  - p002      (Slave)    1          10953  10933             16         16 24766
         1  - p003      (Slave)    1          10925  10933             16         16 24768
         1  - p004      (Slave)    1          10916  10933             16         16 24778
         1  - p005      (Slave)    1          10938  10933             16         16 24781
         1  - p006      (Slave)    1          10951  10933             16         16 24787
         1  - p007      (Slave)    1          10946  10933             16         16 24795

         2  - p000      (Slave)    1          10949  10933             16         16 16920            2152
         2  - p001      (Slave)    1          10937  10933             16         16 16923            2152
         2  - p002      (Slave)    1          10946  10933             16         16 16970            2152
         2  - p003      (Slave)    1          10956  10933             16         16 16972            2152
         2  - p004      (Slave)    1          10902  10933             16         16 16974            2152
         2  - p005      (Slave)    1          10981  10933             16         16 16976            2152
         2  - p006      (Slave)    1          10899  10933             16         16 16988            2152
         2  - p007      (Slave)    1          10927  10933             16         16 16991            2152

         1 SYS          QC                    10945  10945                           3527
         1  - pz99      (Slave)    1          10942  10945              2          2 25875
         2  - pz99      (Slave)    1          10962  10945              2          2 17723           72344
</pre>
<p><b> Summary </b></p>
<p>
  In summary, having too many parallel query slaves spawning across multiple instances can cripple interconnect. There are some optimization techniques that seems to help in the case of single table aggregation and of course, that must be considered as an exception. I have modified the presentation little bit below, but will do a second and complete update on this presentation later:
</p>
<p><a href='http://orainternals.files.wordpress.com/2009/06/battle-of-the-nodes-rac-performance-myths-doc.pdf'>Battle of the nodes RAC performance myths doc</a><br />
<a href='http://orainternals.files.wordpress.com/2009/06/battle-of-the-nodes-rac-performance-myths-ppt.pdf'>Battle of the nodes RAC performance myths ppt</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/495/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/495/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/495/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/495/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/495/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=495&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/06/20/rac-parallel-query-and-udpsnoop/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>Resolving corruption issue with file_hdrs dump</title>
		<link>http://orainternals.wordpress.com/2009/06/18/resolving-corruption-issue-with-file_hdrs-dump/</link>
		<comments>http://orainternals.wordpress.com/2009/06/18/resolving-corruption-issue-with-file_hdrs-dump/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 15:55:49 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[corruption]]></category>
		<category><![CDATA[recovery]]></category>
		<category><![CDATA[controlf]]></category>
		<category><![CDATA[dump]]></category>
		<category><![CDATA[file_hdrs]]></category>
		<category><![CDATA[ORA-01171]]></category>
		<category><![CDATA[oradebug]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=471</guid>
		<description><![CDATA[ One of our client had an interesting and bizarre corruption issue. Intermittently their database is corrupted. 

ORA-01171: datafile 178 going offline due to error advancing checkpoint
ORA-01122: database file 178 failed verification check
ORA-01110: data file 178: &#8216;/app/u04/oradata/somedb/some_data_01.dbf&#8217;
ORA-01251: Unknown File Header Version read for file number 178


  Error message printed above indicates that file header [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=471&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p> One of our client had an interesting and bizarre corruption issue. Intermittently their database is corrupted. </p>
<p>
ORA-01171: datafile 178 going offline due to error advancing checkpoint<br />
ORA-01122: database file 178 failed verification check<br />
ORA-01110: data file 178: &#8216;/app/u04/oradata/somedb/some_data_01.dbf&#8217;<br />
ORA-01251: Unknown File Header Version read for file number 178
</p>
<p>
  Error message printed above indicates that file header is corrupted. This is not a one time issue and recurring many times in the past 45 days or so. Database become unusable and only option was to restore the database from backup and recover it. A painful and business impacting issue. Client&#8217;s frustration is understandable.</p>
<p>
  Of course, Client tried normal channels to resolve this problem with out luck. Opening Service tickets with vendors, Relink software stack, update dbid, modify kernel parameters and replace hardware etc. Client has even planned to reinstall OS soon. Still, problem re-occurred every week. That&#8217;s when he reached out to us.
</p>
<p><b> file_hdrs dump </b></p>
<p>
  Realizing that file header is corrupted, First thing, I wanted to do was that to find what exactly is there in those file headers. What type of corruption in those file headers? Is it a block formatted with null characters? or Is it that few fields are corrupted? This will give more clues and direct us in the right path. So, I asked the client to perform a file_hdrs dump when this problem re-occurs. Following commands were sent to the client.
</p>
<pre>
oradebug setmypid
oradebug dump file_hdrs 10
exit
</pre>
<p>
Above statement is to dump file headers at level 10. oradebug file_hdrs dump will print blocks from the file headers.
</p>
<pre>
oradebug setmypid
oradebug dump controlf 10
</pre>
<p>
    Second dump (controlf dump) should print control file records to the trace file. Idea here is to match the file headers and control file file header section to see if we gain more insights in to this corruption issue.
</p>
<p>
  It is quite possible that this could be a control file corruption and control file corruption can&#8217;t be ruled out yet. File headers and files can be corrupted. Essentially, this needs cross verification between control file and file headers to identify the root cause. At least, I was hopeful that this will point us in right direction.
</p>
<p><b> dd of file header block </b></p>
<p>
  I also requested the client to take a backup of first few blocks of the corrupted file using  &#8216;dd if=filename of=filehdr.out bs=8192 count=2&#8242; command. In UNIX platform, this dd command will copy first two blocks (of block size 8K) in to a flat file. After every corruption, only workaround is to restore and recover the database  and I wanted to collect as much information as possible in one round.
</p>
<p><b> What happens on Friday? </b></p>
<p>
  Client also pointed out that this issue happens on Fridays only. Various groups were checking UNIX, SAN layers to see if there is anything special about Friday, looking for maintenance jobs that runs on Friday etc. Nothing of any significance shows up. At this point, we were waiting for the problem to reoccur.
</p>
<p> And then it did&#8230;</p>
<p><b> file_hdr and controlf trace files </b></p>
<p> We received trace files from the client and reviewed it. We will concentrate on just one corrupted data file, even though 68 files were corrupted at this point. </p>
<p> control file section for that file printed below:</p>
<pre>
DATA FILE #32:
(name #41) /app/u04/oradata/somedb/somedata1.dbf
 creation size=12800 block size=8192 status=0x1c head=41 tail=41 dup=1
 tablespace 32, index=33 krfil=32 prev_file=0
 unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00
 Checkpoint cnt:48 scn: 0x0910.62fd2f34 05/08/2009 10:30:32
 Stop scn: 0x0910.6305098e 05/08/2009 17:42:13
 Creation Checkpointed at scn:  0x0000.000935a6 04/30/2009 21:42:29
</pre>
<p>
  Nothing jumps out. Checkpoint SCN is recent enough [ Of course, this problem happened in May 2009].<br />
  Let&#8217;s review the file header section for that corrupted file. Clearly , there is a corruption since controlf dump command itself is unable to print correct file header version.
</p>
<pre>
File header version cannot be determined due to corruption &lt;&lt;&lt;&lt;
Dump may be suspect
 V10 STYLE FILE HEADER:
	Compatibility Vsn = 169870080=0xa200300
	Db ID=1755378070=0x68a0f196, Db Name=&#39;SOMEDB&#39;
	Activation ID=0=0x0
	Control Seq=3032023=0x2e43d7, File size=401792=0x62180
	File Number=18, Blksiz=8192, File Type=3 DATA
</pre>
<p>
  If the file header is filled with null then above section starting with &#8216;V10 STYLE FILE HEADER:&#8217; can not be printed. oradebug command is complaining that file header version can not be determined, while also printing fields from file header. Confusing and that doesn&#8217;t make sense: File header version is corrupt but fields from file headers can be printed. This means that we might need to review the output of dd command. But, before going that route , decided to compare corrupted file header output with another uncorrupted file in the control file trace file to see if we can spot any obvious issue(s).
</p>
<p><b> controlf trace file for an uncorrupted file </b></p>
<p>  Following first two sections prints the control file record section for a uncorrupted file. Checkpoint scn time line is matching for corrupted and uncorrupted data file records. This gives us a clue that control file record for these files may not be corrupted. Genuinely, there must be a corruption in the file header.
</p>
<pre>
DATA FILE #33:
  (name #42) /app/u03/oradata/qnoldv01/ANOTHER_GOOD_FILE_01.dbf
creation size=12800 block size=8192 status=0xe head=42 tail=42 dup=1
 tablespace 33, index=34 krfil=33 prev_file=0
 unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00
 Checkpoint cnt:53 scn: 0x0910.641e926d 05/13/2009 16:25:26
 Stop scn: 0xffff.ffffffff 05/02/2009 13:41:42
 Creation Checkpointed at scn:  0x0000.000935c5 04/30/2009 21:42:31
 thread:1 rba:(0x3.e3bbd.10)
</pre>
<p>
  Let&#8217;s also review the file header section of an uncorrupted data file.
</p>
<pre>
 Hot Backup end marker scn: 0x0000.00000000
 aux_file is NOT DEFINED
 V10 STYLE FILE HEADER:
	Compatibility Vsn = 169870080=0xa200300
	Db ID=1908337442=0x71beeb22, Db Name='SOMEDB'
	Activation ID=0=0x0
	Control Seq=34895=0x884f, File size=2434616=0x252638
	File Number=33, Blksiz=8192, File Type=3 DATA
</pre>
<p>
  Comparison of corrupted and uncorrupted file is not showing any insights either. OR Is it?
</p>
<p><b> Not so fast&#8230;</b></p>
<p>
  There is a difference in the file header section between these these two file headers. Let me reprint both these file headers side-by-side to see if the difference can be spotted easily.
</p>
<p> Corrupted file: </p>
<pre>
File header version cannot be determined due to corruption
Dump may be suspect
 V10 STYLE FILE HEADER:
	Compatibility Vsn = 169870080=0xa200300
	Db ID=1755378070=0x68a0f196, Db Name='SOMEDB'
	Activation ID=0=0x0
	Control Seq=3032023=0x2e43d7, File size=401792=0x62180
	File Number=18, Blksiz=8192, File Type=3 DATA
</pre>
<p> Uncorrupted file:</p>
<pre>
 Hot Backup end marker scn: 0x0000.00000000
 aux_file is NOT DEFINED
 V10 STYLE FILE HEADER:
	Compatibility Vsn = 169870080=0xa200300
	Db ID=1908337442=0x71beeb22, Db Name='SOMEDB'
	Activation ID=0=0x0
	Control Seq=34895=0x884f, File size=2434616=0x252638
	File Number=33, Blksiz=8192, File Type=3 DATA
</pre>
<p>
   Ahh.. Right there. DBID is different between these two files! How can the DBID be different in this situation? Client assured me that there is no transportable tablespace or read only tablespaces shared between databases going on here. How can the dbids different between two files in the same database? These tablespaces are both opened with read and write activity. We need to follow this clue.
</p>
<pre>
Corrupted file:     :<b>Db ID=1755378070=0x68a0f196 </b>, Db Name='SOMEDB'
...
Uncorruped file     :<b>Db ID=1908337442=0x71beeb22 </b>, Db Name='SOMEDB'
</pre>
<p>
  After pointing out that dbid is different between uncorrupted and corrupted files, client dumped control files from other development and test databases to see if they can locate a db with dbid 1755378070. No databases had the same dbid.</p>
<p><b> Finally..</b></p>
<p>
With dbid difference in mind, few hours later, client DBA recollected something. When they migrated from old database server to new database server, they used scp to move the database files from old server to new server. Of course, client DBA did not want scp connection to die when his VPN connection dies and so wrote a script to scp the files from cron entry as any good DBA will do.
</p>
<p>
After migration, system admins changed oracle password. Machine was supposed to be shutdown and kept in pristine condition for few weeks before returning the hardware. Unfortunately, it was not down.
</p>
<p>
  I am sure, you figured out where I am going with it. There was a cron entry scheduled in that old DB server and that was quietly scp&#8217;ing the files from old database server to new database server corrupting the database. Client disabled that cron entry and also created new ssh key to avoid these issues.
</p>
<p>
I heard that client is able to enjoy his Fridays <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
This blog can be read in a traditional format <a href='http://orainternals.files.wordpress.com/2009/06/resolving_corruption_issue_with_filehdr_dumps.pdf'>resolving_corruption_issue_with_filehdr_dumps</a>.<br />
PS: Thanks to the client for allowing me to blog about this issue.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/471/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/471/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/471/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=471&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/06/18/resolving-corruption-issue-with-file_hdrs-dump/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>Library cache lock and library cache pin waits</title>
		<link>http://orainternals.wordpress.com/2009/06/02/library-cache-lock-and-library-cache-pin-waits/</link>
		<comments>http://orainternals.wordpress.com/2009/06/02/library-cache-lock-and-library-cache-pin-waits/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 21:37:44 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[gv$ges_blocking_enqueue]]></category>
		<category><![CDATA[library cache lock]]></category>
		<category><![CDATA[library cache pin]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[x$kgllk]]></category>
		<category><![CDATA[x$kglob]]></category>
		<category><![CDATA[x$kglpn]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=449</guid>
		<description><![CDATA[ I encountered few customer issues centered around library cache lock and library cache pin waits. Library cache lock and pin waits can hang instance, and in few cases, whole clusters of RAC instances can be hung due to library cache lock and pin waits. 
 Why  Library cache locks are needed? 
 Library [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=449&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p> I encountered few customer issues centered around library cache lock and library cache pin waits. Library cache lock and pin waits can hang instance, and in few cases, whole clusters of RAC instances can be hung due to library cache lock and pin waits. </p>
<p><b> Why  Library cache locks are needed? </b></p>
<p> Library cache locks aka parse locks are needed to maintain dependency mechanism between objects and their dependent objects like SQL etc. For example, if an object definition need to be modified or if parse locks are to be broken, then dependent objects objects must be invalidated. This dependency is maintained using library cache locks. For example, if a column is dropped from a table then all SQLs dependent upon the table must be invalidated and reparsed during next access to that object. Library cache locks are designed to implement this tracking mechanism.</p>
<p> In a regular enqueue locking scenarios there is a resource (example TM table level lock) and sessions enqueue to lock that resource. More discussion on enqueue locking can be found in <a href="http://www.orainternals.com/papers/internal_locks.pdf"> Internal of locks</a>. Similarly, library cache locks uses object handles as resource structures and locks are taken on that resource. If the resources are not available in a compatible mode, then sessions must wait for library cache objects to be available. </p>
<p><b> Why Library cache pins are needed? </b></p>
<p> Library cache pins deals with current execution of dependent objects. For example, an underlying objects should not be modified when a session is executing or accessing a dependent object (SQL). So, before parse locks on a library cache object can be broken, library cache pins must be acquired in Exclusive mode and then only library cache objects can be dropped. If a session is executing an SQL, then library cache pins will not be available and there will be waits for library cache pins. Typically, this happens for long running SQL statement.
</p>
<p><b> x$kgllk, x$kglpn and x$kglob </b></p>
<p> Library cache locks and pins are externalized in three x$ tables. x$kgllk is externalizing all locking structures on an object. Entries in x$kglob acts as a resource structure. x$kglpn is externalizing all library cache pins.
</p>
<p> x$kglob.kglhdadr acts as a pointer to the resource structure. Presumably, kglhdadr stands KGL handle address. x$kgllk acts as a lock structure and x$kgllk.kgllkhdl points to x$kglob.kglhdadr. Also, x$kglpn acts as a pin stucture and x$kglpn.kglpnhdl  points to x$kglob.kglhdadr to pin a resource. To give an analogy between object locking scenarios, x$kglob acts as resource structure and x$kgllk acts as lock structures for library cache locks. For library cache pins, x$kglpn acts as pin structure. x$kglpn also pins that resource using kglpnhdl. This might be clear after reviewing the example below.
</p>
<p><b> Test case </b></p>
<p> We will create a simple test case to create library cache locks and pin waits </p>
<pre>
create or replace procedure backup.test_kgllk (l_sleep in boolean , l_compile in boolean)
as
 begin
  if (l_sleep ) then
	sys.dbms_lock.sleep(60);
  elsif (l_compile )  then
  	execute immediate 'alter procedure test_kgllk compile';
  end if;
 end;
/
</pre>
<p>
 In this test case above, we create a procedure and it accepts two boolean parameters: sleep and compile. Passing true to first argument will enable the procedure to sleep for a minute and passing true for the second argument will enable the procedure to recompile itself.
</p>
<p>
  Let&#8217;s create two sessions in the database and then execute them as below. </p>
<p>
 Session #1: exec test_kgllk ( true, false); &#8212; Sleep for 1 minutes and no compile<br />
 Session #2: exec test_kgllk ( false, true); &#8212; No sleep,but compile..
</p>
<p>At this point both sessions are waiting. Following SQL can be used to print session wait details. </p>
<pre>
select
 distinct
   ses.ksusenum sid, ses.ksuseser serial#, ses.ksuudlna username,ses.ksuseunm machine,
   ob.kglnaown obj_owner, ob.kglnaobj obj_name
   ,pn.kglpncnt pin_cnt, pn.kglpnmod pin_mode, pn.kglpnreq pin_req
   , w.state, w.event, w.wait_Time, w.seconds_in_Wait
   -- lk.kglnaobj, lk.user_name, lk.kgllksnm,
   --,lk.kgllkhdl,lk.kglhdpar
   --,trim(lk.kgllkcnt) lock_cnt, lk.kgllkmod lock_mode, lk.kgllkreq lock_req,
   --,lk.kgllkpns, lk.kgllkpnc,pn.kglpnhdl
 from
  x$kglpn pn,  x$kglob ob,x$ksuse ses
   , v$session_wait w
where pn.kglpnhdl in
(select kglpnhdl from x$kglpn where kglpnreq &gt;0 )
and ob.kglhdadr = pn.kglpnhdl
and pn.kglpnuse = ses.addr
and w.sid = ses.indx
order by seconds_in_wait desc
/
</pre>
<p> Output of above SQL is: </p>
<pre>
                                                                pin  pin  pin                                 wait seconds
  SID   SERIAL# USERNAME     MACHINE   OBJ_OWNER  OBJ_NAME      cnt  mode req  STATE      EVENT               time in_wait
----- --------- ------------ --------- ---------- ------------- ---- ---- ---- ---------- ------------------- ----- -------
  268     12409 SYS          orap      SYS        TEST_KGLLK    3    2    0    WAITING    PL/SQL lock timer       0       7
  313     45572 SYS          orap      SYS        TEST_KGLLK    0    0    3    WAITING    library cache pin       0       3
  313     45572 SYS          orap      SYS        TEST_KGLLK    3    2    0    WAITING    library cache pin       0       3
</pre>
<ol>
<li> Session 268 (session #1) is sleeping while holding library cache pin on test_kgllk object (waiting on PL/SQL lock timer more accurately).</li>
<li> Session 313  is holding library cache pin in mode 2 and waiting for library cache pin in mode 3.</li>
</ol>
<p>
 Obviously, session 313 is waiting for session 268 to release library cache pins. Since session 268 is executing, session 313 should not be allowed to modify test_kgllk library cache object. That&#8217;s exactly why library cache pins are needed.
</p>
<p><b> Adding another session to this mix..</b></p>
<p> Let&#8217;s add one more session as below </p>
<pre>
exec test_kgllk (false, true);
</pre>
<p>Output of above query is:</p>
<pre>
                                                                                   pin  pin  pin                                            wait seconds
  SID   SERIAL# USERNAME     MACHINE              OBJ_OWNER  OBJ_NAME              cnt mode  req STATE      EVENT                           time in_wait
----- --------- ------------ -------------------- ---------- -------------------- ---- ---- ---- ---------- ------------------------------ ----- -------
  268     12409 SYS          oraperf              SYS        TEST_KGLLK              3    2    0 WAITING    PL/SQL lock timer                  0      34
  313     45572 SYS          oraperf              SYS        TEST_KGLLK              0    0    3 WAITING    library cache pin                  0      29
  313     45572 SYS          oraperf              SYS        TEST_KGLLK              3    2    0 WAITING    library cache pin                  0      29
  442      4142 SYS          oraperf              SYS        TEST_KGLLK              0    0    2 WAITING    library cache pin                  0       3
</pre>
<p> Well, no surprise there. New session 442 also waiting for library cache pin. But, notice the request mode for session 442. It is 2. Session 442 needs that library cache pin in share mode to start execution. But 313 has already requested that library cache pin in mode 3. A queue is building up here. Many processes can queue behind session 313 at this point leading to an hung instance.
</pre>
<p><b> library cache locks..</b></p>
<p> Let's execute same package but both with same parameters. </p>
<pre>
 Session #1: exec test_kgllk(false, true);
 Session #2: exec test_kgllk(false, true);
</pre>
<p> Rerunning above query tells us that session 313 is waiting for the self. Eventually, this will lead library cache pin self deadlock. </p>
<pre>

Library cache pin holders/waiters
---------------------------------
                                                                                   pin  pin  pin                                            wait seconds
  SID   SERIAL# USERNAME     MACHINE              OBJ_OWNER  OBJ_NAME              cnt mode  req STATE      EVENT                           time in_wait
----- --------- ------------ -------------------- ---------- -------------------- ---- ---- ---- ---------- ------------------------------ ----- -------
  313     45572 SYS          oraperf              SYS        TEST_KGLLK              0    0    3 WAITING    library cache pin                  0      26
  313     45572 SYS          oraperf              SYS        TEST_KGLLK              3    2    0 WAITING    library cache pin                  0      26
</pre>
<p> Wait, what happened to session #2? It is not visible in x$kglpn. Querying v$session_wait shows that Session #2 is waiting for library cache lock. We will run yet another query against x$kgllk to see library cache lock waits.
</p>
<pre>
  Querying x$kgllk with the query below:
select
 distinct
   ses.ksusenum sid, ses.ksuseser serial#, ses.ksuudlna username,KSUSEMNM module,
   ob.kglnaown obj_owner, ob.kglnaobj obj_name
   ,lk.kgllkcnt lck_cnt, lk.kgllkmod lock_mode, lk.kgllkreq lock_req
   , w.state, w.event, w.wait_Time, w.seconds_in_Wait
 from
  x$kgllk lk,  x$kglob ob,x$ksuse ses
  , v$session_wait w
where lk.kgllkhdl in
(select kgllkhdl from x$kgllk where kgllkreq &gt;0 )
and ob.kglhdadr = lk.kgllkhdl
and lk.kgllkuse = ses.addr
and w.sid = ses.indx
order by seconds_in_wait desc
/
</pre>
<pre>

Library cache lock holders/waiters
---------------------------------
                                                                                   lock lock                                            wait seconds
  SID   SERIAL# USERNAME     MODULE     OBJ_OWNER  OBJ_NAME                LCK_CNT mode  req STATE      EVENT                           time in_wait
----- --------- ------------ ---------- ---------- -------------------- ---------- ---- ---- ---------- ------------------------------ ----- -------
  313     45572 SYS          wsqfinc1a  SYS        TEST_KGLLK                    1    1    0 WAITING    library cache pin                  0      29
  313     45572 SYS          wsqfinc1a  SYS        TEST_KGLLK                    1    3    0 WAITING    library cache pin                  0      29
  268     12409 SYS          wsqfinc1a  SYS        TEST_KGLLK                    0    0    2 WAITING    library cache lock                 0      12
  268     12409 SYS          wsqfinc1a  SYS        TEST_KGLLK                    1    1    0 WAITING    library cache lock                 0      12
</pre>
<p>
  Session 313 is holding library cache lock on that object in mode 3 and session 268 is requesting lock on that library cache object in mode 2. So, session 268 is waiting for library cache lock while session 313 is waiting for library cache pin (self ). Again, point here is that session 268 is trying to access library cache object and need to acquire library cache lock in correct mode. That library cache lock is not available leading to a wait.
</p>
<p> Complete script can be downloaded from my <a href="http://www.orainternals.com/viewfile.php?id=29">script archive</a>. </p>
<p><b> RAC, library cache locks and pins </b></p>
<p>
Things are different in RAC. Library cache locks and pins are global resources controlled by GES layer. So, these scripts might not work if  these library cache lock and pin waits are global events. Let's look at what happens in a RAC environment
</p>
<p>
  exec test_kgllk ( false, true);  -- node 1<br />
  exec test_kgllk ( false, true);  -- node 2</p>
<p> In node1, only one session is visible. </p>
<pre>
Library cache pin holders/waiters
----------------------------------
                                                                                   pin  pin  pin                                            wait seconds
  SID   SERIAL# USERNAME     MACHINE              OBJ_OWNER  OBJ_NAME              cnt mode  req STATE      EVENT                           time in_wait
----- --------- ------------ -------------------- ---------- -------------------- ---- ---- ---- ---------- ------------------------------ ----- -------
  268     12409 SYS          oraperf              SYS        TEST_KGLLK              0    0    3 WAITING    library cache pin                  0      18
  268     12409 SYS          oraperf              SYS        TEST_KGLLK              3    2    0 WAITING    library cache pin                  0      18
</pre>
<pre> In node 2, only requestor of the lock is visible. 

                                                                                   lock lock                                            wait seconds
  SID   SERIAL# USERNAME     MODULE     OBJ_OWNER  OBJ_NAME                LCK_CNT mode  req STATE      EVENT                           time in_wait
----- --------- ------------ ---------- ---------- -------------------- ---------- ---- ---- ---------- ------------------------------ ----- -------
  377     43558 SYS          wsqfinc2a  SYS        TEST_KGLLK                    0    0    2 WAITING    library cache lock                 0      86
</pre>
<p>
  Essentially, this script does not work in a RAC environment since it accesses x$ tables directly, which are local to an instance. To understand the issue in a RAC environment we need to access gv$ views, based on x$kgllk, x$kglpn etc. But, I don't see gv$ views over these x$ tables. We are out of luck there unless we do some more coding.
</p>
<p>
  Nevertheless, we can see lockers and waiters accessing gv$ges_blocking_enqneue to understand locking in RAC.
</p>
<pre>
  1  select inst_id, handle, grant_level, request_level, resource_name1, resource_name2, pid , transaction_id0, transaction_id1
  2* ,owner_node, blocked, blocker, state from gv$ges_blocking_enqueue
SQL&gt; /

   INST_ID HANDLE           GRANT_LEV REQUEST_L RESOURCE_NAME1                 RESOURCE_NAME2                        PID
---------- ---------------- --------- --------- ------------------------------ ------------------------------ ----------
TRANSACTION_ID0 TRANSACTION_ID1 OWNER_NODE    BLOCKED    BLOCKER
--------------- --------------- ---------- ---------- ----------
STATE
----------------------------------------------------------------
         2 00000008DD779258 KJUSERNL  KJUSERPR  [0x45993b44][0x3a1b9eee],[LB]  1167670084,974888686,LB              8700
              0               0          1          1          0
OPENING

         1 00000008E8123878 KJUSEREX  KJUSEREX  [0x45993b44][0x3a1b9eee],[LB]  1167670084,974888686,LB             12741
              0               0          0          0          1
GRANTED
</pre>
<p>
  We can see that PID 12741 from instance 1 is holding a library cache global lock [LB]. Global resource in this case is [0x45993b44][0x3a1b9eee],[LB] which uniquely identifies a library cache object at the cluster level. Grant_level is KJUSEREX or Exclusive level and request_level from node 2 is KJUSERPR which is Protected Read level. PID 8700 in node 2 is waiting for library cache lock held by PID 12741 in node1. Using this output and our script output, we can pin point which process is holding library cache lock or pin. While Library cache locks are globalized as global locks in the range of [LA] - [LZ], Library cache pins are also globalized as lock types in the range [NA]-[NZ].
 </p>
<p>
This blog can be read in a document format from<br />
<a href='http://orainternals.files.wordpress.com/2009/06/library_cache_locks_and_library_cache_pin_waits.pdf'>Library_cache_locks_and_library_cache_pin_waits</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/449/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/449/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/449/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/449/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/449/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=449&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/06/02/library-cache-lock-and-library-cache-pin-waits/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>COLLABORATE 2009 presentation: 11g performance new feature.</title>
		<link>http://orainternals.wordpress.com/2009/05/06/collaborate-2009-presentation-11g-performance-new-feature/</link>
		<comments>http://orainternals.wordpress.com/2009/05/06/collaborate-2009-presentation-11g-performance-new-feature/#comments</comments>
		<pubDate>Wed, 06 May 2009 02:28:53 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[11g]]></category>
		<category><![CDATA[CBO]]></category>
		<category><![CDATA[EBS11i]]></category>
		<category><![CDATA[Oracle database internals]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[adaptive cursor sharing]]></category>
		<category><![CDATA[bind peeking]]></category>
		<category><![CDATA[deduplicate]]></category>
		<category><![CDATA[extended_stats]]></category>
		<category><![CDATA[invisible indexes]]></category>
		<category><![CDATA[lob compression]]></category>
		<category><![CDATA[OD lock_type]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[securefile lobs]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=425</guid>
		<description><![CDATA[ I just presented about Oracle 11g new features specific to performance in COLLABORATE 2009, Orlando Florida. You can download presentation and paper from here: 
11g performance specific new features &#8211; presentation 
11g performance specific new features &#8211; paper 
I met couple of new friends and many familiar faces. 
 Catherin Devlin introduced sqlpython tool [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=425&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p> I just presented about Oracle 11g new features specific to performance in COLLABORATE 2009, Orlando Florida. You can download presentation and paper from here: </p>
<p><a href="http://orainternals.files.wordpress.com/2009/05/riyaj_performance_features_-in_11g_ppt.pdf">11g performance specific new features &#8211; presentation </a><br />
<a href="http://orainternals.files.wordpress.com/2009/05/riyaj_performance_features_11g_doc.pdf">11g performance specific new features &#8211; paper </a></p>
<p>I met couple of new friends and many familiar faces. </p>
<p> <a href="http://catherinedevlin.blogspot.com/2009/03/sqlpython-161-puts-python-in-sqlpython.html">Catherin Devlin</a> introduced sqlpython tool to me. This tool is an user friendly replacement for sqlplus with many UNIX like goodies. This tool will be an useful addition to command line tools. You can see installation instructions for <a href="https://twiki.cern.ch/twiki/bin/view/PSSGroup/SqlPython">sqlpython here</a>.  </p>
<p> I also attended an interesting application performance panel discussion with fellow Oakie Mark W Farnheim, Mike Brown and Sandra Vucinic. We discussed few customer issues. </p>
<p> An interesting problem discussion is worth mentioning. A client clones production database to development database using full rapidclone methodology. But, access plans for a SQL statement is different between production and development, even though everything was exactly the same. I am hoping, that client will send 10053 trace files from both databases and I will blog about it if I get anything from that client. I think, bind peeking is causing the plan difference, but need to analyze 10053 trace file to confirm that. Another possibility is that, may be , he is not cloning Oracle Software and some software patches are not existing in cloned environment. Need trace files to proceed further here. </p>
<p> Of course, I met few other friends <a href="http://www.ardentperf.com">Jeremy Schneider</a>, <a href="http://www.dannorris.com/">Dan Norris</a> to mention few.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/425/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/425/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/425/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=425&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/05/06/collaborate-2009-presentation-11g-performance-new-feature/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
		<item>
		<title>DOUG presentation: Why does optimizer hate my SQL?</title>
		<link>http://orainternals.wordpress.com/2009/04/18/doug-presentation-why-does-optimizer-hate-my-sql/</link>
		<comments>http://orainternals.wordpress.com/2009/04/18/doug-presentation-why-does-optimizer-hate-my-sql/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 20:56:40 +0000</pubDate>
		<dc:creator>orainternals</dc:creator>
				<category><![CDATA[11g]]></category>
		<category><![CDATA[CBO]]></category>
		<category><![CDATA[Performance tuning]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[dbms_xplan]]></category>
		<category><![CDATA[extended statistics]]></category>
		<category><![CDATA[first_rows]]></category>
		<category><![CDATA[oracle performance]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://orainternals.wordpress.com/?p=401</guid>
		<description><![CDATA[I presented about Cost based optimizer explaining why some times CBO chose inefficient access plan, even though, there is an efficient plan in the search space. This entry is to post presentation slides and they can be downloaded from Why_optimizer_hates_my_sql 
.

Update: Updated presentation after Greg&#8217;s comments.
Update2: Further bug fixes in presentation and script.
Update3: Updates after [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=401&subd=orainternals&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I presented about Cost based optimizer explaining why some times CBO chose inefficient access plan, even though, there is an efficient plan in the search space. This entry is to post presentation slides and they can be downloaded from <a href='http://orainternals.files.wordpress.com/2009/04/why_optimizer_hates_my_sql1.pdf'>Why_optimizer_hates_my_sql</a> </p>
<p>.</p>
<p>
Update: Updated presentation after Greg&#8217;s comments.<br />
Update2: Further bug fixes in presentation and script.<br />
Update3: Updates after Randolf&#8217;s comments.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/orainternals.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/orainternals.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/orainternals.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/orainternals.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/orainternals.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/orainternals.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/orainternals.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/orainternals.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/orainternals.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/orainternals.wordpress.com/401/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=orainternals.wordpress.com&blog=670821&post=401&subd=orainternals&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://orainternals.wordpress.com/2009/04/18/doug-presentation-why-does-optimizer-hate-my-sql/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/de30d27adb6aee87e455780e8cb19e7b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">orainternals</media:title>
		</media:content>
	</item>
	</channel>
</rss>