<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-23846373</id><updated>2011-12-12T09:11:06.123-08:00</updated><category term='buffer cache _serial_direct_read direct path read full table scan parallel'/><category term='active data guard'/><category term='_defer_log_boundary_ckpt'/><category term='rman'/><category term='data loss'/><category term='Goldengate GG Xstreams logical standby'/><category term='ora_rowscn oracle bug weirdness rowdependencies dual about'/><category term='bct'/><category term='_defer_log_count'/><category term='block change tracking'/><category term='11g'/><category term='standby database'/><title type='text'>Oracle blog</title><subtitle type='html'>This blog is about the stuff related to Oracle DBA. Views expressed here may not hold true or may not work in your environment. Your feedback is appreciated.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-23846373.post-3926074822222479832</id><published>2011-09-08T00:09:00.000-07:00</published><updated>2011-09-08T01:39:44.985-07:00</updated><title type='text'>Enhancing Oracle Active Data Guard.</title><content type='html'>I think Active Data Guard (ADG) is one of the best features Oracle has ever released and it is remarkably popular considering how easily read work load can be off loaded while guaranteeing data quality (due to the nature of binary replication, good luck to those who rely on logical replication for DR) and ability to ensure zero data loss.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here are some of the enhancements which can make ADG even more adaptable:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Ability to create global temporary tables. Oracle doesn't have to generate redo for GTT's and hence they can be supported on ADG standby. This will enable batch jobs and ETL job's to run on the ADG standby.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2) Continue using parallel threads for redo apply when redo stream encounters new datafile addition. When you add new datafile on primary, redo apply will serialize on creating the datafile on ADG standby. When you add lot of datafiles in quick succession on primary, standby can fall behind by several minutes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) When new datafile addition fails on standby for any reason, manual fix requires ADG standby to go in "MOUNT" mode, which is an outage. Most common reason for datafile addition to fail is lack of space, once the space issue is addressed manual fix is to use "create datafile as" command which requires standby to be in "MOUNT" mode.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4) Ability to maintain partial physical standby for ADG. When you use RAC for database consolidation, multiple schemas become part of one big physical database. Not all applications have same business priority, it is very natural that only some of those schema's require read only traffic offload to ADG standby. Instead of creating full physical standby, you only want to create standby with the tablespaces you are interested in and it requires quite a bit of manual scripting and processes involved to take care of new datafiles being created on primary which are not part of the interested tablespaces. Oracle can introduce init parameters like "KEEP_TABLESPACES" and "UNKEEP_TABLESPACES" on the standby which can address this issue by managing new datafiles depending on how it falls into these parameters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5) Block cleanout that happens as part of commit on primary database is non logged (not recorded in the redolog), which means commit time block cleanout can't happen on the standby.  This will cause all read queries on ADG standby to keep visiting undo transaction table (one additional undo block visit for every data segment block that is not cleaned out). I think Oracle should log commit time block cleanout so that standby can also see it and this problem will be resolved.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6) Data Guard role switchover from standby to primary causing ADG standby to go from open read only state to "MOUNT" state and then to "OPEN" state causing all established connections to fail, which can extend total database outage. Although it is not significant, every second counts for availability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7) Like "CURRENT_SCN" column in v$database, additional column for corresponding time would make it very easier to determine standby lag in real time. All other options currently available are either expensive to query for multiple executions or not fully reliable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8) When you enable supplemental logging (or force logging) on the primary database, it only gets saved in the control file and this change will not go to the standby unless you regenerate standby control file from the primary or run that command explicitly on the standby too. This can cause huge problem, if you have logical standby or Goldengate being used, after you switchover to the standby. Oracle should record any change in supplemental logging definition to the dictionary also than just to the control file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;9) Ability to determine datafiles impacted by NOLOGGING changes on the standby. Querying "UNRECOVERABLE_TIME" from v$datafile doesn't yield correct result and customer's can falsely rely on this data. Since metadata about blocks impacted by NOLOGGING change is already logged, redo apply on the standby can update standby control file with this information and hence v$datafile can be queried reliably for determining nologging impacted datafiles.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;10) Ability to use multiple processes for redo thread merging as part of redo apply for RAC databases. As redo generation is increasing with each release of Oracle  and customers increasingly using RAC for database consolidation, one process may not be able to merge redo from all the threads fast enough for recovery slaves to consume. It can be a problem if large number of RAC nodes are being used and redo generation in most of the threads is quite high.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've opened enhancement request for some of the above points.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-3926074822222479832?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/3926074822222479832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2011/09/enhancing-active-data-guard.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3926074822222479832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3926074822222479832'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2011/09/enhancing-active-data-guard.html' title='Enhancing Oracle Active Data Guard.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-6454014372657867466</id><published>2011-08-24T00:17:00.000-07:00</published><updated>2011-08-24T01:32:01.581-07:00</updated><title type='text'>Is Oracle ACID compliant database?</title><content type='html'>I attended Jonathan Lewis's NOCOUG session on May 18th, 2011. Towards the end of his session, he demonstrated a test case suspending lgwr process using oradebug, issue commit for an open transaction in another session, and read the same data from third session successfully even though the second session's commit record is not yet preserved to disk.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can read more about it at:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 12px; line-height: 18px; "&gt;&lt;pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; color: rgb(51, 51, 51); "&gt;&lt;a rel="nofollow" href="http://tonyhasler.wordpress.com/2011/08/22/why-is-acid-important/" style="text-decoration: underline; "&gt;http://tonyhasler.wordpress.com/2011/08/22/why-is-acid-important/&lt;/a&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span class="Apple-style-span"&gt;&lt;pre style="font-family: verdana, arial, helvetica, sans-serif; font-size: 12px; line-height: 18px; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; color: rgb(51, 51, 51); "&gt;&lt;a rel="nofollow" href="http://jonathanlewis.wordpress.com/2011/08/19/redo-2/" style="text-decoration: underline; "&gt;http://jonathanlewis.wordpress.com/2011/08/19/redo-2/&lt;/a&gt;&lt;/pre&gt;&lt;pre style="margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; "&gt;&lt;span class="Apple-style-span" &gt;&lt;span class="Apple-style-span" style="font-size: 12px; line-height: 18px;"&gt;http://www.freelists.org/post/oracle-l/ACID&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This basically means Oracle is not fully ACID complaint.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even though some people are categorizing it as an architectural limitation, it is a bug to the customer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In reality it is very rare to run into this problem because:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Quite often we see that the session (or process) committing a transaction is the one moving on to finish other dependent transactions before returning acknowledgment back to the customer.&lt;/div&gt;&lt;div&gt;2) Session reading commit in flight data usually go on to initiate it's own transaction which will either get blocked by the same underlying redo problem or the whole transaction will fail if redo writes are still blocked. &lt;/div&gt;&lt;div&gt;3) Redo write times are typically under couple of milli seconds and hence the exposure window is very narrow.&lt;/div&gt;&lt;div&gt;4) Distributed databases are not that widely used&lt;/div&gt;&lt;div&gt;5) Event based scheduling with changes spanning more than 1 database is not very common, i.e. batch job waiting for an event to happen (can be simple change in status table) and then run the job.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ironically, if an application is just reading data from one database and making decisions on transactions happening on other databases, then using active data guard standby (ADG) for the read part will solve the problem naturally, although the same problem can still happen in theory if both primary and ADG standby go down at the same time (It'd be very interesting to test this out).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Here is my take on solving this problem:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When a query is executed, Oracle computes current SCN and construct read consistent data as of that SCN. This is very fundamental to this problem, do they really have to run the query as of current SCN?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think it won't add too much overhead, if lgwr can post the SCN, to SGA location, up to which it has written redo to the disk from log buffer. Every session executing sql statements can check this memory location for determining on disk SCN up to which redo was flushed and then execute the query as of that SCN. This will solve the problem.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It should not be done for DML's, including select for updates, all of which need to read the data as of current SCN.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By default Oracle should still maintain the current behavior but provide session/system/query level parameter to change the behavior of executing read only queries as of disk SCN.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since Oracle can write redo out of scn order from log buffer to redo log files (recovery process does sort it by SCN before applying the redo), determining the correct on disk SCN may pose a challenge.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-6454014372657867466?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/6454014372657867466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2011/08/is-oracle-acid-compliant-database.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/6454014372657867466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/6454014372657867466'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2011/08/is-oracle-acid-compliant-database.html' title='Is Oracle ACID compliant database?'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-1584337461798187319</id><published>2011-05-18T22:03:00.000-07:00</published><updated>2011-05-18T23:02:38.115-07:00</updated><title type='text'>How to create self managing circular tables</title><content type='html'>One of the most common tasks DBA's deal with often is to enforce purge policies of data life cycle management for tables. Same thing applies for the logging tables DBA's create internally to track or manage monitoring jobs, performance data, stats collection, auditing, etc.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even though logging tables DBA's create don't typically grow to gigabytes in size, it'd be ideal to automate data purge process as per retention requirements.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enter the self managing circular table. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oralce is internally using circular buffer to implement the same for ASH (active session history) and for some of the fixed tables in the dictionary. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another way to do this is by designing the table with retention time depicting columns to use for becoming part of the primary key pair, to locate the interested data, and to merge the new data.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's say the requirement is to track standby lag for all the standby databases in the environment and to maintain this data for one full year. This needs to be logged in a table in the central repository database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;create table  stby_lag_audit (&lt;/div&gt;&lt;div&gt; day_id number not null,&lt;/div&gt;&lt;div&gt; day_hour number not null,&lt;/div&gt;&lt;div&gt; stby_date date,&lt;/div&gt;&lt;div&gt; instance_name varchar2(30) not null,&lt;/div&gt;&lt;div&gt; host_name varchar2(30) not null,&lt;/div&gt;&lt;div&gt; stby_version varchar2(10),&lt;/div&gt;&lt;div&gt; stby_lag number)&lt;/div&gt;&lt;div&gt;/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;create unique index stby_lag_audit_idx on stby_lag_audit (day_id, day_hour, instance_name, host_name)&lt;/div&gt;&lt;div&gt;/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;alter table stby_lag_audit add primary key (day_id, day_hour, instance_name, host_name) using index&lt;/div&gt;&lt;div&gt;/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now all we have to do is use "merge" statement if there is a driving table to insert a new record if no record exists for a given primary key or to update an existing record. Pl/sql or other procedural languages can be used to upsert the data into stby_lag_audit table where there is no driving table.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's say our driving table is stby_lag_info with columns (instance_name, host_name, stby_version, stby_lag).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;merge into stby_lag_audit a using stby_lag_info b&lt;/div&gt;&lt;div&gt;on (a.day_id = to_number(to_char(sysdate, 'DDD')) and&lt;/div&gt;&lt;div&gt;       a.day_hour = to_number(to_char(sysdate, 'HH24')) and&lt;/div&gt;&lt;div&gt;       a.instance_name = b.instance_name and&lt;/div&gt;&lt;div&gt;       a.host_name = b.host_name)&lt;/div&gt;&lt;div&gt;when matched then&lt;/div&gt;&lt;div&gt;update set&lt;/div&gt;&lt;div&gt;a.stby_date = sysdate,&lt;/div&gt;&lt;div&gt;a.stby_version = b.stby_version,&lt;/div&gt;&lt;div&gt;a.stby_lag = b.stby_lag&lt;/div&gt;&lt;div&gt;when not matched then&lt;/div&gt;&lt;div&gt;insert (a.day_id, a.day_hour, a.stby_date, a.instance_name, a.host_name, a.stby_version, a.stby_lag)&lt;/div&gt;&lt;div&gt;values&lt;/div&gt;&lt;div&gt;(to_number(to_char(sysdate, 'DDD')),&lt;/div&gt;&lt;div&gt; to_number(to_char(sysdate, 'HH24')),&lt;/div&gt;&lt;div&gt; sysdate,&lt;/div&gt;&lt;div&gt; b.instance_name,&lt;/div&gt;&lt;div&gt; b.host_name,&lt;/div&gt;&lt;div&gt; b.stby_version,&lt;/div&gt;&lt;div&gt; b.stby_lag)&lt;/div&gt;&lt;div&gt;/&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With this, logging data older than one year gets updated automatically with new data and no need to create any additional jobs to purge the logging data older than retention period.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-1584337461798187319?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/1584337461798187319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2011/05/how-to-create-self-managing-circular.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/1584337461798187319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/1584337461798187319'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2011/05/how-to-create-self-managing-circular.html' title='How to create self managing circular tables'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-769956369807740392</id><published>2011-04-26T11:21:00.000-07:00</published><updated>2011-04-26T11:39:28.160-07:00</updated><title type='text'>How to make sqlprompt bold and blinking</title><content type='html'>In a large database environment, when DBA's use multiple windows to connect to databases, it is quite possible to type command meant for standby database on a live database window and vice versa.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If all live database sqlplus windows have bold and blinking prompt, then it may reduce the chance of making mistakes like above.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This can be achieved by using external table.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p class="MsoNormal"&gt;&lt;span style="color:red"&gt;Run this one time shell command on all database boxes:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;span style="font-size:11.0pt;font-family:&amp;quot;Calibri&amp;quot;,&amp;quot;sans-serif&amp;quot;;mso-fareast-font-family: Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:&amp;quot;Times New Roman&amp;quot;; mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"&gt;echo "`tput blink; tput smso`LIVE`tput rmso;tput sgr0`" &amp;gt; /oracle/custom_sqlprompt.log&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:11.0pt;font-family:&amp;quot;Calibri&amp;quot;,&amp;quot;sans-serif&amp;quot;;mso-fareast-font-family: Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:&amp;quot;Times New Roman&amp;quot;; mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0); "&gt;Add following table to all live databases:&lt;/span&gt;&lt;/div&gt;  &lt;p class="MsoNormal"&gt;create table  custom_sqlprompt (&lt;/p&gt;&lt;p class="MsoNormal"&gt;custom_sqlprompt varchar2(30)&lt;/p&gt;  &lt;p class="MsoNormal"&gt;)&lt;/p&gt;  &lt;p class="MsoNormal"&gt;organization external&lt;/p&gt;  &lt;p class="MsoNormal"&gt;(type oracle_loader&lt;/p&gt;  &lt;p class="MsoNormal"&gt; default directory custom_sqlprompt_dir&lt;/p&gt;  &lt;p class="MsoNormal"&gt; access parameters&lt;/p&gt;  &lt;p class="MsoNormal"&gt;  (&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   records delimited by newline&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   nobadfile&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   nologfile&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   nodiscardfile&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   fields terminated by '\n'&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   missing field values are null&lt;/p&gt;  &lt;p class="MsoNormal"&gt; (CUSTOM_SQLPROMPT)&lt;/p&gt;  &lt;p class="MsoNormal"&gt;  )&lt;/p&gt;  &lt;p class="MsoNormal"&gt; location ('custom_sqlprompt.log')&lt;/p&gt;  &lt;p class="MsoNormal"&gt;)&lt;/p&gt;  &lt;p class="MsoNormal"&gt;reject limit unlimited;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;create public synonym custom_sqlprompt for custom_sqlprompt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;grant select on custom_sqlprompt to public;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="color:red"&gt;Add following entry in glogin.sql or  login.sql:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;column sql_prompt new_value sqlprompt&lt;/p&gt;  &lt;p class="MsoNormal"&gt;set termout off&lt;/p&gt;  &lt;p class="MsoNormal"&gt;select ctype sql_prompt from (select case when controlfile_type = 'STANDBY' then 'STBY' &lt;/p&gt;  &lt;p class="MsoNormal"&gt;                      else &lt;/p&gt;  &lt;p class="MsoNormal"&gt;                      (select custom_sqlprompt from customl_sqlprompt) end as ctype &lt;/p&gt;  &lt;p class="MsoNormal"&gt;                      from v$database);&lt;/p&gt;  &lt;p class="MsoNormal"&gt;set termout on&lt;/p&gt;  &lt;p class="MsoNormal"&gt;set sqlprompt "&amp;amp;sqlprompt&amp;gt;"&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Keep in mind that when you try to open spool files using vi editor, you'll see bunch of control characters, this will not be the case if you use "cat or more" command. You can temporarily disable custom sqlprompt if you don't want to see control characters in the spool file.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-769956369807740392?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/769956369807740392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2011/04/how-to-make-sqlprompt-bold-and-blinking.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/769956369807740392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/769956369807740392'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2011/04/how-to-make-sqlprompt-bold-and-blinking.html' title='How to make sqlprompt bold and blinking'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-3275470518526334856</id><published>2010-09-22T11:40:00.000-07:00</published><updated>2010-10-05T06:36:48.286-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Goldengate GG Xstreams logical standby'/><title type='text'>What is Oracle Goldengate?</title><content type='html'>After Oracle corp. acquiring Goldengate software there is a lot of buzz about Oracle Goldengate and it is one of the hot topics at Oracle open world 2010.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oracle Goldengate can be used as a replication tool, ETL, and even as a DR solution.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oracle Goldengate (GG) is probably the best replication software and it is very easy to configure and deploy it in large scale environment. Here are some of the things you need to be aware of:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) All GG configuration files are ascii text based files. Very easy to make changes but it is prone to human errors in an environment having many DBA's working on it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2) In order to use parallel apply threads, GG breaks down the database transaction into multiple transactions based on the hashing key defined for range split of the data. So, transactional consistency will not be guaranteed during real time but there won't be any data loss, but make sure that your application can tolerate this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) If there is no primary key or unique index exists on any table, GG will use all the columns as supplemental logging key pair for both extracts and replicats. But if you define key columns in the GG extract parameter file and if you don't have the supplemental logging enabled on that key columns combination, then GG will assume missing key columns record data as "NULL", which is a huge deal, and this will introduce logical data corruption on the target.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4) GG started supporting bulk data loads with their 11.1 release but any NOLOGGING data changes will be silently ignored without any warning.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5) GG doesn't support compression on the source database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6) GG does support DDL replication but it is not easy to do selective DDL replication, it replicates every DDL that happens on the source database which is not desirable for some customers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7) Tables being replicated to on the target can also be written to by any other application or DBA's.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8) GG supports ignoring data conflicts for updates after the first instantiation of the target database until it catches up. But it is very easy to forget turning off that parameter and any updates being lost will not be alerted by GG. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;9) GG still works by reverse engineering the Oracle redolog. This may not be totally true with GG 11, but I expect GG to interpret Oracle redo more directly in later versions of 11 or 12.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;10) GG dynamically decides to change the key columns that form the supplemental logging based on the state of primary key (i.e. in VALIDATED or NONVALIDATED  state), which can introduce data corruptions on the target databases as the expected key columns data is missing in the trail files and they will be set to NULL. They now have the patch available for this, you can set "_USEALLKEYCOLUMNS and ALLOWNONVALIDATEDKEYS" parameters in GLOBALS file to get around this problem.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Use cases:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think Oracle is not promoting logical standby as much as they should have. Oracle logical standby guarantees data consistency, data integrity, maintains order of transactions, and doesn't let target database tables to be modified by others which by itself offer great confidence in data quality. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oracle Xstreams offers greatest flexibility and superior performance in extracting data from the source database and applying the same to the target database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For Oracle database upgrades or having a logical DR standby it is better to use Oracle logical standby, use Xstreams if you want more flexibility and high performance in moving data across databases, and use GG for keeping the downstream database up to date for reporting, ETL purposes, or to move data across hybrid databases.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-3275470518526334856?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/3275470518526334856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/what-is-oracle-goldengate.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3275470518526334856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3275470518526334856'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/what-is-oracle-goldengate.html' title='What is Oracle Goldengate?'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-9063696646593213561</id><published>2010-09-06T15:19:00.000-07:00</published><updated>2010-09-23T15:42:22.385-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='standby database'/><category scheme='http://www.blogger.com/atom/ns#' term='11g'/><category scheme='http://www.blogger.com/atom/ns#' term='active data guard'/><category scheme='http://www.blogger.com/atom/ns#' term='_defer_log_boundary_ckpt'/><category scheme='http://www.blogger.com/atom/ns#' term='_defer_log_count'/><title type='text'>Undocumented 11g new features of standby database</title><content type='html'>Apart from the documented new features of being able to use BCT (block change tracking) on the physical standby, ability to use rman duplicate command over the sqlnet to build physical standby from the primary database, here are some of the undocumented features (or change in behavior) introduced as of 11.2.0.1:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Ability to defer log boundary checkpoints ("_defer_log_boundary_ckpt")&lt;/div&gt;&lt;div&gt;2) Ability to define number of logs checkpoint can get behind ("_defer_log_count")&lt;/div&gt;&lt;div&gt;3) Media recovery process now reads maximum of 1024 pending asynch block reads&lt;/div&gt;&lt;div&gt;4) DBWR only do the writes for incremental checkpoint unless free buffer is requested&lt;/div&gt;&lt;div&gt;5) v$recovery_progress view is updated even when only few redo blocks applied by the MRP&lt;/div&gt;&lt;div&gt;6) Removed v$standby_apply_snapshot view.&lt;/div&gt;&lt;div&gt;7) More smoothened incremental recovery checkpoint writes&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The best feature among the above is the ability to defer checkpoints happen at the log boundary.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Parameters "_defer_log_boundary_ckpt" set to "TRUE" by default and "_defer_log_count" set to 2 by default will automatically get in to play only when the physical standby is actively applying the logs instead of waiting for redo or logs to arrive in managed recovery mode.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;During my tests, changing "_defer_log_count" to different values didn't work, Oracle seems to use value 2 only (more testing is needed).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If standby ever falls behind or catching up, it doesn't have to wait for the mandatory checkpoint at the log boundary to finish before applying the next log, which is a big deal if the underlying storage system can only support limited iops.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Media recovery process on the standby will read the data blocks in parallel, Oracle used "db file parallel read" wait event for this until 9i, starting 10g they changed it to "recovery read" wait event. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In 10g, MRP process can keep issuing asynch data block read requests in batches until the overall outstanding block reads for a given MRP process reach 4096. This has caused a havoc in our 10g standbys, as this huge burst of I/O caused underlying SAN to suffer even worse (finally causing corruptions).  They have done it to improve the performance of redo apply.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oracle silently changed it to read 1024 outstanding asynch block reads in 11g.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In order to even out the write activity, dbwr seems to be doing incremental recovery checkpoint writes only, unless dbwr is asked to free up buffers, (you can verify it by setting "_disable_incremental_recovery_ckpt" to true ). By default dbwr is writing once the checkpoint batch size reach 500 as defined by the parameter "_incremental_recovery_ckpt_min_batch".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These are great improvements to the performance of physical standby apply process, but it'd be even better if we can control how many logs checkpoint can defer by so that we can do one big mandatory checkpoint for every few logs and have a big enough sga to control the physical reads, this will improve the performance of standby apply process and reduce the overall I/O. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Only downside to this is, if standby crashes, it'd have to apply all the logs since the last checkpoint. But physical standby for RAC databases will greatly benefit from it especially when you have many nodes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've opened enhancement request 9943911 for the above request.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Overall, these are great improvements Oracle has introduced in 11g.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-9063696646593213561?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/9063696646593213561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/undocumented-11g-features-of-standby.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/9063696646593213561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/9063696646593213561'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/undocumented-11g-features-of-standby.html' title='Undocumented 11g new features of standby database'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-4740626610922501090</id><published>2010-09-04T22:57:00.000-07:00</published><updated>2010-09-23T12:50:09.582-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bct'/><category scheme='http://www.blogger.com/atom/ns#' term='data loss'/><category scheme='http://www.blogger.com/atom/ns#' term='block change tracking'/><category scheme='http://www.blogger.com/atom/ns#' term='rman'/><title type='text'>Beware of data loss in BCT based RMAN backups</title><content type='html'>Block change tracking feature introduced in Oracle 10g is intended for RMAN incremental backups to directly go after the changed data blocks. It can even be used on active data guard standby in 11g.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alex Gorbachev has written excellent white paper about BCT, it is at &lt;a href="http://www.pythian.com/documents/Pythian-oracle-block-change.pdf"&gt;http://www.pythian.com/documents/Pythian-oracle-block-change.pdf&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By default BCT maintains 8 bitmap versions for a given datafile in the change tracking file, background process ctwr process is responsible for maintaining BCT bitmap file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;BCT background process ctwr is hooked up with the redo apply mechanism, as user process executes any transaction on the primary database (internally Oracle will apply the generated redo to the data blocks for making changes to the data blocks) and as media recovery process applies the redo on the standby database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the most popular database backup method is to run rman incremental level 0 image copy of all datafiles, followed by periodic incremental level 1 backups which can be merged with the previous level 0 backup for rolling full backup of the database. BCT is very useful for this purpose.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So BCT is a good feature and it has very light overhead on primary or the standby database and it has been out there for few years now with many customers using it; are there any issues with using this feature?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a possibility of data loss in rman incremantal backups based on BCT.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Data loss scenario 1:&lt;/div&gt;&lt;div&gt;BCT works on the physical standby only when managed recovery is in use and of course active data guard license is needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enable BCT on the standby.&lt;/div&gt;&lt;div&gt;Create a test table on the primary and insert one record.&lt;/div&gt;&lt;div&gt;Identify which datafile the test table belongs to.&lt;/div&gt;&lt;div&gt;Use standby managed recovery to bring it current with the primary.&lt;/div&gt;&lt;div&gt;Stop the managed recovery on the standby.&lt;/div&gt;&lt;div&gt;Take rman incremental backup (backup incremental level 1 for recover of copy with tag 'bct1' tablespace test_tbs)&lt;/div&gt;&lt;div&gt;Insert second row in test table on the primary and switch the logfile.&lt;/div&gt;&lt;div&gt;Apply new logs on the standby using traditional recovery (i.e. recover standby database)&lt;/div&gt;&lt;div&gt;Run the rman incremental backup again with the same command as above&lt;/div&gt;&lt;div&gt;Merge the rman incremental backup with the first image copy (i.e. recover copy of datafile 5 with tab 'bct1')&lt;/div&gt;&lt;div&gt;Offline drop the datafile having the test table on the standby and rename it to the rman backup copy of that datafile.&lt;/div&gt;&lt;div&gt;Now open the standby in read only mode and select from the test table. Second row will be missing.&lt;/div&gt;&lt;div&gt;Bug# 10094823 was opened for this. It is now fixed and the patch is available for 11.2.0.1&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Data loss scenario 2:&lt;/div&gt;&lt;div&gt;If you ever have to refresh a datafile on the standby with later checkpoint time (SCN) and you run the rman incremental backup right after that before bringing rest of the datafiles on the standby to the consistent checkpoint time with the recently refreshed datafile, then there will be a data loss in the just refreshed datafile if the same backup is restored (and rename the just refresh datafile to the rman backup copy) before running the next rman incremental. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This problem can get automatically corrected in the next rman incremental but only if you use the latest backup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Data loss scenario 3:&lt;/div&gt;&lt;div&gt;Offline drop a datafile on the standby&lt;/div&gt;&lt;div&gt;Create a test table on production. Make sure that the table extents are in the above datafile.&lt;/div&gt;&lt;div&gt;Copy the datafile from production with later checkpoint time and leave the datafile in offline status.&lt;/div&gt;&lt;div&gt;Apply few logs on the standby using managed recovery mode.&lt;/div&gt;&lt;div&gt;Online the datafile.&lt;/div&gt;&lt;div&gt;Apply logs on the standby using managed recovery until standby is caught up with live.&lt;/div&gt;&lt;div&gt;Take rman incremental backup of that datafile&lt;/div&gt;&lt;div&gt;Update incremental backup copy with "recover copy of datafile with tag" command&lt;/div&gt;&lt;div&gt;Rename datafile to the rman backup copy&lt;/div&gt;&lt;div&gt;Apply few more logs and open the standby in read only mode&lt;/div&gt;&lt;div&gt;You will now see the test table data missing in that datafile&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Reliability of BCT:&lt;/div&gt;&lt;div&gt;On 11.2.0.1 standby, I've seen managed standby recovery failing to start until BCT is reset at least while running the above tests. I'm working with Oracle support to get all these issues fixed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As of 11.2.0.1, make sure to get the above mentioned issues addressed before using BCT on the standby.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Update (09/23/2010):&lt;/div&gt;&lt;div&gt;I've opened an enhancement request for Oracle support to implement the following features in BCT:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1)  Ability to enable/disable BCT at datafile level.&lt;/div&gt;&lt;div&gt;2)  Make rman to check checkpoint_time seen from BCT for a given datafile with the actual checkpoint_time from the datafile header and use BCT only if both the checkpoint_time's match.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-4740626610922501090?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/4740626610922501090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/beware-of-data-loss-in-bct-based-rman.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/4740626610922501090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/4740626610922501090'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/09/beware-of-data-loss-in-bct-based-rman.html' title='Beware of data loss in BCT based RMAN backups'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-3943024566619563860</id><published>2010-08-09T16:59:00.000-07:00</published><updated>2010-08-09T21:54:05.085-07:00</updated><title type='text'>Internals of online index build</title><content type='html'>Internals of online index build:&lt;br /&gt;Basic premise for online index build, which was introduced in Oracle 8i, was to let DML's to continue while online index build is in progress. It greatly improved database availability for most of the applications. But it suffered from complete hang of DML's during initial and end phases of online index build, which is resolved in 11g.&lt;br /&gt;&lt;br /&gt;The way online index build (OIB) works is by creating an IOT journal table to keep track of changes while the OIB is in progress and merge all the changes from journal table to complete index build operation.&lt;br /&gt;&lt;br /&gt;If I have a table with the structure of (A NUMBER, B NUMBER, C CHAR(100), D NUMBER) and to create index on (A, B, C) column, Oracle would create journal table like:&lt;br /&gt;&lt;br /&gt;create table "ORACLE"."SYS_JOURNAL_18155" (C0 NUMBER, C1 NUMBER, C2 VARCHAR2(100), opcode char(1), partno number, rid rowid, primary key( C0, C1, C2 , rid )) organization index;&lt;br /&gt;&lt;br /&gt;Before 11g, OIB will get in the DML queue to lock the table exclusively while preventing the new DML's to go through, once all the active transactions (ones which were initiated before the OIB) are completed, OIB will create the journal IOT table and release the exclusive table lock (it'll still keep the share lock on the table to prevent any other DDL's) for DML's to continue.&lt;br /&gt;&lt;br /&gt;As part of journal table creation, Oracle would create an internal trigger on the primary table to record all the changes to the journal table. Along with using all the index columns, journal table will add "ROWID" to that list to make it as primary key.&lt;br /&gt;&lt;br /&gt;"OPCODE" column represents the type of operation like "I" for Insert and "D" for Delete.&lt;br /&gt;"PARTNO" column represents partition number of the underlying table.&lt;br /&gt;&lt;br /&gt;Among all the changes to a given row for any of the index key columns, only the most recent change for that record is visible in the journal table. Any update operation of index key columns would be converted to "DELETE" and "INSERT" in the journal table.&lt;br /&gt;&lt;br /&gt;While rest of the user sessions populate journal table with the ongoing changes for index key columns, OIB session would be reading the table in consistent mode (as of the time journal table is created) to create the index followed by the final merge operation.&lt;br /&gt;&lt;br /&gt;During the merge process, Oracle will read the journal table (IOT) leaf blocks from left to right to merge those changes with the index being built. As the journal table leaf block changes are applied, once a leaf block is fully consumed, it's reference will be deleted from the branch block.&lt;br /&gt;&lt;br /&gt;This process will continue until all leaf blocks are consumed and when it comes to the last leaf block, Oracle would stop all the DML's again to do the final merge and drop the journal table before releasing the mode 6 exclsuive table lock.&lt;br /&gt;&lt;br /&gt;As each leaf block is consumed, Oracle would mark each entry as deleted. If more DML's happen while Oracle is doing the merge, it'll do one more pass of walking through the leaf blocks, this process continues until the merge process is all done.&lt;br /&gt;&lt;br /&gt;If there is any long running DML before issuing the OIB, Oracle would wait on the long running transaction and it will prevent upcoming DML's also. This is one of the major problems with OIB. Same thing can happen when it is doing the final merge.&lt;br /&gt;&lt;br /&gt;With 11g, significant changes were introduced to address all these problems.&lt;br /&gt;&lt;br /&gt;Oracle will still wait for long running transactions to complete before starting the OIB process, but it will not block the upcoming DML's. Oracle will not use exclusive table lock (mode 6) for OIB, which will eliminate any DML hang situations.&lt;br /&gt;&lt;br /&gt;As soon as OIB process is initiated, Oracle will create IOT journal table and use internal trigger on the underlying table to keep track of the changes.&lt;br /&gt;&lt;br /&gt;Once the journal table is created and the long running transactions are completed, Oracle will create the index by reading the table blocks in "CURRENT" mode, which means any committed changes in a block happened before the current SCN are read instead of the old way of accessing the blocks as of journal table creation time. This will virtually eliminate chance of running into rollback segment too small errors.&lt;br /&gt;&lt;br /&gt;Oracle will recreate the internal trigger to directly modify the target index structure once the index build is completed (but the merge job is still pending). This means all user sessions will now directly update the target index instead of updating the journal table. Any change coming through would first be checked in the journal table before consolidating the change for the target index (this is best explanied with the example below).&lt;br /&gt;&lt;br /&gt;Record "A" was inserted with rowid "RID" before the merge phase and hence it is tracked in the journal table.&lt;br /&gt;Record "A" was deleted during the merge phase. Now the user session will read the journal table by record "A" with rowid "RID" and apply that change to the target index before deleteing the same record. It will also mark that record as consumed (i.e. deleted) in the IOT journal table leaf block.&lt;br /&gt;&lt;br /&gt;While the user sessions continue to update the target index with the ongoing changes, OIB session will do the merge of journal table changes into the final index, as there will not be any ongoing DML changes being tracked in the journal table, this process will complete faster than before (i.e. pre 11g).&lt;br /&gt;&lt;br /&gt;If you are creating unique index online, that uniqueness will not be enforced in the IOT journal table, but rather in the target index from the initiation of build/merge phase.&lt;br /&gt;&lt;br /&gt;If you are creating either a reverse key index or global hash partitioned index to resolve any index contention (because you have sequentially increasing leading key column), then the OIB process will suffer from the contention because the underlying IOT journal table is created as normal B-tree index (i.e. no reverse key or hash partitioning).&lt;br /&gt;&lt;br /&gt;I've created enhancement request 9912950 for this issue with Oracle support. Hopefully they resolve it in 12g.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-3943024566619563860?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/3943024566619563860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/08/internals-of-online-index-build.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3943024566619563860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3943024566619563860'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/08/internals-of-online-index-build.html' title='Internals of online index build'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-7950753717328543874</id><published>2010-06-15T11:19:00.000-07:00</published><updated>2010-06-15T12:54:27.228-07:00</updated><title type='text'>Full table scan behavior in 11g</title><content type='html'>Before 11gr2, full table scan access path read all the blocks of a table (or index fast full scan) under high water mark into the buffer cache unless either "_serial_direct_read" hidden parameter is set to true or the table/index have default parallelism set.&lt;br /&gt;&lt;br /&gt;In 11gR2, Oracle will automatically decide whether to use direct path reads bypassing buffer cache for serial full table scans.&lt;br /&gt;&lt;br /&gt;For using direct path reads, Oracle first has to write any dirty blocks of the table to disk by issuing object level checkpoint and then read all the blocks from disk into the PGA of server process. If it has to undo any uncommitted transactions to provide read consistency or to do delayed block clean out, Oracle will use server process PGA to construct read consistent block buffers.&lt;br /&gt;&lt;br /&gt;If block clean out has to be performed by the server process using direct path reads for full table scans, it won't write those modified blocks back to disk, so every time you perform full table scan using direct path reads it'd have to keep doing the same work of cleaning out the blocks for every execution. For this reason, it is recommended to manually clean out those blocks by performing full table scan without using direct path reads.&lt;br /&gt;&lt;br /&gt;Following behavior was observed with my testing on 11.2.0.1:&lt;br /&gt;&lt;br /&gt;Hidden parameter "_small_table_threshold" defines the number of blocks to consider a table as small. Any table having more blocks (about 5 times the value of "_small_table_threshold" if you leave it at default value) will automatically use direct path reads for serial full table scans (FTS).&lt;br /&gt;&lt;br /&gt;Hidden parameter "_very_large_object_threshold" defines the upper limit of object size in MB for using direct path reads. There is no effect on FTS behavior just by setting this parameter alone.&lt;br /&gt;&lt;br /&gt;Event 10949 set to any level will disable direct path reads for serial scans only if the size of an object is less then 5 times the size of buffer cache.&lt;br /&gt;&lt;br /&gt;Combination of event 10949 and "_very_large_object_threshold" parameter will disable direct path reads for serial scans if the size of an object is less than 5 times the size of buffer cache or the value of "_very_large_object_threshold" is less than about 0.8 times the size of an object.&lt;br /&gt;&lt;br /&gt;So, if you want to disable direct path reads for serial scans for any object, then set event 10949 at any level and set "_very_large_object_threshold" to greater than the size of largest object in MB.&lt;br /&gt;&lt;br /&gt;Hidden parameter "_serial_direct_read" (or event 10355 set at any level)  set to TRUE will enable direct path reads for all serial scans, unless the table is considered as small table and it's caching attribute is set (by issuing alter table xxxx cache). Remember that any sql statement already parsed and not using direct path reads will continue to do so unless hard parse is forced after setting these parameters. For this reason, it is better not to set these parameters.&lt;br /&gt;&lt;br /&gt;It is not recommended to set any of the above mentioned hidden parameters if you want direct path reads to be used for serial scans, let Oracle decide dynamically based on the size of an object.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-7950753717328543874?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/7950753717328543874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/06/full-table-scan-behavior-in-11g.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/7950753717328543874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/7950753717328543874'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/06/full-table-scan-behavior-in-11g.html' title='Full table scan behavior in 11g'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-5847242965700425261</id><published>2010-05-29T01:05:00.000-07:00</published><updated>2010-05-29T01:58:06.562-07:00</updated><title type='text'>Read only tables in 11g is not fully read only.</title><content type='html'>When any large transaction is committed, it is quite possible that not all blocks it modified are cleaned out and these blocks have to be cleaned out before any data in them can be retrieved. But what happens if you open the database in read only mode, or make table/tablespace read only.&lt;br /&gt;&lt;br /&gt;All the blocks that require a clean out will be done in shadow process PGA memory when parallel query option or direct path reads are used.&lt;br /&gt;&lt;br /&gt;Blocks will be clean out but not written to disk when the database is opened in read only mode or tablespace in read only mode.&lt;br /&gt;&lt;br /&gt;But after the table is put in read only mode, any further select queries against this table that require block cleanout (dirty blocks) will be written to the disk.  In this sense, it is a surprise that read only table can have dirty buffers which will be written to disk. It is definitely the right thing to do.&lt;br /&gt;&lt;br /&gt;Oracle can safely ignore any block clean out operations for read only tables and tablespaces as it is given that there can't be any other open DML transactions against them.  I'll try to open an enhancement request for this.&lt;br /&gt;&lt;br /&gt;Until this issue is fixed, make sure to manually clean out the blocks (by running full scans of the table) before you put any tablespace in read only mode to avoid repeated clean out of the same blocks later on which would incur more performance overhead.&lt;br /&gt;&lt;br /&gt;Also, be aware that in 11g by default Oracle will use direct path reads for full table scans if the table size is large enough as dictated by _small_table_threshold/_very_large_object_threshold,  you can use event 10949 at level 1 to disable direct path reads for serial full table scans (parallel query option will still use direct path reads).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-5847242965700425261?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/5847242965700425261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/05/read-only-tables-in-11g-is-not-fully.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5847242965700425261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5847242965700425261'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/05/read-only-tables-in-11g-is-not-fully.html' title='Read only tables in 11g is not fully read only.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-5144090462653068921</id><published>2010-05-28T22:47:00.000-07:00</published><updated>2010-05-29T00:37:41.288-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ora_rowscn oracle bug weirdness rowdependencies dual about'/><title type='text'>All about ora_rowscn</title><content type='html'>SCN information has always been maintained at the block level as long as it have some data in it. Ora_rowscn basically piggyback on that fact to expose SCN (or timestamp) conservatively when a block has been updated.&lt;br /&gt;&lt;br /&gt;When a transaction is committed Oracle will revisit either all or few blocks, it has modified as part of the transaction, to mark end of transaction as long as those block buffers are available in the buffer cache. Rest of the blocks will be cleaned out during subsequent access of those blocks as part of any future transaction. During block clean out operation, if the transaction information is not available in the undo segments, Oracle will mark transaction in that block with the SCN of first available transaction in the undo segments. It is this SCN that will be reported for ora_rowscn.&lt;br /&gt;&lt;br /&gt;Some weirdness of selecting ora_rowscn from dual:&lt;br /&gt;&lt;br /&gt;13:58:23 SQL&gt; show rel&lt;br /&gt;release 1102000100&lt;br /&gt;13:58:28 SQL&gt;  select ora_rowscn from dual;&lt;br /&gt;&lt;br /&gt;ORA_ROWSCN&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;13:58:32  SQL&gt; select ora_rowscn, sysdate from dual;&lt;br /&gt;&lt;br /&gt;ORA_ROWSCN SYSDATE&lt;br /&gt;----------  ---------------&lt;br /&gt;        27-MAY-10&lt;br /&gt;&lt;br /&gt;13:58:42 SQL&gt; select  ora_rowscn, dummy from dual;&lt;br /&gt;&lt;br /&gt;ORA_ROWSCN D&lt;br /&gt;---------- -&lt;br /&gt;    1329 X&lt;br /&gt;&lt;br /&gt;13:58:48 SQL&gt; select * from dual where ora_rowscn  &gt; 1;&lt;br /&gt;&lt;br /&gt;D&lt;br /&gt;-&lt;br /&gt;X&lt;br /&gt;&lt;br /&gt;13:58:58 SQL&gt; select 1 from dual  where ora_rowscn &gt; 1;&lt;br /&gt;select 1 from dual where ora_rowscn &gt; 1&lt;br /&gt;            *&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-00600: internal error code,  arguments: [qkeIsExprReferenced1], [], [], [], [], [], [], [], [], [],  [], []&lt;br /&gt;&lt;br /&gt;Opened bug# 9761357 for the above issue.&lt;br /&gt;&lt;br /&gt;Problems with ora_rowscn:&lt;br /&gt;&lt;br /&gt;1) bug# 9761357 for the above issue&lt;br /&gt;2) bug# 5270479 for not doing ora_rowscn predicate checking in the current version of the block&lt;br /&gt;3) returning null ora_rowscn when rowdependencies is enabled and querying data from the modified data blocks in an open transaction.&lt;br /&gt;4) Different ora_rowscn values can be reported over time when the underlying block has not been modified.&lt;br /&gt;5) Reporting same ora_rowscn for all the records in a given block when not all those records were changed as part of that commit SCN. This is only when rowdependencies is not used.&lt;br /&gt;&lt;br /&gt;Problem #2:&lt;br /&gt;This will basically prevent us from using ora_rowscn for optimistic locking unless following work around is used.&lt;br /&gt;&lt;br /&gt;Either use one of the columns being modified in the predicate along with using ora_rowscn predicate or use something like (ora_rowscn+length(column_being_modified) = ora_rowscn_value+length(column_being_modified). But this will not work when other columns are updated by a competing transaction which blocked our transaction, in this case we will update the same record again but not the same columns. If this is not desirable, then don't use ora_rowscn for implementing optimistic locking until the current bug is fixed.&lt;br /&gt;&lt;br /&gt;problem #3:&lt;br /&gt;Oracle records SCN for each row in the block when ROWDEPENDENCIES is enabled. Since current SCN can only be recorded for each row when the transaction is not committed (lets call this DSCN), ITL transaction entries in the block is updated with the commit SCN later when the transaction is committed (read above for further explanation of block clean out).  DSCN recorded for each row in the block will not be cleaned out as part of normal block clean out process.&lt;br /&gt;&lt;br /&gt;Commit SCN (or the upper bound SCN) reported in the block ITL enrties is used for reporting ora_rowscn of all the rows corresponding to an ITL entry modified in the past. But if a given ITL entry needs to be reused for other transactions later on, commit SCN of ITL entry will be used to update DSCN of all the rows it modified in the past before that ITL entry can be reused.&lt;br /&gt;&lt;br /&gt;Oracle can report current SCN recorded with each row, instead of returning null Ora_rowscn, when the data from the modified blocks is queried as part of an open transaction. I don't see any open bug created for this one yet.&lt;br /&gt;&lt;br /&gt;Problem #4:&lt;br /&gt;Different ora_rowscn values can be reported over time even though the underlying block contents have not been modified. There are 2 reasons for this:&lt;br /&gt;&lt;br /&gt;1) If that block was modified with direct path operations, like CTAS and insert with append, and the transaction commit SCN information is not available in the undo segments. Direct path loads write above HMW (and hence very little undo unless indexes exist) and commit SCN is only updated in few blocks when the transaction is completed. When the remaining blocks are accessed again and the corresponding direct path transaction information is not available in any UNDO segments, Oracle will report conservative SCN (least SCN available from the undo transaction table) but it will not clean out the blocks (i.e. all these blocks loaded using direct path operations will remain clean with no commit (or upper bound) SCN available in them).&lt;br /&gt;&lt;br /&gt;2) Using direct path operations (or parallel query option) to access the data blocks which needs to be cleaned out. This is very evident in 11g since direct path reads are used for serial full table scans when the table size is big enough. You can change this behavior by setting "alter system set events '10949 trace name context forever, level 1'". It will still do the block clean out but it does this in PGA memory of user process. Over time, as the transaction state information is aged out from the undo segments, different ora_rowscn's will be reported.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Problem #5:&lt;br /&gt;It is not a problem per say, but rather the way it is implemented. Use ROWDEPENDENCIES if you want SCN information at row level more accurately.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Use cases:&lt;br /&gt;&lt;br /&gt;You can use ora_rowscn for:&lt;br /&gt;1) To implement optimistic locking&lt;br /&gt;2) To report active time window of table data (i.e. how far back in time data in the table is modified). This information can be used for any archival or data purge analysis.&lt;br /&gt;3) To figure out the last time table data is changed.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-5144090462653068921?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/5144090462653068921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2010/05/all-about-orarowscn.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5144090462653068921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5144090462653068921'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2010/05/all-about-orarowscn.html' title='All about ora_rowscn'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-5194646579316439460</id><published>2009-06-19T00:43:00.000-07:00</published><updated>2009-06-22T11:50:39.110-07:00</updated><title type='text'>Oracle new feature enhancement requests for 11gr2 and above</title><content type='html'>Here is my wish list:&lt;br /&gt;&lt;br /&gt;1) Ability to create composite partitioned local indexes when the table is not composite partitioned and first level partitioning for index and table is same.&lt;br /&gt;&lt;br /&gt;  If we have a table range partitioned by TIME_CREATED column and column like "ID" is generated off of a sequence then the local index on "ID" column is prone to index contention as DML concurrency goes up.&lt;br /&gt;&lt;br /&gt;  Creating reverse key indexes would resolve the contention but would limit our ability to range scans and it also introduces more physical I/O for DML's and select queries.&lt;br /&gt;&lt;br /&gt;  If we can partition index on "ID" column by TIME_CREATED and do subpartition by hash on "ID", it will not only resolve index contention and would also give us the ability to do the range scans along with less physical I/O for DML's and select queries.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2) Ability to use In memory undo and private redo for short transactions when supplemental logging is enabled.&lt;br /&gt;&lt;br /&gt;  Right now, when supplemental logging is enabled, in memory undo is siltenly turned off automatically. This provides more scalability to OLTP type of database applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3) Adding more intelligence in determining amount of space reserved for ITL entries during index leaf block splits.&lt;br /&gt;&lt;br /&gt;  Right now, if you have an index on a sequence based column and when sudden surge in DML's occurs, Oracle would reserve as much space as possible for all the concurrent transactions in the form of ITL entries and the same amount of space reserved for ITL slots in future leaf block splits even though the spike in DML's may be one time activity.&lt;br /&gt;&lt;br /&gt;It should basically add a timestamp to when the maximum number of ITL slots (and also maintain average number of ITL's used) were used and if it was done more than an hour ago (or a day ago) then reserve&lt;br /&gt;  only the space required for average number of ITL's used for future leaf block splits.&lt;br /&gt;&lt;br /&gt;This would avoid wasting lot of space when the transaction concurrency spikes are very rare (we should be altering index with more initrans in this case anyways).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;4) Often times, DBA's create function based mod index to resolve right most leaf block index contention by dividing index column (say "ID") into few buckets (i.e. create index on (mod(ID,10), ID)). This requires change in application for all the sql queries belong to this table and hence it may force DBA's to create reverse key indexes, which is not the ideal solution for big tables.&lt;br /&gt;&lt;br /&gt;Just like the way Oracle is recognizing upper or lower functions, when used on an indexed column, to consider index access path, it'd be better if Oracle can recognize mod function also (i.e. convert "WHERE ID=10" to "WHERE ID=10 and mod(id,10)=0" automatically depending on the way mod function index was used.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5) Ability to define index leaf block split records ratio, right now, Oracle put's last record in the new leaf block and the rest will be left in the current leaf block when the right most leaf block is split due to insertion of maximum key value, and use 50-50 ratio for all other leaf block split operations.&lt;br /&gt;&lt;br /&gt;When application is designed to address index contention of sequence based column's by dividing them into several buckets (like mod index explained above) and grow them sequentially in each bucket, then Oracle would be wasting lot of space when 50-50 leaf block splits happen.&lt;br /&gt;&lt;br /&gt;By having ability to define leaf block split ratio (not for right most leaf block split) then indexes will be more skinnier (for this used case) and hence improved performance due to the possibility of caching more index blocks.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;6) Ability to define index affinity. If we have a table with (account#, phone_number,  pin_number, etc) and have indexes on (account#, phone_number) and (account#, pin_number), then if most executed queries use the first index and if we have a query with "where account# = ?" then oracle can use first or second index based on the optimizer statistics.&lt;br /&gt;&lt;br /&gt;In this case, even if statistics indicate that the second index is better, just from caching perspective first index is ideal. We need to have ability to alter an particular index to more affinity either by having alter index command (which will be enforced when leading columns of the indexes were used as predicates and more than one index has this.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;7) Ability to enforce delayed (or on demand) global index maintenance. With one process trying to sort all the indexed columns from the table partition being altered and deleting them from the index requires significant amount of time and if we have multiple partition level changes to be done in a given partition maintenance window, it can run into peak business time or it can pose other operational issues like what happens if instance is crashed, etc.&lt;br /&gt;&lt;br /&gt;  Since object_id is part of rowid to be stored in global indexes, Oracle can simply mark an object_id as "INVALID" and when user tries to query the data belong to that object, then either perform the cleanup in those leaf blocks at that time or ignore the entries belong to that object. This way, global index maintenance will be like local indexes, with the only difference of on demand cleanup of global index leaf block entries (and we need to have ability to explicitly perform the cleanup of leaf blocks entries).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;8) Include access and filter predicates of v$sql_plan in DBA_HIST_SQL_PLAN; right now Oracle doesn't record those column values in any awr base tables.&lt;br /&gt;&lt;br /&gt;9) Record the first snap_id of when a sql statement first executed on the database in awr base table (DBA_HIST_SQLTEXT). This information is recorded in statspack base table STATS$SQLTEXT.LAST_SNAP_ID, but not in any awr tables. This is useful in figuring out what changed when a new application rolls out.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;10) Record out of normal entries from ash buffer into awr table (DBA_HIST_ACTIVE_SESS_HISTORY) instead of just picking one sample id on 10 second interval. DBA can define threshold for out of normal activity in terms of number of sessions waiting on any given waitevent, etc. This will be very helpful in doing root cause analysis and for any scalability analysis.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;11) Honour "_db_block_max_cr_dba" parameter which has a default value of 6, limiting how many clone copies of one block can exist in buffer cache. I've see it going over 10 in many situation. Cloning a buffer is needed for read consistency purposes, but having more copies of them than 6 is hardly ever a requirement and Oracle should reuse an existing clone&lt;br /&gt;   if no other process is pinned it (this by itself resolves the problem). Not doing so can increase cache buffer chains latch contention since the latch is needed to be held longer to figure out the right clone buffer image to use.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;12) Record redo usage per sql statement in v$sql. This will be very useful for troubleshooting and root cause analysis.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;13) Use direct path reads when parallel query option is used with rowid range scans, i.e. select /*+ rowid(w) parallel(w, 2) */ ... where rowid between :1 and :2". Right now, Oracle used scattered reads to read the blocks into buffer cache, but using direct path reads bypassing buffer cache has it's used cases.&lt;br /&gt;&lt;br /&gt;   Since Oracle is doing direct path reads for each extent of the segment, it can easily get the extent boundaries from the rowid range and hence should be able to direct path reads.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-5194646579316439460?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/5194646579316439460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2009/06/oracle-new-feature-enhancement-requests.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5194646579316439460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/5194646579316439460'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2009/06/oracle-new-feature-enhancement-requests.html' title='Oracle new feature enhancement requests for 11gr2 and above'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-567227643232571969</id><published>2009-04-29T23:33:00.000-07:00</published><updated>2009-04-30T00:09:17.313-07:00</updated><title type='text'>Cheap and light way to get record count frequently in a big table</title><content type='html'>How to get count(*) without really scanning all the records in a huge table:&lt;br /&gt;&lt;br /&gt;If your requirement is to frequently get count of records in a huge table and to get it quickly, then you may use the following method to achieve it.  One real life requirement example is to find the count of records in an exception queue table to determine how many application threads need to be started to process the exception queue for meeting SLA's.&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:85%;color:navy;"   &gt;&lt;span style=";font-family:Arial;font-size:10;color:navy;"   &gt;Basically, we would  create a new tracking table to be populated though trigger on the main table to maintain  the counters for any inserts or deletes on the main table. We also need an  Oracle sequence to distribute the counter trackers for better concurrency and  locking mechanism. In essence, counter will be incremented by 1 for an insert  and decremented by 1 for a delete statement.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Oracle Materialized view does similar thing but it is not scalable for a busy table (you will see enqueue contention).&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:85%;color:navy;"   &gt;&lt;span style=";font-family:Arial;font-size:10;color:navy;"   &gt;create table test_tmp(id1 varchar2(30), id2 number, id3 number);&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;create table test_cnt (id1 varchar2(30), id2 number, c1 char(25),&lt;br /&gt;c2 number, c3 number) initrans 50; #This is the tracking table&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;create unique index test_cnt_idx on test_cnt(id1, id2, c2);&lt;br /&gt;Index created.&lt;br /&gt;&lt;br /&gt;create sequence test_cnt_seq start with 1 increment by 1 maxvalue 100 cycle cache 20;&lt;br /&gt;Sequence created.&lt;br /&gt;&lt;br /&gt;create or replace trigger test_tr before insert or delete on test_tmp&lt;br /&gt;for each row&lt;br /&gt;declare&lt;br /&gt;v1 number;&lt;br /&gt;begin&lt;br /&gt;select test_cnt_seq.nextval into v1 from dual;&lt;br /&gt;if inserting then&lt;br /&gt;update test_cnt set c3 = c3+1 where id1=:new.id1 and id2 = :new.id2 and c2=v1;&lt;br /&gt;if sql%notfound then&lt;br /&gt;insert into test_cnt values (:new.id1, :new.id2, 'X', v1, 1);&lt;br /&gt;end if;&lt;br /&gt;end if;&lt;br /&gt;if deleting then&lt;br /&gt;update test_cnt set c3 = c3-1 where id1=:old.id1 and id2 = :old.id2 and c2=v1;&lt;br /&gt;if sql%notfound then&lt;br /&gt;insert into test_cnt values (:old.id1, :new.id2, 'X', v1, -1);&lt;br /&gt;end if;&lt;br /&gt;end if;&lt;br /&gt;end;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;Trigger created.&lt;br /&gt;&lt;br /&gt;insert into test_tmp values ('A', 1, 1);&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;insert into test_tmp values ('B', 2, 2);&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;insert into test_tmp values ('C', 3, 3);&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;insert into test_tmp values ('D', 4, 4);&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;insert into test_tmp values ('E', 5, 5);&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;Commit complete.&lt;br /&gt;&lt;br /&gt;select id1, sum(c3) from test_cnt group by id1 having sum(c3) &gt; 0;&lt;br /&gt;&lt;br /&gt;id1 SUM(C3)&lt;br /&gt;------------------------------ ----------&lt;br /&gt;D 1&lt;br /&gt;A 1&lt;br /&gt;B 1&lt;br /&gt;C 1&lt;br /&gt;E 1&lt;br /&gt;&lt;br /&gt;delete from test_tmp where id3=5;&lt;br /&gt;1 row deleted.&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;Commit complete.&lt;br /&gt;&lt;br /&gt;select id1, sum(c3) from test_cnt group by id1 having sum(c3) &gt; 0;&lt;br /&gt;&lt;br /&gt;id1 SUM(C3)&lt;br /&gt;------------------------------ ----------&lt;br /&gt;D 1&lt;br /&gt;A 1&lt;br /&gt;B 1&lt;br /&gt;C 1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:85%;color:navy;"   &gt;&lt;span style=";font-family:Arial;font-size:10;color:navy;"   &gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:85%;color:navy;"   &gt;&lt;span style=";font-family:Arial;font-size:10;color:navy;"   &gt;Triggers have it's downside and they can fire multiple times for the same record in a single sql statement execution as per  http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:11504247549852&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:85%;color:navy;"   &gt;&lt;span style=";font-family:Arial;font-size:10;color:navy;"   &gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-567227643232571969?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/567227643232571969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2009/04/cheap-and-lightweight-way-to-frequently.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/567227643232571969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/567227643232571969'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2009/04/cheap-and-lightweight-way-to-frequently.html' title='Cheap and light way to get record count frequently in a big table'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-3198894669959118954</id><published>2009-04-28T00:36:00.000-07:00</published><updated>2009-04-28T00:56:31.342-07:00</updated><title type='text'>Beware of index contention after mass delete and insert</title><content type='html'>One insert can cause an outage on your system:&lt;br /&gt;&lt;br /&gt;If you delete large number of records from a table having an index and insert the same records as part of another transaction, then one of the subsequent inserts would have to perform tremendous amount of work while splitting an index block as it has to find a free block from the free list but the blocks reused from delete-insert operation were still there in free list and hence this operation would have to unlink them one by one until it finds an all empty block.&lt;br /&gt;&lt;br /&gt;This can be demonstrated easily with the following test case (on 10.2.0.3 with 8k block size and no assm tablespace):&lt;br /&gt;create tablespace idx1 datafile '?/dbs/idx1.dbf' size 500M&lt;br /&gt;segment space management manual&lt;br /&gt;extent management local uniform size 10M;&lt;br /&gt;&lt;br /&gt;create table idx1(a number) tablespace idx1;&lt;br /&gt;&lt;br /&gt;create index idx1_idx on idx1 (a) tablespace idx1 pctfree 0;&lt;br /&gt;&lt;br /&gt;insert into idx1 select rownum from all_objects, all_objects where rownum &lt;= 250000;&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;create table idx2 tablespace idx1 as select * from idx1 where 1=2;&lt;br /&gt;&lt;br /&gt;insert into idx2&lt;br /&gt;select * from idx1 where rowid in&lt;br /&gt; (select rid from&lt;br /&gt;    (select rid, rownum rn from&lt;br /&gt;       (select rowid rid from idx1 where a between 10127 and 243625 order by a)&lt;br /&gt;    )&lt;br /&gt;  where mod(rn, 250) = 0&lt;br /&gt; )&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;delete from idx1 where a between 10127 and 243625;&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;insert into idx1 select * from idx2;&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;insert into idx1 select 250000+rownum from all_objects where rownum &lt;= 126;&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;select sql_id, executions, buffer_gets, disk_reads, cpu_time, elapsed_time, rows_processed, sql_text from v$sql&lt;br /&gt;where sql_text like '%insert%idx1%' and sql_text not like '%v$sql%';&lt;br /&gt;&lt;br /&gt;insert into idx1 values (251000);&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;&lt;br /&gt;select sql_id, executions, buffer_gets, disk_reads, cpu_time, elapsed_time, rows_processed, sql_text from v$sql&lt;br /&gt;where sql_text like '%insert%idx1%' and sql_text not like '%v$sql%';&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you run the above statements, you will see that one insert statement consuming over 900 buffer gets. While it is in the middle of getting 900 blocks (some of them may be on the disk), all other inserts would have to wait for it to finish. &lt;br /&gt;&lt;br /&gt;If you either coalesce or shrink the index with an alter statement, then this problem will go away (alternatively you can also do online index rebuild), but the best way to deal with it is by doing the delete and insert in one transaction. &lt;br /&gt;&lt;br /&gt;I've opened bug# &lt;span style="font-family:helvetica;"&gt;8446989 with Oracle support on this one, hopefully it will be fixed soon.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;Sai.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-3198894669959118954?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/3198894669959118954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2009/04/beware-of-index-contention-after-mass.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3198894669959118954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/3198894669959118954'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2009/04/beware-of-index-contention-after-mass.html' title='Beware of index contention after mass delete and insert'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-7424706609806461703</id><published>2007-12-08T00:15:00.000-08:00</published><updated>2007-12-08T10:46:14.540-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='buffer cache _serial_direct_read direct path read full table scan parallel'/><title type='text'>How to bypass buffer cache for full table scans.</title><content type='html'>&lt;span style="color: rgb(255, 102, 102);"&gt;How to reduce impact of full table scans:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Full table scans (FTS) have their place, even on OLTP databases, and they are not evil when used properly.  FTS are unavoidable on most DW databases. So apart from popular belief of possible increased response time and increased I/O, is there any impact on the database?&lt;br /&gt;&lt;br /&gt;FTS on a large table can effectively pollute the buffer cache by aging out blocks in the buffer cache otherwise needed by other sessions, even though the FTS blocks are placed at LRU end. It will also have increased latch activity (cache buffer chains, cache buffer lru, etc.). It can also create many CR cloned buffers, if there are any blocks for that table already in the cache.&lt;br /&gt;&lt;br /&gt;All these problems can be solved by setting one hidden parameter "_serial_direct_read = true" for that session or at the system level. The beauty of this parameter is that once execution plan is generated for any sql with this setting on, same behavior will be exhibited even when it is not set as long as the cursor is not re-parsed.&lt;br /&gt;&lt;br /&gt;"_serial_direct_read = true" basically use "direct path reads" for single threaded multi block read operations like FTS. Oracle will first issue fast checkpoint at object level to write all dirty buffers of that object to the disk and perform direct path reads in to the PGA of shadow process.&lt;br /&gt;This will be especially useful for batch jobs.&lt;br /&gt;&lt;br /&gt;Oracle introduced event 10379 to do the same for rowid range scans but never really implemented it fully. Of course you can always use parallel query option to achieve the same thing with multiple threads, but you will be consuming additional resources on the system.&lt;br /&gt;&lt;br /&gt;00:50:19 SQL&gt; alter session set "_serial_direct_read" = true;&lt;br /&gt;Session altered.&lt;br /&gt;&lt;br /&gt;00:50:19 SQL&gt; select avg(id) from test;&lt;br /&gt;&lt;br /&gt;00:50:32 SQL&gt; select event, total_waits from v$session_event&lt;br /&gt;00:50:40   2   where sid = (select sid from v$mystat where rownum = 1)&lt;br /&gt;00:50:40   3   and event like '%read%';&lt;br /&gt;&lt;br /&gt;EVENT                          TOTAL_WAITS&lt;br /&gt;------------------------------ -----------&lt;br /&gt;direct path read                       124&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-7424706609806461703?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/7424706609806461703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2007/12/how-to-bypass-buffer-cache-for-full.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/7424706609806461703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/7424706609806461703'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2007/12/how-to-bypass-buffer-cache-for-full.html' title='How to bypass buffer cache for full table scans.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-6571733611005968308</id><published>2007-05-23T22:58:00.000-07:00</published><updated>2007-05-24T07:53:16.420-07:00</updated><title type='text'>Librarycache changes in 10g</title><content type='html'>&lt;span style="color: rgb(255, 0, 0);"&gt;Shared pool improvements:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Oracle introduced multiple shared pool latches (up to 7) in Oracle 9i, this is to reduce shared pool latch contention and the impact of shared pool fragmentation is localized to that latched pool only.&lt;br /&gt;&lt;br /&gt;With Oracle 10g R2, some types of chunk (like sqlarea) allocation sizes are standardized to reduce shared pool fragmentation. Parent and child cursor heaps are allocated explicitly.&lt;br /&gt;&lt;br /&gt;Since all the linked list structures (for buffer headers, etc) are mapped within the defined shared pool size, be sure to allocate more memory (may be 20%) to the shared pool.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Librarycache improvements:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Oracle implemented mutexes for some of the library cache latching operations, this will reduce the library cache latch gets tremendously if you are using bind variables in sql statements.&lt;br /&gt;&lt;br /&gt;Implications of this change is greater scalability &amp;amp; availability, and increased shadow server process memory usage.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-6571733611005968308?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/6571733611005968308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2007/05/librarycache-changes-in-10g.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/6571733611005968308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/6571733611005968308'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2007/05/librarycache-changes-in-10g.html' title='Librarycache changes in 10g'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-116539236880262186</id><published>2006-12-06T00:06:00.000-08:00</published><updated>2006-12-06T09:21:44.196-08:00</updated><title type='text'>Finding table extents after losing a datafile in LMT</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;What it means of losing a datafile in locally managed tablespace:&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finding the list of tables and the number of extents stored in a lost datafile could prove very important under some situations; you could either resort to old copies of those tables or make better decision about the impact of lost datafile.&lt;br /&gt;&lt;br /&gt;This is not a problem in dictionary managed tablespace as all the extent related information is stored in dictionary objects,  i.e., DBA_EXTENTS and DBA_SEGMENTS.&lt;br /&gt;&lt;br /&gt;As all the extents map related information is stored in the actual datafiles, losing a datafile could very well mean losing extents information partially or fully.&lt;br /&gt;&lt;br /&gt;If the datafile lost don't have any segment headers, then you can find all the segments and it's extent information from the following query:&lt;br /&gt;&lt;br /&gt;select count(*), sum(blocks), sum(bytes) from dba_extents where file_id = &amp;file_id and&lt;br /&gt;segment_name in (select segment_name from dba_segments where extents is not null and header_file  = &amp;amp;&amp;amp;file_id);&lt;br /&gt;&lt;br /&gt;If the datafile lost have some segment headers stored in it, you can find the list of those segments by:&lt;br /&gt;&lt;br /&gt;select segment_name, segment_type, owner from dba_segments where extents is null and header_file = &amp;file_id);&lt;br /&gt;&lt;br /&gt;And hence, it is highly advisable to backup dba_extents periodically.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-116539236880262186?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/116539236880262186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/12/finding-table-extents-after-losing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/116539236880262186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/116539236880262186'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/12/finding-table-extents-after-losing.html' title='Finding table extents after losing a datafile in LMT'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-115044001062765968</id><published>2006-06-15T23:40:00.000-07:00</published><updated>2006-06-15T23:40:10.676-07:00</updated><title type='text'>How to update joining column using MERGE.</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;Updating joining column in MERGE command:&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let's say you want to merge "SOURCE" table into "TARGET" table with "ID" column as joining condition and you want to update "ID" column too.&lt;br /&gt;&lt;br /&gt;merge into TARGET using&lt;br /&gt;(select target.rowid rid, source.* from SOURCE, TARGET&lt;br /&gt;  where source.id = target.id(+)&lt;br /&gt;) SOURCE&lt;br /&gt;on (TARGET.rowid = SOURCE.rid)&lt;br /&gt;when matched then&lt;br /&gt;update set target.id = source.id, target.column2 = source.column2, ....&lt;br /&gt;when not matched then&lt;br /&gt;insert values (source.id, source.column2, ....)&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In fact this is the only to come up with a plan using INDEX_FFS.&lt;br /&gt;&lt;br /&gt;Say, you have about 90% updates and 10% inserts to go into TARGET table from SOURCE table, and you do have an index on "TARGET.ID" column, but you are not intending to update "ID" column.&lt;br /&gt;&lt;br /&gt;If doing full table scan of "TARGET" table is more expensive than doing index fast full scan on "TARGET.ID" with table lookups by rowid, then above mentioned merge command would give you the best plan that Oracle is unable to come up with if you dont use inline view subquery in place of "SOURCE" table.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-115044001062765968?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/115044001062765968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/06/how-to-update-joining-column-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/115044001062765968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/115044001062765968'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/06/how-to-update-joining-column-using.html' title='How to update joining column using MERGE.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114407553236968662</id><published>2006-04-03T07:45:00.000-07:00</published><updated>2006-04-03T07:51:13.486-07:00</updated><title type='text'>How much shared_pool_reserved_size?</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;What is shared_pool_reserved_size:&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Shared pool memory is allocated in chunks and as shared pool fragments with time you will see more smaller chunks being allocated for all sql statements requiring hard parse.&lt;br /&gt;&lt;br /&gt;So, to reduce shared pool fragmentation due to large memory allocation requirements, Oracle reserves a minimum of 5% shared pool size for such allocations.&lt;br /&gt;&lt;br /&gt;Any chunk allocation with more than "_shared_pool_reserved_min_alloc = 4400" bytes, would go to reserved shared pool unless such memory allocation can be satisfied from the shared pool memory without aging out any other chunks.&lt;br /&gt;&lt;br /&gt;Interestingly all sessions connected to the database require 27224 bytes (in Oracle 9i) each from shared pool, which is called "session param v" chunk, and it has to come out from one chunk.&lt;br /&gt;&lt;br /&gt;If you have an application which keeps closing and opening new connections, you would need to set minimum shared_pool_reserved_size as follows:&lt;br /&gt;&lt;br /&gt;Maximum of  (shared_pool_size*(5/100), "sessions" * 27224)&lt;br /&gt;&lt;br /&gt;This is one more reason why it is a good idea to use connection pooling and don't bother much about above equation.&lt;br /&gt;&lt;br /&gt;You can check the utilization of shared pool reserved size by querying v$shared_pool_reserved view.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114407553236968662?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114407553236968662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/04/how-much-sharedpoolreservedsize.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114407553236968662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114407553236968662'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/04/how-much-sharedpoolreservedsize.html' title='How much shared_pool_reserved_size?'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114377924962708276</id><published>2006-03-30T20:27:00.000-08:00</published><updated>2006-03-30T23:12:17.733-08:00</updated><title type='text'>Difference between SCN and checkpoint.</title><content type='html'>&lt;span style="text-decoration: underline;"&gt;SCN and checkpoint:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;System change number(SCN) is represented with SCN_WRAP and SCN_BASE. Whenever SCN_BASE reaches 4294967290 (2 power 32), SCN_WRAP goes up by one and SCN_BASE will be reset to 0. This way you can have a maximum SCN at 1.8E+19.&lt;br /&gt;&lt;br /&gt;SCN = (SCN_WRAP * 4294967290) + SCN_BASE&lt;br /&gt;&lt;br /&gt;Checkpoint number is the SCN number at which all the dirty buffers are written to the disk, there can be a checkpoint at object/tablespace/datafile/database level.&lt;br /&gt;&lt;br /&gt;Checkpoint number is never updated for the datafiles of readonly tablespaces.&lt;br /&gt;&lt;br /&gt;Oracle doesn't use any sequence to generate SCN_BASE numbers, it make calls to "kcmgas" function (per Steve Adams), which is a permanent memory structure for the instance. It is reported in v$sysstat under "calls to kcmgas" name.&lt;br /&gt;&lt;br /&gt;Does Oracle do either crash recovery or transaction recovery after shutdown abort if the checkpoint was taken right before the instance crash?&lt;br /&gt;&lt;br /&gt;Yes, Oracle perform rollforward first if there are any changes beyond last checkpoint and rollback any uncommitted transactions.&lt;br /&gt;&lt;br /&gt;SCN numbers are being reported at frequent intervals by SMON in "SMON_SCN_TIME" table.&lt;br /&gt;&lt;br /&gt;You can also query v$transaction to arrive at the SCN for that transaction.&lt;br /&gt;&lt;br /&gt;Controlfile records information about last checkpoint and archived sequence along with other information.&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114377924962708276?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114377924962708276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/difference-between-scn-and-checkpoint.html#comment-form' title='23 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114377924962708276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114377924962708276'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/difference-between-scn-and-checkpoint.html' title='Difference between SCN and checkpoint.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114233504279226350</id><published>2006-03-14T03:17:00.000-08:00</published><updated>2006-03-14T03:17:22.830-08:00</updated><title type='text'>What is "index scans kdiixs1 "  statistic?</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;Statistic "index scans kdiixs1"&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On Oracle 9.2.0.5:&lt;br /&gt;&lt;p&gt;stat# 206 -&gt; Index fetch by key&lt;br /&gt;stat# 207 -&gt; index scans kdiixs1&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Index fetch by key:&lt;br /&gt;This statistic will be incremented for each "INDEX (UNIQUE SCAN)". This also applies to all DML statements which has "INDEX(UNIQUE SCAN)" in the execution plan.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Index scans kdiixs1:&lt;br /&gt; This statistic is incremented for each index range scan operation, except for index fat full scans, index full scan, and index unique scan.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Both of the above statistics will be incremented for index lookups against recursive statements also.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;create table t(a number not null, b number);&lt;br /&gt;create index t_idx1 on t(a):&lt;br /&gt;create unique index t_idx2 on t(b);&lt;br /&gt;analyze table t compute statistics;&lt;br /&gt;insert into t select rownum, rownum+50000 from dba_objects;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:29:56 SQL&gt; select * from v$sesstat where sid=181 and statistic#&lt;br /&gt;between 203 and 207&lt;br /&gt;23:29:56   2  /&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  SID STATISTIC#      VALUE&lt;br /&gt;----- ---------- ----------&lt;br /&gt;  181        203          4&lt;br /&gt;  181        204          0&lt;br /&gt;  181        205          0&lt;br /&gt;  181        206         21&lt;br /&gt;  181        207         66&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:29:56 SQL&gt; select count(*) from t where a=17;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  COUNT(*)&lt;br /&gt;----------&lt;br /&gt;         1&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:30:16 SQL&gt; @t&lt;br /&gt;23:30:17 SQL&gt; select * from v$sesstat where sid=181 and statistic#&lt;br /&gt;between 203 and 207&lt;br /&gt;23:30:17   2  /&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  SID STATISTIC#      VALUE&lt;br /&gt;----- ---------- ----------&lt;br /&gt;  181        203          4&lt;br /&gt;  181        204          0&lt;br /&gt;  181        205          0&lt;br /&gt;  181        206         21&lt;br /&gt;  181        207         67&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:30:17 SQL&gt; select a.a, b.a from t a, t b where a.a=b.a and a.a=100;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;         A          A&lt;br /&gt;---------- ----------&lt;br /&gt;       100        100&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:30:24 SQL&gt; @t&lt;br /&gt;23:30:26 SQL&gt; select * from v$sesstat where sid=181 and statistic#&lt;br /&gt;between 203 and 207&lt;br /&gt;23:30:26   2  /&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  SID STATISTIC#      VALUE&lt;br /&gt;----- ---------- ----------&lt;br /&gt;  181        203          4&lt;br /&gt;  181        204          0&lt;br /&gt;  181        205          0&lt;br /&gt;  181        206         21&lt;br /&gt;  181        207         69&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:30:26 SQL&gt; select a.a, b.a from t a, t b where a.a=b.a and a.a=100;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;         A          A&lt;br /&gt;---------- ----------&lt;br /&gt;       100        100&lt;br /&gt;&lt;/p&gt;&lt;p&gt;23:30:29 SQL&gt; @t&lt;br /&gt;23:30:31 SQL&gt; select * from v$sesstat where sid=181 and statistic#&lt;br /&gt;between 203 and 207&lt;br /&gt;23:30:31   2  /&lt;br /&gt;&lt;/p&gt;  SID STATISTIC#      VALUE&lt;br /&gt;----- ---------- ----------&lt;br /&gt;  181        203          4&lt;br /&gt;  181        204          0&lt;br /&gt;  181        205          0&lt;br /&gt;  181        206         21&lt;br /&gt;  181        207         71&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114233504279226350?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114233504279226350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/what-is-index-scans-kdiixs1-statistic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114233504279226350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114233504279226350'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/what-is-index-scans-kdiixs1-statistic.html' title='What is &quot;index scans kdiixs1 &quot;  statistic?'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114212461885898036</id><published>2006-03-11T16:50:00.000-08:00</published><updated>2006-03-13T22:55:47.630-08:00</updated><title type='text'>How to predict Index blevel and when to rebuild.</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;Determining Index blevel's&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Depth of an index(blevel plus one) would determine the minimum number of consistent gets required for Index lookups in any joins and in index range scans. In nested loop joins, Oracle would always read index root block into process PGA memory and hence one less block to read from an index in every loop iteration. For queries like "where x between :a and :b" Oracle would always do leaf block level walk throughs, hence caching any index blocks is not required here.&lt;br /&gt;&lt;br /&gt;So, index blevel is one of the key indicators of performance of sql queries doing Index range scans.&lt;br /&gt;&lt;br /&gt;Index depth is one of the prime factor involved in determining whether to rebuild an index. In most cases, you wouldn't need to rebuild any index. You may consider doing it when you have one off major delete/update done on that table.&lt;br /&gt;&lt;br /&gt;You can  more or less predict when would blevel of an index would go from one level to another level.  If you have right hand index it is very easy to predict blevel, otherwise it becomes very hard. Here is a simple test case.&lt;br /&gt;&lt;br /&gt;create table t(a number);&lt;br /&gt;create index t_idx on t(a);&lt;br /&gt;insert into t select rownum from all_objects where rownum &lt;= 500;&lt;br /&gt;analyze index t_idx compute statistics;&lt;br /&gt;select blevel from user_indexes where index_name='T_IDX';&lt;br /&gt;&lt;br /&gt;You would see around 540 rows to fit in one Index 8K blocksize. So, Index blevel would change when the number of index records reach power(540, blevel). Bear in mind that the number of indexed columns, their datatype, and the column size would dictate the number of records fit in one index block.&lt;br /&gt;&lt;br /&gt;Blevel       #Records&lt;br /&gt; 0                     540&lt;br /&gt;1                      29K&lt;br /&gt;2                     150 million&lt;br /&gt;3                     8.5 billion&lt;br /&gt;&lt;br /&gt;See the difference in number of records from blevel 2 to 3, that is the reason why you would hardly see index blevel going beyond 3.&lt;br /&gt;&lt;br /&gt;If you have one off major deletes/updates done on your table, then consider rebuilding the affected indexes on that table. It all depends on the way you access and modify key values of that index.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114212461885898036?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114212461885898036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/how-to-predict-index-blevel-and-when.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114212461885898036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114212461885898036'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/how-to-predict-index-blevel-and-when.html' title='How to predict Index blevel and when to rebuild.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114205931245857982</id><published>2006-03-10T22:41:00.000-08:00</published><updated>2006-03-10T22:56:05.783-08:00</updated><title type='text'>Weirdness of v$datafile on a standby db.</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;Here are some oddities of v$datafile on a standby&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Oracle gets content of v$datafile from controlfile, but on a standby database "STATUS" column wouldn't get updated in some scenarios. All datafiles created after the standby controlfile creation timestamp would get "RECOVER" status as they get pushed to the standby database. But how to find out if the datafile is offline or online?&lt;br /&gt;&lt;br /&gt;V$datafile_header is the answer. Whenever we query v$datafile_header, Oracle would visit all datafile header blocks, and it gives us the right "STATUS" of datafiles.&lt;br /&gt;&lt;br /&gt;What you see in v$datafile for Checkpoint_change# and Checkpoint_time may not be correct if you refresh that datafile from the primary and the recovery on those datafiles haven't started yet, and here also v$datafile_header is an answer.&lt;br /&gt;&lt;br /&gt;If a datafile is offline, it's tablespace number will be "0" in v$datafile_header, and you need to use v$datafile for this purpose.&lt;br /&gt;&lt;br /&gt;Also, Unrecoverable_change# and Unrecoverable_time columns would never get updated in v$datafile on any standby database.&lt;br /&gt;&lt;br /&gt;How do you know where to start for the recovery, you can in general use v$recover_file. But on a standby database, you may not see entry for some datafiles in v$recover_file, and v$datafile_header is an answer here also.&lt;br /&gt;&lt;br /&gt;You may occasionally get ORA-235 "controlfile fixed table inconsistent due to concurrent update" while querying v$datafile, then again you can get most of that information with more correctness from v$datafile_header.&lt;br /&gt;&lt;br /&gt;You may sometimes find using rule hint may help your query run faster against v$datafile, but try it only if you get ORA-235 error.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114205931245857982?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114205931245857982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/weirdness-of-vdatafile-on-standby-db.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114205931245857982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114205931245857982'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/weirdness-of-vdatafile-on-standby-db.html' title='Weirdness of v$datafile on a standby db.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114205080304476532</id><published>2006-03-10T20:20:00.000-08:00</published><updated>2009-04-28T00:34:33.135-07:00</updated><title type='text'>How to split a table into rowid ranges.</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;This script helps immensely to copy any table with "out of row" lob columns in it  across dblink. This can also be used for CTAS over dblinks, any parallel  insert/delete/update operations.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;This is not a duplicate to what  Oracle parallel query option does, it basically fills in the gaps of Oracle  parallel query option.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;For example:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;Out of row lobs takes hell lot of  time to be copied over to another table, Oracle parallel query doesn’t help here  across dblinks.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;You can’t get parallel queries on  both source and target tables of CTAS operation across db  links.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;Good amount of limitations on Oracle  parallel DML operations.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;By using this script you can split  any table into up to 255 rowid ranges.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;-- This script spits desired number of rowid ranges to be used for any parallel operations.&lt;br /&gt;-- Best to use it for copying a huge table with out of row lob columns in it or CTAS/copy the data over db links.&lt;br /&gt;-- This can also be used to simulate parallel insert/update/delete operations.&lt;br /&gt;-- Maximum number of rowid ranges you can get here is 255.&lt;br /&gt;-- Doesn't work for partitioned tables, but with minor changes it can be adopted easily.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;-- Doesn't display any output if the total table blocks are less than rowid ranges times 128.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;-- It can split a table into more ranges than the number of extents&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;set verify off&lt;br /&gt;undefine rowid_ranges&lt;br /&gt;undefine seg_name&lt;br /&gt;undefine owner&lt;br /&gt;set head off&lt;br /&gt;set pages 0&lt;br /&gt;set trimspool on&lt;br /&gt;&lt;br /&gt;select decode(rn3, &amp;amp;&amp;amp;rowid_ranges, 'rowid &gt;= ''', 'rowid between ''')||&lt;br /&gt;   sys.dbms_rowid.rowid_create(1, id, file_id, new_bid, 0)||&lt;br /&gt;   decode(rn3, &amp;amp;&amp;amp;rowid_ranges, '''', ''' and ''')||&lt;br /&gt;   decode(rn3, &amp;amp;&amp;amp;rowid_ranges, null, sys.dbms_rowid.rowid_create(1, id, fid2, bid2-1, 99999))||&lt;br /&gt;   decode(rn3, &amp;amp;&amp;amp;rowid_ranges, null, '''') from  (select id, file_id, new_bid, rn3, lead(file_id) over (order by rn3) fid2,&lt;br /&gt;     lead(new_bid) over (order by rn3) bid2&lt;br /&gt;from&lt;br /&gt;(select file_id, block_id, rn3,&lt;br /&gt;       round(block_id + (equi_blks * (rn5 - 1))) new_bid, id&lt;br /&gt;from&lt;br /&gt; (select file_id, block_id, equi_blks, rn3,&lt;br /&gt;         row_number() over (partition by rn1 order by rn3) rn5&lt;br /&gt;  from&lt;br /&gt;   (select file_id, block_id, equi_blks, rn1, rn3,&lt;br /&gt;           row_number() over (partition by rn3 order by rn1) rn4&lt;br /&gt;    from&lt;br /&gt;     (select file_id, block_id, sum2, equi_blks, rn1&lt;br /&gt;      from&lt;br /&gt;       (select file_id, block_id, sum2, rn1, equi_blks,&lt;br /&gt;               row_number() over (partition by rn1 order by sum2) rn2&lt;br /&gt;        from&lt;br /&gt;         (select file_id, block_id, sum1, sum2, (sum1/&amp;amp;&amp;amp;rowid_ranges) equi_blks,&lt;br /&gt;                 trunc((sum2 * &amp;amp;&amp;amp;rowid_ranges)/(sum1 + 1))+1 rn1&lt;br /&gt;          from&lt;br /&gt;           (select relative_fno file_id, block_id, sum(blocks) over () sum1,&lt;br /&gt;                   sum(blocks) over (order by relative_fno, block_id) sum2&lt;br /&gt;            from dba_extents&lt;br /&gt;            where&lt;br /&gt;            segment_name = upper('&amp;amp;&amp;amp;seg_name') and&lt;br /&gt;            owner = upper('&amp;amp;&amp;amp;amp;amp;amp;owner') and&lt;br /&gt;            256 &gt; &amp;amp;&amp;amp;rowid_ranges&lt;br /&gt;           )&lt;br /&gt;          where&lt;br /&gt;          sum1 &gt; (128 * &amp;amp;&amp;amp;rowid_ranges)&lt;br /&gt;         )&lt;br /&gt;       )&lt;br /&gt;      where rn2 = 1&lt;br /&gt;     ) a,&lt;br /&gt;     (select rownum rn3 from (select 1 from dual group by cube (1, 1, 1, 1, 1, 1, 1, 1))&lt;br /&gt;      where rownum &lt;= &amp;amp;&amp;amp;rowid_ranges          ) b         where         b.rn3 &lt;= a.rn1        )       where       rn4 = 1      ) c,      (select max(data_object_id) id       from       dba_objects       where       object_name = upper('&amp;amp;seg_name') and       owner = upper('&amp;amp;owner') and       data_object_id is not null      ) d    )  ) / &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;-------------------------&gt; End of the sql script&lt;br /&gt;-------------------------&gt; &lt;-----------------------&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;--- Update on April 28th 2009, above script has a bug, please use the corrected script below:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;select&lt;br /&gt; 'rowid between '''||sys.dbms_rowid.rowid_create(1, d.oid, c.fid1, c.bid1, 0)||''' and '''||&lt;br /&gt; sys.dbms_rowid.rowid_create(1, d.oid, c.fid2, c.bid2, 9999)||''''&lt;br /&gt;from&lt;br /&gt; (select&lt;br /&gt;  distinct b.rn,&lt;br /&gt;  first_value(a.fid) over (partition by b.rn order by a.fid, a.bid rows between unbounded preceding and unbounded following) fid1,&lt;br /&gt;  last_value(a.fid) over (partition by b.rn order by a.fid, a.bid rows between unbounded preceding and unbounded following) fid2,&lt;br /&gt;  first_value(decode(sign(range2-range1), 1, a.bid+((b.rn-a.range1)*a.chunks1), a.bid)) over&lt;br /&gt;   (partition by b.rn order by a.fid, a.bid rows between unbounded preceding and unbounded following) bid1,&lt;br /&gt;  last_value(decode(sign(range2-range1), 1, a.bid+((b.rn-a.range1+1)*a.chunks1)-1, (a.bid+a.blocks-1))) over&lt;br /&gt;   (partition by b.rn order by a.fid, a.bid rows between unbounded preceding and unbounded following) bid2&lt;br /&gt;  from&lt;br /&gt;   (select&lt;br /&gt;    fid,&lt;br /&gt;    bid,&lt;br /&gt;    blocks,&lt;br /&gt;    chunks1,&lt;br /&gt;    trunc((sum2-blocks+1-0.1)/chunks1) range1,&lt;br /&gt;    trunc((sum2-0.1)/chunks1) range2&lt;br /&gt;    from&lt;br /&gt;     (select /*+ rule */&lt;br /&gt;      relative_fno fid,&lt;br /&gt;      block_id bid,&lt;br /&gt;      blocks,&lt;br /&gt;      sum(blocks) over () sum1,&lt;br /&gt;      trunc((sum(blocks) over ())/&amp;amp;&amp;amp;rowid_ranges) chunks1,&lt;br /&gt;      sum(blocks) over (order by relative_fno, block_id) sum2&lt;br /&gt;      from dba_extents&lt;br /&gt;      where&lt;br /&gt;      segment_name = upper('&amp;amp;&amp;amp;segment_name') and&lt;br /&gt;      owner = upper('&amp;amp;&amp;amp;owner')&lt;br /&gt;     )&lt;br /&gt;    where&lt;br /&gt;    sum1 &gt; &amp;amp;&amp;amp;rowid_ranges&lt;br /&gt;   ) a,&lt;br /&gt;   (select rownum-1 rn from dual connect by level &lt;= &amp;amp;&amp;amp;rowid_ranges) b&lt;br /&gt;   where&lt;br /&gt;   b.rn between a.range1 and a.range2&lt;br /&gt; ) c,&lt;br /&gt; (select max(data_object_id) oid from dba_objects&lt;br /&gt;  where object_name = upper('&amp;amp;&amp;amp;segment_name') and owner = upper('&amp;amp;&amp;amp;owner') and data_object_id is not null&lt;br /&gt; ) d&lt;br /&gt;/&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span style="font-family:Arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114205080304476532?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114205080304476532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/how-to-split-table-into-rowid-ranges.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114205080304476532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114205080304476532'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/how-to-split-table-into-rowid-ranges.html' title='How to split a table into rowid ranges.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23846373.post-114204929238807271</id><published>2006-03-10T19:54:00.000-08:00</published><updated>2006-03-10T19:59:06.926-08:00</updated><title type='text'>Quick summary of locks and skip v$lock.</title><content type='html'>&lt;a href="http://sai-oracle.blogspot.com/"&gt;Lock summary without accessing v$lock&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;  Script to report summary of lock activity by waiters on the database.&lt;br /&gt;  OBJ              -&gt; Table: waitevent: p1: p2: locktype: ROWID.&lt;br /&gt;  CMD             -&gt; Type of command being waited on.&lt;br /&gt;  SES_CNT     -&gt; Number of sessions waiting.&lt;br /&gt;  HASH           -&gt; Hash value being waited on.&lt;br /&gt;  MODULE      -&gt; Module they are coming from.&lt;br /&gt;  Written by Sai */&lt;br /&gt;&lt;br /&gt;col obj for a70&lt;br /&gt;col cmd for a19&lt;br /&gt;col module for a15&lt;br /&gt;set lines 160&lt;br /&gt;set trimspool on&lt;br /&gt;&lt;br /&gt;select obj, cmd, count(*) as ses_cnt, min(hash_value) hash, module&lt;br /&gt;from&lt;br /&gt;(select decode(sign(ROW_WAIT_OBJ#), 1,&lt;br /&gt;                      (select object_name from dba_objects where object_id=ROW_WAIT_OBJ# and data_object_id is not null)&lt;br /&gt;                      ,-1, 'UNKNOWN', 'UNKNOWN') || ':' ||&lt;br /&gt;           w.event || ':' || w.p2 || ':' || w.p3 || ':' ||&lt;br /&gt;           chr(bitand(p1, -16777216)/16777215) || chr(bitand(p1, 16711680)/65535) || ':''' ||&lt;br /&gt;           decode(sign(ROW_WAIT_OBJ#), 1, dbms_rowid.rowid_create(1, (select data_object_id from dba_objects&lt;br /&gt;                                                                where object_id = ROW_WAIT_OBJ# and data_object_id is not null),&lt;br /&gt;                                                                ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#), 'No rowid') || '''' as obj,&lt;br /&gt;           decode(command, 2, 'INSERT', 6, 'UPDATE', 7, 'DELETE', 182, 'UPDATE INDEXES', 3, 'SELECT FOR UPDATE', command) as cmd,&lt;br /&gt;           decode(sign(sql_hash_value), 1, sql_hash_value, prev_hash_value) hash_value,&lt;br /&gt;           module&lt;br /&gt; from&lt;br /&gt; v$session s, v$session_wait w&lt;br /&gt; where&lt;br /&gt; status = 'ACTIVE' and&lt;br /&gt; lockwait is not null and&lt;br /&gt; s.sid = w.sid)&lt;br /&gt;group by obj, cmd, module&lt;br /&gt;order by 3, 1&lt;br /&gt;/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/23846373-114204929238807271?l=sai-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sai-oracle.blogspot.com/feeds/114204929238807271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/quick-summary-of-locks-and-skip-vlock.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114204929238807271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23846373/posts/default/114204929238807271'/><link rel='alternate' type='text/html' href='http://sai-oracle.blogspot.com/2006/03/quick-summary-of-locks-and-skip-vlock.html' title='Quick summary of locks and skip v$lock.'/><author><name>Saibabu Devabhaktuni</name><uri>http://www.blogger.com/profile/06538436896963786125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry></feed>
