<?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-36335310</id><updated>2012-01-23T03:07:55.955-08:00</updated><category term='Tuning'/><category term='MOS'/><category term='WTF'/><category term='XML'/><category term='RDBMS'/><category term='sqlplus'/><category term='RAC'/><category term='RMAN'/><category term='Linux'/><category term='Grid Manager'/><category term='ASM'/><title type='text'>ORACLE Cookies</title><subtitle type='html'>This blog is mainly about ORACLE, a great database server. I am going to put here my thoughts about various ORACLE topics, tips &amp;amp; tricks and other cool stuff as far as these technologies are concerned.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>56</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-36335310.post-4750133947391410007</id><published>2011-01-26T01:32:00.000-08:00</published><updated>2011-01-26T01:32:08.859-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MOS'/><title type='text'>Light HTML Oracle Support Site</title><content type='html'>The standard Flash GUI of the actual &lt;a href="http://support.oracle.com"&gt;Oracle Support&lt;/a&gt; site is driving me crazy. For a guy like me, used to work especially with console applications, addicted to &lt;a href="http://www.vim.org/"&gt;VIM&lt;/a&gt; and browsing using &lt;a href="http://vimperator.org/vimperator"&gt;Vimperator&lt;/a&gt;, having this Flash site in front of me really hurts. It hurts when I have to move my hand to click something with the mouse, it hurts when I cannot go back to the previous page, it hurts... it hurts... it hurts! Oracle Support is not a game, it doesn't need animation, video or other such things Flash is good at. &lt;br /&gt;&lt;br /&gt;Okey, enough with all these complaints! If you don't like Flash, or your browser simply doesn't support it you may switch to the plain html interface: &lt;a  href="https://supporthtml.oracle.com"&gt;https://supporthtml.oracle.com&lt;/a&gt;. Isn't it cool? Just have a look: &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_gGEccZZIMqc/TT_o_BoMlUI/AAAAAAAAADc/13VarW-V510/s1600/html-mos.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="254" width="400" src="http://2.bp.blogspot.com/_gGEccZZIMqc/TT_o_BoMlUI/AAAAAAAAADc/13VarW-V510/s400/html-mos.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now I can use my beloved Vimperator and, of course, &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/flashblock/"&gt;Flashblock&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;However, I have to point out the limitations.The HTML option does not include the following functionality, which is only available in the Flash version of My Oracle Support:&lt;br /&gt;&lt;br /&gt;    * Systems&lt;br /&gt;    * Projects&lt;br /&gt;    * Healthchecks&lt;br /&gt;    * Patch Advice &amp; Recommendations&lt;br /&gt;    * Inventory Reporting&lt;br /&gt;    * OnDemand Portal, Service Request and RFC Functionality &lt;br /&gt;    * CRM OnDemand Service Requests &amp; Knowledge&lt;br /&gt;&lt;br /&gt;As far as I'm concerned, I didn't use those features anyway therefore I'm good!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-4750133947391410007?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/4750133947391410007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=4750133947391410007' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/4750133947391410007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/4750133947391410007'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2011/01/light-html-oracle-support-site.html' title='Light HTML Oracle Support Site'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gGEccZZIMqc/TT_o_BoMlUI/AAAAAAAAADc/13VarW-V510/s72-c/html-mos.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7973556160244213</id><published>2011-01-24T02:27:00.000-08:00</published><updated>2011-01-25T00:26:51.377-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>crs_stat pretty print on RAC 11.2</title><content type='html'>I really don't like the way &lt;code&gt;crs_stat -t&lt;/code&gt; displays RAC status information on my 11.2.0.2 database. For example, one of my instances are down. Can you figure out this looking at the output below?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[grid@owl ~]$ crs_stat -t&lt;br /&gt;Name           Type           Target    State     Host        &lt;br /&gt;------------------------------------------------------------&lt;br /&gt;ora.DATA.dg    ora....up.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....ER.lsnr ora....er.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....N1.lsnr ora....er.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....N2.lsnr ora....er.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....N3.lsnr ora....er.type ONLINE    ONLINE    owl         &lt;br /&gt;ora.asm        ora.asm.type   ONLINE    ONLINE    hen         &lt;br /&gt;ora.cvu        ora.cvu.type   ONLINE    ONLINE    hen         &lt;br /&gt;ora.gns        ora.gns.type   ONLINE    ONLINE    hen         &lt;br /&gt;ora.gns.vip    ora....ip.type ONLINE    ONLINE    hen         &lt;br /&gt;ora.gsd        ora.gsd.type   OFFLINE   OFFLINE               &lt;br /&gt;ora....SM2.asm application    ONLINE    ONLINE    hen         &lt;br /&gt;ora....EN.lsnr application    ONLINE    ONLINE    hen         &lt;br /&gt;ora.hen.gsd    application    OFFLINE   OFFLINE               &lt;br /&gt;ora.hen.ons    application    ONLINE    ONLINE    hen         &lt;br /&gt;ora.hen.vip    ora....t1.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....network ora....rk.type ONLINE    ONLINE    hen         &lt;br /&gt;ora.oc4j       ora.oc4j.type  ONLINE    ONLINE    hen         &lt;br /&gt;ora.ons        ora.ons.type   ONLINE    ONLINE    hen         &lt;br /&gt;ora....SM1.asm application    ONLINE    ONLINE    owl         &lt;br /&gt;ora....WL.lsnr application    ONLINE    ONLINE    owl         &lt;br /&gt;ora.owl.gsd    application    OFFLINE   OFFLINE               &lt;br /&gt;ora.owl.ons    application    ONLINE    ONLINE    owl         &lt;br /&gt;ora.owl.vip    ora....t1.type ONLINE    ONLINE    owl         &lt;br /&gt;ora.poc.db     ora....se.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....uci.svc ora....ce.type ONLINE    ONLINE    hen         &lt;br /&gt;ora....ry.acfs ora....fs.type ONLINE    ONLINE    hen         &lt;br /&gt;ora.scan1.vip  ora....ip.type ONLINE    ONLINE    hen         &lt;br /&gt;ora.scan2.vip  ora....ip.type ONLINE    ONLINE    hen         &lt;br /&gt;ora.scan3.vip  ora....ip.type ONLINE    ONLINE    owl         &lt;/pre&gt;The resource "ora.poc.db" is ONLINE therefore no red flags you might say. Well, bad luck: the database is up &amp; running but with only one instance. The other one is dead. The database is policy managed but I want to be aware if all instances from the pool are running. How can we figure this out? Not a very big deal, just issue: "crsctl status resource". You'll get something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;NAME=ora.poc.db&lt;br /&gt;TYPE=ora.database.type&lt;br /&gt;TARGET=OFFLINE, ONLINE&lt;br /&gt;STATE=OFFLINE, ONLINE on hen&lt;/pre&gt;&lt;br /&gt;Looking at TARGET and STATE is clear that something is OFFLINE and the red flag pops up right away. Of course, "crsctl status resource" command has the same problem as crs_stat when it comes to pretty print the result. It also has a tabular format (see the -t switch) but it'a a little bit verbose as it also displays the local resources status. But hey, do you remember Note 259301.1? It was about an awk script used for parsing the crs_stat output and displaying it in a nicer way. Okey, let's take that script and change it to take the output of the "crsctl status resource" command. I'm not an awk expert, but the following script is working pretty well:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/ksh&lt;br /&gt;#&lt;br /&gt;# Sample 10g CRS resource status query script&lt;br /&gt;#&lt;br /&gt;# Description:&lt;br /&gt;#    - Returns formatted version of crs_stat -t, in tabular&lt;br /&gt;#      format, with the complete rsc names and filtering keywords&lt;br /&gt;#   - The argument, $RSC_KEY, is optional and if passed to the script, will&lt;br /&gt;#     limit the output to HA resources whose names match $RSC_KEY.&lt;br /&gt;# Requirements:&lt;br /&gt;#   - $ORA_CRS_HOME should be set in your environment &lt;br /&gt;&lt;br /&gt;RSC_KEY=$1&lt;br /&gt;QSTAT=-u&lt;br /&gt;AWK=/bin/awk    # if not available use /usr/bin/awk&lt;br /&gt;&lt;br /&gt;# Table header:echo ""&lt;br /&gt;$AWK \&lt;br /&gt;  'BEGIN {printf "%-45s %-10s %-18s\n", "HA Resource", "Target", "State";&lt;br /&gt;          printf "%-45s %-10s %-18s\n", "-----------", "------", "-----";}'&lt;br /&gt;&lt;br /&gt;# Table body:&lt;br /&gt;$ORACLE_HOME/bin/crsctl status resource | $AWK \&lt;br /&gt; '&lt;br /&gt;function ltrim(s) { sub(/^[ \t]+/, "", s); return s }&lt;br /&gt;function rtrim(s) { sub(/[ \t]+$/, "", s); return s }&lt;br /&gt;function trim(s)  { return rtrim(ltrim(s)); }&lt;br /&gt;&lt;br /&gt;  BEGIN { FS="="; state = 0; }&lt;br /&gt;  $1~/NAME/ &amp;&amp; $2~/'$RSC_KEY'/ {appname = $2; state=1};&lt;br /&gt;  state == 0 {next;}&lt;br /&gt;  $1~/TARGET/ &amp;&amp; state == 1 {apptarget = $2; split(apptarget, atarget, ","); state=2;}&lt;br /&gt;  $1~/STATE/ &amp;&amp; state == 2 {appstate = $2; split(appstate, astate, ","); state=3;}&lt;br /&gt;  state == 3 { split(appname, a, ","); &lt;br /&gt;               for (i = 1; i &lt;= length(atarget); i++) { &lt;br /&gt;                 printf "%-45s %-10s %-18s\n", appname, trim(atarget[i]), trim(astate[i]) &lt;br /&gt;               }; &lt;br /&gt;               state=0;}'&lt;/pre&gt;And the output is:&lt;pre&gt;[grid@owl ~]$ cs&lt;br /&gt;HA Resource                                   Target     State             &lt;br /&gt;-----------                                   ------     -----             &lt;br /&gt;ora.DATA.dg                                   ONLINE     ONLINE on hen     &lt;br /&gt;ora.DATA.dg                                   ONLINE     ONLINE on owl     &lt;br /&gt;ora.LISTENER.lsnr                             ONLINE     ONLINE on hen     &lt;br /&gt;ora.LISTENER.lsnr                             ONLINE     ONLINE on owl     &lt;br /&gt;ora.LISTENER_SCAN1.lsnr                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.LISTENER_SCAN2.lsnr                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.LISTENER_SCAN3.lsnr                       ONLINE     ONLINE on owl     &lt;br /&gt;ora.asm                                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.asm                                       ONLINE     ONLINE on owl     &lt;br /&gt;ora.cvu                                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.gns                                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.gns.vip                                   ONLINE     ONLINE on hen     &lt;br /&gt;ora.gsd                                       OFFLINE    OFFLINE           &lt;br /&gt;ora.gsd                                       OFFLINE    OFFLINE           &lt;br /&gt;ora.hen.vip                                   ONLINE     ONLINE on hen     &lt;br /&gt;ora.net1.network                              ONLINE     ONLINE on hen     &lt;br /&gt;ora.net1.network                              ONLINE     ONLINE on owl     &lt;br /&gt;ora.oc4j                                      ONLINE     ONLINE on hen     &lt;br /&gt;ora.ons                                       ONLINE     ONLINE on hen     &lt;br /&gt;ora.ons                                       ONLINE     ONLINE on owl     &lt;br /&gt;ora.owl.vip                                   ONLINE     ONLINE on owl     &lt;br /&gt;ora.poc.db                                    OFFLINE    OFFLINE           &lt;br /&gt;ora.poc.db                                    ONLINE     ONLINE on hen     &lt;br /&gt;ora.poc.muci.svc                              ONLINE     ONLINE on hen     &lt;br /&gt;ora.poc.muci.svc                              ONLINE     OFFLINE           &lt;br /&gt;ora.registry.acfs                             ONLINE     ONLINE on hen     &lt;br /&gt;ora.registry.acfs                             ONLINE     ONLINE on owl     &lt;br /&gt;ora.scan1.vip                                 ONLINE     ONLINE on hen     &lt;br /&gt;ora.scan2.vip                                 ONLINE     ONLINE on hen     &lt;br /&gt;ora.scan3.vip                                 ONLINE     ONLINE on owl     &lt;/pre&gt;&lt;br /&gt;Looking at the above output I can clearly see the partial OFFLINE status of my database. From my point of view, is much better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7973556160244213?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7973556160244213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7973556160244213' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7973556160244213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7973556160244213'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2011/01/crsstat-pretty-print-on-rac-112.html' title='crs_stat pretty print on RAC 11.2'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7785943063852010849</id><published>2010-12-14T06:31:00.000-08:00</published><updated>2010-12-14T06:34:50.123-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>Kill a Session From Any Node</title><content type='html'>I really like this new 11g feature which allows the DBA to kill a session despite his session is on a different instance than the instance where the session to be killed resides. The ALTER SYSTEM KILL SESSION statement has been improved and allows specifying the instance number where the session you want to kill is located:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ALTER SYSTEM KILL SESSION 'sid, serial#, @inst_no';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Great!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7785943063852010849?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7785943063852010849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7785943063852010849' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7785943063852010849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7785943063852010849'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/12/kill-session-from-any-node.html' title='Kill a Session From Any Node'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-3613376368712106853</id><published>2010-12-11T01:47:00.000-08:00</published><updated>2010-12-11T01:47:30.652-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>Extending my RAC with a new node</title><content type='html'>I have a 11.2.0.2 database comprised of one node. I especially created it with one node just to have the chance to add another node later. Why? Because I wanted to play with this new GPnP feature. So, despite my RAC was comprised of one node, it was actually a fully functional environment, with GNS, IPMI, CTSAS and a policy managed database. Okey, the process should be straightforward: run some CVU checks to see if the node to be added is ready and then run addNode.sh script from the GI home of the existing RAC node. In my case, the existing node was named "owl" and the node to be added was "hen".&lt;br /&gt;&lt;br /&gt;First of all, I ran:&lt;br /&gt;&lt;pre&gt;[grid@owl bin]$ cluvfy stage -pre nodeadd -n hen&lt;br /&gt;&lt;br /&gt;Performing pre-checks for node addition&lt;br /&gt;&lt;br /&gt;Checking node reachability...&lt;br /&gt;Node reachability check passed from node "owl"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Checking user equivalence...&lt;br /&gt;User equivalence check passed for user "grid"&lt;br /&gt;&lt;br /&gt;Checking node connectivity...&lt;br /&gt;&lt;br /&gt;Checking hosts config file...&lt;br /&gt;&lt;br /&gt;Verification of the hosts config file successful&lt;br /&gt;&lt;br /&gt;Check: Node connectivity for interface "eth0"&lt;br /&gt;Node connectivity passed for interface "eth0"&lt;br /&gt;&lt;br /&gt;Node connectivity check passed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Checking CRS integrity...&lt;br /&gt;&lt;br /&gt;CRS integrity check passed&lt;br /&gt;&lt;br /&gt;Checking shared resources...&lt;br /&gt;&lt;br /&gt;Checking CRS home location...&lt;br /&gt;The location "/u01/app/11.2.0.2/grid" is not shared but is present/creatable on all nodes&lt;br /&gt;Shared resources check for node addition passed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Checking node connectivity...&lt;br /&gt;&lt;br /&gt;Checking hosts config file...&lt;br /&gt;&lt;br /&gt;Verification of the hosts config file successful&lt;br /&gt;&lt;br /&gt;Check: Node connectivity for interface "eth0"&lt;br /&gt;Node connectivity passed for interface "eth0"&lt;br /&gt;&lt;br /&gt;Check: Node connectivity for interface "eth1"&lt;br /&gt;Node connectivity passed for interface "eth1"&lt;br /&gt;&lt;br /&gt;Node connectivity check passed&lt;br /&gt;&lt;br /&gt;Total memory check passed&lt;br /&gt;Available memory check passed&lt;br /&gt;Swap space check passed&lt;br /&gt;Free disk space check passed for "owl:/tmp"&lt;br /&gt;Free disk space check passed for "hen:/tmp"&lt;br /&gt;Check for multiple users with UID value 1100 passed&lt;br /&gt;User existence check passed for "grid"&lt;br /&gt;Run level check passed&lt;br /&gt;Hard limits check passed for "maximum open file descriptors"&lt;br /&gt;Soft limits check passed for "maximum open file descriptors"&lt;br /&gt;Hard limits check passed for "maximum user processes"&lt;br /&gt;Soft limits check passed for "maximum user processes"&lt;br /&gt;System architecture check passed&lt;br /&gt;Kernel version check passed&lt;br /&gt;Kernel parameter check passed for "semmsl"&lt;br /&gt;Kernel parameter check passed for "semmns"&lt;br /&gt;Kernel parameter check passed for "semopm"&lt;br /&gt;Kernel parameter check passed for "semmni"&lt;br /&gt;Kernel parameter check passed for "shmmax"&lt;br /&gt;Kernel parameter check passed for "shmmni"&lt;br /&gt;Kernel parameter check passed for "shmall"&lt;br /&gt;Kernel parameter check passed for "file-max"&lt;br /&gt;Kernel parameter check passed for "ip_local_port_range"&lt;br /&gt;Kernel parameter check passed for "rmem_default"&lt;br /&gt;Kernel parameter check passed for "rmem_max"&lt;br /&gt;Kernel parameter check passed for "wmem_default"&lt;br /&gt;Kernel parameter check passed for "wmem_max"&lt;br /&gt;Kernel parameter check passed for "aio-max-nr"&lt;br /&gt;Package existence check passed for "make-3.81( x86_64)"&lt;br /&gt;Package existence check passed for "binutils-2.17.50.0.6( x86_64)"&lt;br /&gt;Package existence check passed for "gcc-4.1.2 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "libaio-0.3.106 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "glibc-2.5-24 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "compat-libstdc++-33-3.2.3 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "elfutils-libelf-0.125 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "elfutils-libelf-devel-0.125( x86_64)"&lt;br /&gt;Package existence check passed for "glibc-common-2.5( x86_64)"&lt;br /&gt;Package existence check passed for "glibc-devel-2.5 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "glibc-headers-2.5( x86_64)"&lt;br /&gt;Package existence check passed for "gcc-c++-4.1.2 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "libaio-devel-0.3.106 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "libgcc-4.1.2 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "libstdc++-4.1.2 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "libstdc++-devel-4.1.2 (x86_64)( x86_64)"&lt;br /&gt;Package existence check passed for "sysstat-7.0.2( x86_64)"&lt;br /&gt;Package existence check passed for "ksh-20060214( x86_64)"&lt;br /&gt;Check for multiple users with UID value 0 passed&lt;br /&gt;Current group ID check passed&lt;br /&gt;&lt;br /&gt;Checking OCR integrity...&lt;br /&gt;&lt;br /&gt;OCR integrity check passed&lt;br /&gt;&lt;br /&gt;Checking Oracle Cluster Voting Disk configuration...&lt;br /&gt;&lt;br /&gt;Oracle Cluster Voting Disk configuration check passed&lt;br /&gt;Time zone consistency check passed&lt;br /&gt;&lt;br /&gt;Starting Clock synchronization checks using Network Time Protocol(NTP)...&lt;br /&gt;&lt;br /&gt;NTP Configuration file check started...&lt;br /&gt;No NTP Daemons or Services were found to be running&lt;br /&gt;&lt;br /&gt;Clock synchronization check using Network Time Protocol(NTP) passed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;User "grid" is not part of "root" group. Check passed&lt;br /&gt;Checking consistency of file "/etc/resolv.conf" across nodes&lt;br /&gt;&lt;br /&gt;File "/etc/resolv.conf" does not have both domain and search entries defined&lt;br /&gt;domain entry in file "/etc/resolv.conf" is consistent across nodes&lt;br /&gt;search entry in file "/etc/resolv.conf" is consistent across nodes&lt;br /&gt;All nodes have one search entry defined in file "/etc/resolv.conf"&lt;br /&gt;The DNS response time for an unreachable node is within acceptable limit on all nodes&lt;br /&gt;&lt;br /&gt;File "/etc/resolv.conf" is consistent across nodes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Checking GNS integrity...&lt;br /&gt;The GNS subdomain name "vmrac.fits.ro" is a valid domain name&lt;br /&gt;GNS VIP "poc-gns-vip.vmrac.fits.ro" resolves to a valid IP address&lt;br /&gt;&lt;b&gt;&lt;span style="color: #990000;"&gt;PRVF-5229 : GNS VIP is active before Clusterware installation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #990000;"&gt;PRVF-5232 : The GNS subdomain qualified host name "hen.vmrac.fits.ro" was resolved into an IP address&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #990000;"&gt;GNS integrity check failed&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Pre-check for node addition was unsuccessful on all the nodes.&lt;/pre&gt;PRVF-5229 is really a strange error: of course the GNS VIP is active because I already have my RAC installed. It really makes sense when installing a new RAC and the GNS vip sould be unallocated but otherwise I don't get it. So, I decided to go on even the CVU was complaining.&lt;br /&gt;&lt;br /&gt;The next step would be to run addNode.sh script from [GI_HOME]/oui/bin location. I ran the script and I found that it does nothing if the CVU checks are not passed. You can figure out this if you run the script with debugging:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[grid@owl bin]$ sh -x ./addNode.sh -silent "CLUSTER_NEW_NODES={hen}"&lt;br /&gt;+ OHOME=/u01/app/11.2.0.2/grid&lt;br /&gt;+ INVPTRLOC=/u01/app/11.2.0.2/grid/oraInst.loc&lt;br /&gt;+ ADDNODE='/u01/app/11.2.0.2/grid/oui/bin/runInstaller -addNode -invPtrLoc /u01/app/11.2.0.2/grid/oraInst.loc ORACLE_HOME=/u01/app/11.2.0.2/grid -silent CLUSTER_NEW_NODES={hen}'&lt;br /&gt;+ '[' '' = Y -o '!' -f /u01/app/11.2.0.2/grid/cv/cvutl/check_nodeadd.pl ']'&lt;br /&gt;+ CHECK_NODEADD='/u01/app/11.2.0.2/grid/perl/bin/perl /u01/app/11.2.0.2/grid/cv/cvutl/check_nodeadd.pl -pre -silent CLUSTER_NEW_NODES={hen}'&lt;br /&gt;+ /u01/app/11.2.0.2/grid/perl/bin/perl /u01/app/11.2.0.2/grid/cv/cvutl/check_nodeadd.pl -pre -silent 'CLUSTER_NEW_NODES={hen}'&lt;br /&gt;+ '[' 1 -eq 0 ']'&lt;/pre&gt;&lt;br /&gt;As you can see, the check_nodeadd.pl script ends with a non-zero exit code which means error (this perl script is really running the cluvfy utility so, it fails because of the GNS check). The only workaround I found was to ignore this checking using: &lt;code&gt;export IGNORE_PREADDNODE_CHECKS=Y&lt;/code&gt;&lt;br /&gt;After that I was able to successfully run addNode.sh script:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[grid@owl bin]$ ./addNode.sh -silent "CLUSTER_NEW_NODES={hen}"&lt;br /&gt;Starting Oracle Universal Installer...&lt;br /&gt;&lt;br /&gt;... output truncated ...&lt;br /&gt;&lt;br /&gt;Saving inventory on nodes (Friday, December 10, 2010 8:49:27 PM EET)&lt;br /&gt;.                                                               100% Done.&lt;br /&gt;Save inventory complete&lt;br /&gt;WARNING:A new inventory has been created on one or more nodes in this session. However, it has not yet been registered as the central inventory of this system.&lt;br /&gt;To register the new inventory please run the script at '/u01/app/oraInventory/orainstRoot.sh' with root privileges on nodes 'hen'.&lt;br /&gt;If you do not register the inventory, you may not be able to update or patch the products you installed.&lt;br /&gt;The following configuration scripts need to be executed as the "root" user in each cluster node.&lt;br /&gt;/u01/app/oraInventory/orainstRoot.sh #On nodes hen&lt;br /&gt;/u01/app/11.2.0.2/grid/root.sh #On nodes hen&lt;br /&gt;To execute the configuration scripts:&lt;br /&gt;    1. Open a terminal window&lt;br /&gt;    2. Log in as "root"&lt;br /&gt;    3. Run the scripts in each cluster node&lt;br /&gt;&lt;br /&gt;The Cluster Node Addition of /u01/app/11.2.0.2/grid was successful.&lt;br /&gt;Please check '/tmp/silentInstall.log' for more details.&lt;/pre&gt;&lt;br /&gt;Okey, GREAT! Let's run those scripts on the new node:&lt;br /&gt;&lt;pre&gt;[root@hen app]# /u01/app/oraInventory/orainstRoot.sh&lt;br /&gt;Creating the Oracle inventory pointer file (/etc/oraInst.loc)&lt;br /&gt;Changing permissions of /u01/app/oraInventory.&lt;br /&gt;Adding read,write permissions for group.&lt;br /&gt;Removing read,write,execute permissions for world.&lt;br /&gt;&lt;br /&gt;Changing groupname of /u01/app/oraInventory to oinstall.&lt;br /&gt;The execution of the script is complete.&lt;br /&gt;&lt;br /&gt;[root@hen app]# /u01/app/11.2.0.2/grid/root.sh&lt;br /&gt;Running Oracle 11g root script...&lt;br /&gt;&lt;br /&gt;The following environment variables are set as:&lt;br /&gt;    ORACLE_OWNER= grid&lt;br /&gt;    ORACLE_HOME=  /u01/app/11.2.0.2/grid&lt;br /&gt;&lt;br /&gt;Enter the full pathname of the local bin directory: [/usr/local/bin]: &lt;br /&gt;The contents of "dbhome" have not changed. No need to overwrite.&lt;br /&gt;The contents of "oraenv" have not changed. No need to overwrite.&lt;br /&gt;The contents of "coraenv" have not changed. No need to overwrite.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Creating /etc/oratab file...&lt;br /&gt;Entries will be added to the /etc/oratab file as needed by&lt;br /&gt;Database Configuration Assistant when a database is created&lt;br /&gt;Finished running generic part of root script.&lt;br /&gt;Now product-specific root actions will be performed.&lt;br /&gt;Using configuration parameter file: /u01/app/11.2.0.2/grid/crs/install/crsconfig_params&lt;br /&gt;Creating trace directory&lt;br /&gt;&lt;b&gt;&lt;span style="color: #990000;"&gt;PROTL-16: Internal Error&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #990000;"&gt;Failed to create or upgrade OLR&lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&lt;span style="color: #990000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;Failed to create or upgrade OLR at /u01/app/11.2.0.2/grid/crs/install/crsconfig_lib.pm line 6740.&lt;br /&gt;/u01/app/11.2.0.2/grid/perl/bin/perl -I/u01/app/11.2.0.2/grid/perl/lib -I/u01/app/11.2.0.2/grid/crs/install /u01/app/11.2.0.2/grid/crs/install/rootcrs.pl execution failed&lt;/pre&gt;&lt;br /&gt;Ups! I did not see that coming! First of all, OLR?! Yea, it's like an OCR but local. The only note I found about this error was 1123453.1 and it advises to double check if all install prerequisites are passed using cluvfy. In my case, the only problem I had was with the GNS check. Does GNS have anything to do with my error? As it turned out, no, it doesn't! The big mistake I made (and the cluvfy didn't notice that) was that the SSH setup between nodes was wrong. Connecting from owl to hen was okey, but not vice-versa. After I fixed the SSH configuration the root.sh script was executed without any problems. Great!&lt;br /&gt;&lt;br /&gt;The next step was to clone the database oracle home. That was really easy: just run the addNode.sh in the same way I did for GI. So far so good... at this point I was expecting that little magic to happen. Look what the documentation says:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;If you store your policy-managed database on Oracle Automatic Storage Management (Oracle ASM), Oracle Managed Files (OMF) is enabled, and if there is space in a server pool for node2, then crsd adds the Oracle RAC instance to node2 and no further action is necessary. If OMF is not enabled, then you must manually add undo and redo logs.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Hey, that's my case! Unfortunately, the new instance didn't show up. Furthermore, the pool configuration was asking for a new node:&lt;br /&gt;&lt;pre&gt;[oracle@hen oracle]$ srvctl config srvpool -g poc&lt;br /&gt;Server pool name: poc&lt;br /&gt;Importance: 10, Min: 2, Max: -1&lt;br /&gt;Candidate server names: &lt;/pre&gt;Look, I have increased the importance level and I set the "Min" property to 2. Damn it! I don't know why the new server was not automatically picked up, but maybe is also my leak of experience concerning this new server pools concept. In the end I launched "dbca" from the new added node hoping that some new magic options were added. But, no... even the "Instance Management" option was disabled. But, if you are choosing "Configure database" and next, next, next until the SYSDBA credentials are requested then dbca will try to connect to the local instance and it will actually create this new instance. I'm sure this is not the way it was supposed to work but, at least, I could see some results. However, there was another interesting thing. Looking into the alert of the new created instance I found:&lt;br /&gt;&lt;pre&gt;Could not open audit file: /u01/app/oracle/admin/poc/adump/poc_2_ora_18197_1.aud&lt;br /&gt;Retry Iteration No: 1   OS Error: 2&lt;br /&gt;Retry Iteration No: 2   OS Error: 2&lt;br /&gt;Retry Iteration No: 3   OS Error: 2&lt;br /&gt;Retry Iteration No: 4   OS Error: 2&lt;br /&gt;Retry Iteration No: 5   OS Error: 2&lt;br /&gt;OS Audit file could not be created; failing after 5 retries&lt;/pre&gt;I didn't create the /u01/app/oracle/admin/poc/adump folder on my new node and that was causing the error. So, this is another thing I should remember... as part of the addNode.sh cloning process the "adump" location is not automatically created.&lt;br /&gt;And, that's all! Now, my fancy RAC has a new baby node.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-3613376368712106853?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/3613376368712106853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=3613376368712106853' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3613376368712106853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3613376368712106853'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/12/extending-my-rac-with-new-node.html' title='Extending my RAC with a new node'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7101542062734543643</id><published>2010-12-08T04:03:00.000-08:00</published><updated>2010-12-21T10:45:02.368-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>Upgrade GI to 11.2.0.2: Simply Surprising...</title><content type='html'>I never thought I'd write a post about such a trivial task... Well, if you are going to upgrade from 11.2.0.1 to 11.2.0.2 be prepared for surprises. &lt;br /&gt;&lt;br /&gt;The &lt;b&gt;first surprise&lt;/b&gt; is given by the download page from the oracle support site (formally know as Oracle Metalink). The 11.2.0.2 patch set has 4.8G! WTF?! Furthermore, it is split in 7 pieces... Despite of this huge size, the good thing is that, unlike the previous releases, this patch-set may be used as a self-contained Oracle installer, which means you don't have to install a base 11.2.0.1 release and, after that, to apply the 11.2.0.2 patch-set on top of it, but you may simply install the 11.2.0.2 release directly. There's one more catch: if you want to upgrade just the Grid Infrastructure you don't need all 7 pieces from the patch-set. On the download page is not very clear mentioned but if you have the curiosity to open the README (and you should!) then you'll find the following:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_gGEccZZIMqc/TP9SCFcyLVI/AAAAAAAAADA/L3kmf-qD0pk/s1600/upgrade-files.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="108" src="http://4.bp.blogspot.com/_gGEccZZIMqc/TP9SCFcyLVI/AAAAAAAAADA/L3kmf-qD0pk/s400/upgrade-files.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Great! So, for the beginning we'd need the 3rd piece in order to upgrade our Grid Infrastructure.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;second surprise&lt;/b&gt; is the fact that the GI cannot be in-place upgraded. In previous releases we used to patch providing an existing home location. Starting with 11.2.0.2 in-place upgrades for GI are not supported. According to the "Upgrade" guide:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;As of Oracle Database 11g release 2 (11.2), the Oracle Clusterware software must be upgraded to a new home location in the Oracle grid infrastructure home. Additionally, Oracle ASM and Oracle Clusterware (and Oracle Restart for single-instance databases) must run in the same Oracle grid infrastructure home. When upgrading Oracle Clusterware to release 11.2, OUI automatically calls Oracle ASM Cluster Assistant (ASMCA) to perform the upgrade into the grid infrastructure home.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Okey, good to know! Let's start the upgrade process of GI. The wizard provided by the OUI is quite intuitive therefore I will not bother you with screenshots and other obvious things. However, &lt;b&gt;the next surprise&lt;/b&gt; comes when you are running the &lt;code&gt;rootupgrade.sh&lt;/code&gt; script. The error is:&lt;br /&gt;&lt;pre&gt;Failed to add (property/value):('OLD_OCR_ID/'-1') for checkpoint:ROOTCRS_OLDHOMEINFO.Error code is 256&lt;br /&gt; The fixes for bug 9413827 are not present in the 11.2.0.1 crs home&lt;br /&gt; Apply the patches for these bugs in the 11.2.0.1 crs home and then run &lt;br /&gt; rootupgrade.sh /oragi/perl/bin/perl -I/oragi/perl/lib -I/oragi/crs/install /oragi/crs/install/rootcrs.pl execution failed&lt;/pre&gt;WTF? You cannot patch if you don't have another stupid patch already there. Okey, as an Oracle DBA you have to be a patient guy... take a deep breath and start looking for bug 9413827. First of all there is the 10036834.8 note, which basically says that you might still get this error even if you apply the patch for the 9413827 bug. As an workaround they suggest to also apply the patch for 9655006 bug. That's madness! In the end it turns out that 9655006 patch is actually the July 10.2.0.1.2 PSU. Okey, just download the appropriate version for your platform. Now, &lt;b&gt;another surprise&lt;/b&gt;... you need an updated version of OPatch utility. Damn it! Back to metalink, search for patch 6880880 and download the 11.2.0.0.0 version for your platform (Take care not to download the wrong version. By the way, did you noticed that you may download a wget script which can be used to download the patch without using a browser? Yea, finally something good on that shitty flash GUI.) According to the README they suggest to unzip the upgraded OPatch utility directly into your CRS home, using something like:&lt;br /&gt;&lt;pre&gt;unzip [p6880880...zip] -d [your GI home]&lt;/pre&gt;... which I did!&lt;br /&gt;Now, you have to unzip the PSU patch into an empty folder, let's say /u01/stage, and run the following command as root:&lt;br /&gt;&lt;pre&gt;&lt;your gi="" home=""&gt;/OPatch/opatch auto /u01/stage/ -och [your GI home]&lt;/your&gt;&lt;/pre&gt;In my case, the output was:&lt;br /&gt;&lt;pre&gt;Executing /usr/bin/perl /u01/app/11.2.0.1/grid/OPatch/crs/patch112.pl -patchdir /u01 -patchn stage -och /u01/app/11.2.0.1/grid/ -paramfile /u01/app/11.2.0.1/grid/crs/install/crsconfig_params&lt;br /&gt;2010-12-08 12:32:19: Parsing the host name&lt;br /&gt;2010-12-08 12:32:19: Checking for super user privileges&lt;br /&gt;2010-12-08 12:32:19: User has super user privileges&lt;br /&gt;Using configuration parameter file: /u01/app/11.2.0.1/grid/crs/install/crsconfig_params&lt;br /&gt;The opatch Component check failed. This patch is not applicable for /u01/app/11.2.0.1/grid/&lt;br /&gt;The opatch Component check failed. This patch is not applicable for /u01/app/11.2.0.1/grid/&lt;br /&gt;Patch Component/Conflict  check failed for /u01/app/11.2.0.1/grid/&lt;/pre&gt;Upssy! &lt;b&gt;Another surprise!&lt;/b&gt; This patch is not applicable for bla bla bla? Are you serious? Let's check the logs. They should be in your $CRS_HOME/cfgtoollogs. Search for a log file named as &lt;code&gt;opatchauto[timestamp].log&lt;/code&gt;. The important part for the log:&lt;br /&gt;&lt;pre&gt;2010-12-08 12:32:19: The component check failed with following error&lt;br /&gt;2010-12-08 12:32:19: bash: /u01/app/11.2.0.1/grid/OPatch/opatch: Permission denied&lt;/pre&gt;Ha? I'm root! Aaaa... okey! Apparently it tries to run the OPatch tool under the grid user. Okey, let's fix the permissions.&lt;br /&gt;&lt;pre&gt;chown root:oinstall /u01/app/11.2.0.1/grid/OPatch -R&lt;br /&gt;chmod g+r /u01/app/11.2.0.1/grid/OPatch/opatch&lt;/pre&gt;Now, try again! Yeap... now it's working.&lt;br /&gt;After applying the patch we are ready for our &lt;code&gt;rootupgrade.sh&lt;/code&gt;. It's interesting that the output still contains the &lt;code&gt;Failed to add (property/value):('OLD_OCR_ID/'-1')&lt;/code&gt; message but the upgrade continues without any other complaints. Okey, let's perform a quick check:&lt;br /&gt;&lt;pre&gt;srvctl config asm&lt;br /&gt;ASM home: /u01/app/11.2.0.2/grid&lt;br /&gt;ASM listener: LISTENER&lt;br /&gt;&lt;br /&gt;srvctl config listener -a&lt;br /&gt;Name: LISTENER&lt;br /&gt;Network: 1, Owner: grid&lt;br /&gt;Home: &lt;crs home=""&gt;&lt;br /&gt;  /u01/app/11.2.0.2/grid on node(s) owl&lt;br /&gt;End points: TCP:1521&lt;/crs&gt;&lt;/pre&gt;Great, the ASM and listeners are relocated to the new GI home. The next logical thing to do is to uninstall the old GI home, right? It's as simple as:&lt;br /&gt;&lt;pre&gt;&lt;your gi="" home=""&gt;/deinstall/deinstall&lt;/your&gt;&lt;/pre&gt;Oookey, meet &lt;b&gt;SURPRISE Number 6&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;ERROR: You must delete or downgrade the Oracle RAC databases and de-install the Oracle RAC homes before attempting to remove the Oracle Clusterware homes.&lt;/pre&gt;Isn't it great? On metalink I found Bug 10332736 and, on the WORKAROUND section, it says something about writing a note with a manual uninstall procedure. However, at the time of writing this, the note wasn't published yet. Yea... all I can say is that I'm tired of these stupid issues. What happend with the Oracle testing department? They encourage to patch frequently but, as far as I'm concerned, I always have this creepy feeling before doing it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7101542062734543643?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7101542062734543643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7101542062734543643' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7101542062734543643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7101542062734543643'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/12/upgrade-gi-to-11202-simply-surprising.html' title='Upgrade GI to 11.2.0.2: Simply Surprising...'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gGEccZZIMqc/TP9SCFcyLVI/AAAAAAAAADA/L3kmf-qD0pk/s72-c/upgrade-files.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8090045132010479846</id><published>2010-11-28T15:05:00.000-08:00</published><updated>2010-12-03T13:27:00.061-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>My first 11gR2 RAC on VirtualBox - Learned Lessons</title><content type='html'>Oracle 11gR2 comes with many RAC goodies and, of course, I want to see them in action. But, the first step is to actually have a 11gR2 available. So, I decided to install one on my poor Dell PowerEdge 1850 server. As it turned out, even the installation process is changed with the introduction of the SCAN, GNS, server pools etc. However it makes this task more challenging, doesn't it?&lt;br /&gt;&lt;br /&gt;Because this RAC was not intended to be used for any productive purposes my first choice was for a virtualized environment. I tried Oracle VM in the first place and I was quite disappointed about the results:&lt;br /&gt;&lt;br /&gt;1. my virtual machines were reboting unexpectedly, even they were idle. I didn't managed to find the cause of this.&lt;br /&gt;&lt;br /&gt;2. during heavy loads on my virtual machines I was constantly getting: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;INFO: task kjournal:337 blocked for more than 120 seconds.&lt;br /&gt;"echo 0 &gt; /proc/sys/kernel/hung_task_timeout_sec" disables this message.&lt;/pre&gt;&lt;br /&gt;I guess Oracle already fixed that but I don't have any ULN subscriptions, so no updates. &lt;br /&gt;&lt;br /&gt;My next option was VirtualBox which is a nice choice and it is also provided by Oracle. VirtualBox supports now shared disks which makes it a very appealing solution for RAC testing. In addition, there's also a well written guide about how to install a RAC on VirtualBox &lt;a href='http://www.oracle-base.com/articles/11g/OracleDB11gR2RACInstallationOnOEL5UsingVirtualBox.php'&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To summarize, below are the main lessons I learned out of this RAC installation process:&lt;br /&gt;&lt;br /&gt;1. &lt;strong&gt;High CPU load for my virtual hosts&lt;/strong&gt;: after I created the hosts which were supposed to act as RAC nodes, I noticed that the CPUs on the host server was on 100% even the guests were idle. My host server has 8G RAM and 2 physical CPU on 3.4GHz, so this high CPU consumption didn't feel right at all. The solution was to boot my virtual hosts with the &lt;strong&gt;divider=10&lt;/strong&gt; option. Even with this tweak the whole installation process was slow, so be prepared to wait...&lt;br /&gt;&lt;br /&gt;2. &lt;strong&gt;pay attention to the groups membership for the oracle/grid users&lt;/strong&gt;: I made a stupid mistake and I forgot to add the oracle user to asmdba group. The prerequisites checks didn't complained and I successfully installed the Grid Infrastructure and the Oracle database software. However, when I reached the database installation phase using dbca I noticed that no asm diskgroups were available even they were accessible on my "grid" user. So, in order to save precious time for debugging such tricky issues double check these groups membership requirements.&lt;br /&gt;&lt;br /&gt;3. &lt;strong&gt;the time synchronization issue&lt;/strong&gt;: because I wanted to use new stuff for my RAC I decided to get rid of the ntpd synchronization and to use the Oracle CTSSD implementation. However, be careful here. Oracle is peaky when it comes to detecting if other synchronization software is installed. Even your ntpd daemon is stopped you also have to remove/rename the /etc/ntpd.conf file. Otherwise, the time synchronization check will fail. And another thing: if you configure your NIC interfaces via DHCP you may end up having this /etc/ntpd.conf after every node reboot. In order to prevent this you may use static address initialization or you may add PEERNTPD=no to your ifcfg-ethX scripts.&lt;br /&gt;&lt;br /&gt;4. &lt;strong&gt;GNS preparations&lt;/strong&gt;: this GNS (Grid Naming Service) component is new in 11gR2 and is not a very tasty concept for those DBAs (like me) who do not have a lot of knowledge in network administration field. So, if you are going to use GNS, be sure you have an experienced system administrator around, to provide you support for configuring it. However, you still need to know what to ask him to do. Basically, you have to agree on a new DNS zone. If your company domain is gigel.ro you may choose for your RAC rac.gigel.ro. Then, you need to ask him to delegate the requests form *.rac.gigel.ro to an unallocated IP address from the same IP class as your future RAC public interface. This IP is the VIP for your GNS and it will be available only when your RAC installation is successfully finished. Then, your system administrator will ask you under which name to "glue" the new rac.gigel.ro zone. He actually want to know under which DNS name to register this GNS vip address. &lt;a href="http://en.wikipedia.org/wiki/Domain_Name_System#Circular_dependencies_and_glue_records"&gt;The glue&lt;/a&gt; is really a well-known concept in the DNS terminology. As far as I noticed Oracle uses &amp;lt;cluster_name&amp;gt;-gns-vip.&amp;lt;gns_zone&amp;gt;. So, for our hypothetical example, assuming the rac name is "muci", the gns glue would be: muci-gns-vip.rac.gigel.ro.&lt;br /&gt;&lt;br /&gt;5. &lt;strong&gt;ORA-15081&lt;/strong&gt;: I think this has to do with the membership mistake. DBCA was reporting ORA-15081, complaining that it cannot create stuff into ASM diskgroups. The metalink note 1084186.1 provides the solution.&lt;br /&gt;&lt;br /&gt;Okey, that would be all. Happy (but slow) RAC on VirtualBox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8090045132010479846?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8090045132010479846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8090045132010479846' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8090045132010479846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8090045132010479846'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/11/my-first-11gr2-rac-on-virtualbox.html' title='My first 11gR2 RAC on VirtualBox - Learned Lessons'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-3506531963249146347</id><published>2010-10-31T13:14:00.000-07:00</published><updated>2010-10-31T13:14:39.764-07:00</updated><title type='text'>SHARED remote_login_password_file</title><content type='html'>When talking about the shared option of the remote_login_password_file parameter, the official 11.2 documentation states:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;One or more databases can use the password file. The password file can contain SYS as well as non-SYS users.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Whiles that's true, it is important to mention that, as soon as you set this parameter on SHARED, you are not allowed to add more SYSDBA users nor to change their passwords. A shared password file may contain non-SYS users, only if they were previously granted SYSDBA privilege, at the time the password file was in exclusive mode.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-3506531963249146347?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/3506531963249146347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=3506531963249146347' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3506531963249146347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3506531963249146347'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/10/shared-remoteloginpasswordfile.html' title='SHARED remote_login_password_file'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8894438558754679483</id><published>2010-09-22T06:54:00.000-07:00</published><updated>2010-09-23T00:28:47.955-07:00</updated><title type='text'>Statistics on Client Result Cache</title><content type='html'>I've just noticed that the result cache client statistics are not very accurate on my 11.2.0.1 Oracle server. I have the following java code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.sql.Connection;&lt;br /&gt;import java.sql.PreparedStatement;&lt;br /&gt;import java.sql.ResultSet;&lt;br /&gt;import java.sql.SQLException;&lt;br /&gt;import oracle.jdbc.pool.OracleDataSource;&lt;br /&gt;&lt;br /&gt;public class ClientResultCache {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws SQLException, IOException, InterruptedException {&lt;br /&gt;  OracleDataSource ods = new OracleDataSource();&lt;br /&gt;  ods.setDriverType("oci");&lt;br /&gt;  ods.setTNSEntryName("owldb");&lt;br /&gt;  ods.setUser("talek");&lt;br /&gt;  ods.setPassword("muci");&lt;br /&gt;  Connection conn = ods.getConnection();&lt;br /&gt;  String  query  = "select /*+ result_cache */ * from xxx";&lt;br /&gt;  ((oracle.jdbc.OracleConnection)conn).setImplicitCachingEnabled(true);&lt;br /&gt;     ((oracle.jdbc.OracleConnection)conn).setStatementCacheSize(10);&lt;br /&gt;  PreparedStatement  pstmt;&lt;br /&gt;  ResultSet rs;&lt;br /&gt;  for (int j = 0 ; j &lt; 1000 ; j++ ) {&lt;br /&gt;   System.out.println(j);&lt;br /&gt;   pstmt  = conn.prepareStatement (query);&lt;br /&gt;      rs  = pstmt.executeQuery();&lt;br /&gt;      while (rs.next( ) ) {&lt;br /&gt;      }&lt;br /&gt;      rs.close();&lt;br /&gt;      pstmt.close();&lt;br /&gt;      Thread.sleep(100);&lt;br /&gt;  } &lt;br /&gt;  System.in.read();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;While the above code is running I'm monitoring the CLIENT_RESULT_CACHE_STATS$. And this is what I've got:&lt;br /&gt;&lt;pre&gt;   &lt;br /&gt;STAT_ID NAME                                VALUE&lt;br /&gt;---------- ------------------------------ ----------&lt;br /&gt;         1 Block Size                            256&lt;br /&gt;         2 Block Count Max                       128&lt;br /&gt;         3 Block Count Current                   128&lt;br /&gt;         4 Hash Bucket Count                    1024&lt;br /&gt;         5 Create Count Success                    1&lt;br /&gt;         6 Create Count Failure                    0&lt;br /&gt;         7 Find Count                            812&lt;br /&gt;         8 Invalidation Count                      0&lt;br /&gt;         9 Delete Count Invalid                    0&lt;br /&gt;        10 Delete Count Valid                      0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The "Find Count" should be 999, right? My test program is still running (see the System.in.read at the end) therefore I expect my client result cache to be still there. My first guess was a delay in computing the statistics but even after 15 minutes of waiting I didn't get the right figures. Hmm... am I miss something?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8894438558754679483?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8894438558754679483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8894438558754679483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8894438558754679483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8894438558754679483'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/09/statistics-on-client-result-cache.html' title='Statistics on Client Result Cache'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5782892650023903635</id><published>2010-07-15T06:56:00.000-07:00</published><updated>2010-07-15T06:56:49.534-07:00</updated><title type='text'>Oracle IDE for Geeks</title><content type='html'>Let's be honest guys... how many times you find yourself googeling for “the best oracle IDE”? If you are like me then the answer is “too many times”... Why this? Well, partly I guess because we are not satisfied with what the market offers us in this area. &lt;br /&gt;If we're going to take a look at what we have now, the most well known Oracle IDEs are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.toadsoft.com/toad_oracle.htm"&gt;Toad&lt;/a&gt; from Quest Software&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.allroundautomations.com/plsqldev.html"&gt;PLSQL Developer&lt;/a&gt; offered by Allround Automations&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.oracle.com/technology/products/database/sql_developer/index.html"&gt;SQL Developer&lt;/a&gt; from Oracle&lt;/li&gt;&lt;/ol&gt;If you ask me, my favorite choice would be PLSQL Developer. It has a lot of cool features on a fair price. Toad is also nice but it's expensive. As far as SQL Developer is concerned I simply can't get used with it... In other words, I don't like it: it's slow (maybe Java has something to do with this) and it uses Java Swing for its GUI, bypassing my OS look &amp; feel. However, there are some pros which might count: it's free and it's cross-platform. In fact, if you are on a Unix based OS you don't have many choices but SQL Developer. Of course, there is/was &lt;a href="http://torasql.com/"&gt;Tora&lt;/a&gt;... but I would rather mention it on past tense.&lt;br /&gt;So, what I don't like about these tools? Let's see:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;They are heavy... some of them take a lot of time just to startup.&lt;/li&gt;&lt;li&gt;Most of them are not cross platform.&lt;/li&gt;&lt;li&gt;They are closed software. You don't have access to the code.&lt;/li&gt;&lt;li&gt;Limited editing features. I know they offer templates, auto-complete and stuff, but they look so small in comparison with what &lt;a href="http://www.vim.org/"&gt;VIM&lt;/a&gt; provides.&lt;/li&gt;&lt;li&gt;They are not suitable for server environments. I mean... what if you have to connect to the database on a remote Unix server, connected via ssh within a "friendly" console? I guess sqlplus is all you have there and it's not a very pleasant experience.&lt;/li&gt;&lt;li&gt;A lot of the so useful sqlplus commands doesn't work in these environments. PLSQL Developer does a good job emulating many of these commands but I still miss AUTOTRACE, sub-totals and all the other cool features sqlplus provides.&lt;/li&gt;&lt;/ol&gt;So, taking into consideration the above limitations I decided to create (why not?) my own Oracle IDE. It may sound stupid or too ambitious, but is not (well, maybe ambitious is). The new Oracle IDE I'm working on is called &lt;a href="http://code.google.com/p/vorax/"&gt;VoraX&lt;/a&gt; and is hosted on GoogleCode. VoraX stands for Vim ORAcle eXtenstion and yes... you have right: it's a VIM plugin. If you are a big fan of the VIM editor then you have to give VoraX a try.  Of course there is also &lt;a href="http://www.vim.org/scripts/script.php?script_id=356"&gt;dbext&lt;/a&gt; plugin which provides support for Oracle databases but the main problem with it is that it doesn't maintain a persistent connection to the database. In dbext, when you are going to execute something, sqlplus is launched, a new connection is done, the statement is handed over, the results are fetched into VIM and then, sqlplus is closed. This cycle is restarted on every statement execution which is quite expensive, slow and does not preserve your transactional context. Anyway, dbext is a tool designed for many databases, not just Oracle and, personally, I don't like generic database tools.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5782892650023903635?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5782892650023903635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5782892650023903635' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5782892650023903635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5782892650023903635'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/07/oracle-ide-for-geeks.html' title='Oracle IDE for Geeks'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-6065226883329566675</id><published>2010-05-26T03:29:00.000-07:00</published><updated>2010-05-26T11:34:09.162-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqlplus'/><title type='text'>SqlPlus Injection</title><content type='html'>Despite that at the very first sight it might look stupid you may be hacked by a colleague in a very rude way. Suppose one developer asks you to create a new user for an upcoming system. Because he's a nice guy, he also hands you a simple script which creates this user along with all the required grants. Of course, even you like your colleague and appreciate his effort, you carefully inspect that script before running it. Let's see a preview of this script in a plain vim window:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_gGEccZZIMqc/S_ziPy1Uv0I/AAAAAAAAACo/N99XMg_-C1s/s1600/sqlplus_hack.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/_gGEccZZIMqc/S_ziPy1Uv0I/AAAAAAAAACo/N99XMg_-C1s/s400/sqlplus_hack.png" width="380" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Oookey! The script has nice comments, nothing unusual... You run it in your sqlplus SYS session and... BANG! your SYSTEM user is compromised and you'll even don't know that. If you still have the WTF face, then look again.&lt;br /&gt;The catch is in the last comment. We used to think that in sqlplus a multiline&amp;nbsp; comment start with an /* (and because sqlplus is quite picky it has to be further followed by a space or CR) and then, everything till the closing */ is taken as a comment. This assumption is wrong because, in sqlplus, a # at the very beginning of a line means "execute the command on that line". In fact, it doesn't have to be # but this is the symbol configured by default for sqlprefix setting. Just check it out:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&amp;gt; show sqlprefix&lt;br /&gt;sqlprefix "#" (hex 23)&lt;/pre&gt;However, we are simply fooled by our editor which, with its nice code highlighting feature, just marked our comments accordingly. Of course, it doesn't know anything about the sqlplus "sqlprefix" setting. So, before running any third-party scripts you should carefully look at them, even at comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-6065226883329566675?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/6065226883329566675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=6065226883329566675' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6065226883329566675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6065226883329566675'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/05/sqlplus-injection.html' title='SqlPlus Injection'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gGEccZZIMqc/S_ziPy1Uv0I/AAAAAAAAACo/N99XMg_-C1s/s72-c/sqlplus_hack.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8900564079059372939</id><published>2010-05-02T23:22:00.000-07:00</published><updated>2010-05-04T00:01:52.256-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>Autobackup CF with Flash Recovery Area</title><content type='html'>In our office we have a 10g RAC database. It has a flash recovery area enabled, which points to an ASM disk. Nothing special I would say... However, from time to time, our nightly backup script simply fails complaining that it can't find some obsolete backups which should be deleted:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;RMAN-06207: WARNING: 4 objects could not be deleted for DISK channel(s) due&lt;br /&gt;RMAN-06208:          to mismatched status.  Use CROSSCHECK command to fix status&lt;br /&gt;RMAN-06210: List of Mismatched objects&lt;br /&gt;RMAN-06211: ==========================&lt;br /&gt;RMAN-06212:   Object Type   Filename/Handle&lt;br /&gt;RMAN-06213: --------------- ---------------------------------------------------&lt;br /&gt;RMAN-06214: Backup Piece    /u01/app/oracle/product/10.2.0/db_1/dbs/c-24173594-20100427-00&lt;br /&gt;RMAN-06214: Backup Piece    /u01/app/oracle/product/10.2.0/db_1/dbs/c-24173594-20100427-01&lt;br /&gt;RMAN-06214: Backup Piece    /u01/app/oracle/product/10.2.0/db_1/dbs/c-24173594-20100428-00&lt;br /&gt;RMAN-06214: Backup Piece    /u01/app/oracle/product/10.2.0/db_1/dbs/c-24173594-20100428-01&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's weird! All those backup pieces are controlfile autobackups. RMAN looks for them into a local filesystem and, being a RAC database, those files are accessible, obvious, just from one node. But how? They were supposed to be placed into our shared storage, in FRA, to be more precise. Well, let's look once again to our settings:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; show parameter recov&lt;br /&gt;&lt;br /&gt;NAME         TYPE  VALUE&lt;br /&gt;------------------------------------ ----------- ------------------------------&lt;br /&gt;db_recovery_file_dest       string  +DG1&lt;br /&gt;db_recovery_file_dest_size      big integer 150000M&lt;br /&gt;recovery_parallelism       integer  0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Okey, it's clear we have a FRA! What about RMAN settings?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;RMAN&gt; show all;&lt;br /&gt;&lt;br /&gt;using target database control file instead of recovery catalog&lt;br /&gt;RMAN configuration parameters are:&lt;br /&gt;CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 2 DAYS;&lt;br /&gt;CONFIGURE BACKUP OPTIMIZATION OFF; # default&lt;br /&gt;CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP ON;&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F';&lt;br /&gt;CONFIGURE DEVICE TYPE DISK PARALLELISM 4 BACKUP TYPE TO COMPRESSED BACKUPSET;&lt;br /&gt;CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default&lt;br /&gt;CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default&lt;br /&gt;CONFIGURE MAXSETSIZE TO UNLIMITED; # default&lt;br /&gt;CONFIGURE ENCRYPTION FOR DATABASE OFF; # default&lt;br /&gt;CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default&lt;br /&gt;CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default&lt;br /&gt;CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/u01/app/oracle/product/10.2.0/db_1/dbs/snapcf_fd1.f'; # default&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It looks good... the autobackup format for controlfile is '%F' which is the default one, right? The &lt;a href="http://download.oracle.com/docs/cd/B19306_01/backup.102/b14194/rcmsynta015.htm#i1017491" target="_blank"&gt;documentation&lt;/a&gt; proves that:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;The default location for the autobackup on disk is the flash recovery area (if configured) or a platform-specific location (if not configured). RMAN automatically backs up the current control file using the default format of %F.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Okey, we have a flash recovery area and a %F default autobackup format... WTF? Well, the answer is given by the 338483.1 metalink note. Apparently, there is a big difference between having the autobackup format set on its default value and having it reset to its default... Interesting, ha? It is... So, if you set (explicitly) the autobackup format to %F, the autobackup file will go to a OS specific location, which on Linux is $?/dbs. But if you have the autobackup format on its default (explicitly reset it, or never set it at all) and you have a FRA configured then that autobackup file will actually go to FRA.&lt;br /&gt;So, in my case the solution was simple (please notice the "# default" marker): &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;RMAN&gt; CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK CLEAR; &lt;br /&gt;&lt;br /&gt;old RMAN configuration parameters:&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F';&lt;br /&gt;RMAN configuration parameters are successfully reset to default value&lt;br /&gt;&lt;br /&gt;RMAN&gt; show controlfile autobackup format;&lt;br /&gt;&lt;br /&gt;RMAN configuration parameters are:&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ooookey, really really unintuitive... I think the Oracle documentation should be more precise regarding this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8900564079059372939?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8900564079059372939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8900564079059372939' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8900564079059372939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8900564079059372939'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/05/autobackup-cf-with-flash-recovery-area.html' title='Autobackup CF with Flash Recovery Area'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-4976831542756597039</id><published>2010-03-19T06:53:00.000-07:00</published><updated>2010-03-19T09:16:05.094-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>When having a rman retention policy based on REDUNDANCY is a bad idea...</title><content type='html'>Suppose you have a RMAN retention policy of "REDUNDANCY 2". This means that as long as you have at least two backups of the same datafile, controlfile/spfile or archivelog the other older backups become obsolete and RMAN is allowed to safely remove them.&lt;br /&gt;&lt;br /&gt;Now, let's also suppose that every night you backup your database using the following script:&lt;br /&gt;&lt;pre&gt;CONFIGURE CONTROLFILE AUTOBACKUP ON;&lt;br /&gt;rman {&lt;br /&gt;   backup database plus archivelog;&lt;br /&gt;   delete noprompt obsolete redundancy 2;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The backup task is quite simple: first of all it ensures that we have the controlfile autobackup feature on, then it backups the database and archives and, at the end, it deletes all obsolete backups using the REDUNDANCY 2 retention policy.&lt;br /&gt;Using the above approach you might think that you can restore your database as it was two days ago, right? For example, if you have a backup taken on Monday and another one taken on Tuesday you may restore your database as it was within the (Monday_last_backup - Today) time interval. Well, that's wrong!&lt;br /&gt;&lt;br /&gt;Consider the following scenario:&lt;br /&gt;1. On Monday night you backup the database using the above script;&lt;br /&gt;2. On Tuesday, during the day, you drop a tablespace. Because this is a structural database change a controlfile autobackup will be triggered. Ieeei, you have a new controlfile backup.&lt;br /&gt;3. On Tuesday night you backup again the database... nothing unusual, right? &lt;br /&gt;&lt;br /&gt;Well, the tricky part is regarding the DELETE OBSOLETE command. When the backup script will run this command, RMAN finds out three controlfile backups: one is originating from the Monday backup, one is from the structural change and the third is from our just finished Tuesday backup database command. Now according to the retention policy of "REDUNDANCY 2", RMAN will assume that it is safe to delete the backup of the controlfile taken on Monday night backup because it's out of our retention policy and because this backup is the oldest one. Uuups... this means that we gonna have a big problem restoring the database as it was before our structural change because we don't have a controlfile backup from that time.&lt;br /&gt;&lt;br /&gt;So, if you intend to incomplete recover your database to a previous time in the past it's really a good idea to switch to a retention policy based on a "RECOVERY WINDOW" instead. In our case a RECOVERY WINDOW OF 2 DAYS would be more appropriate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-4976831542756597039?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/4976831542756597039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=4976831542756597039' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/4976831542756597039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/4976831542756597039'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/03/when-having-rman-retention-policy-based.html' title='When having a rman retention policy based on REDUNDANCY is a bad idea...'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8560023977738414187</id><published>2010-02-28T11:54:00.000-08:00</published><updated>2010-05-26T01:20:17.647-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>PLSQL "All or Nothing" Pitfall</title><content type='html'>Transactions are such a common thing when working with databases. They act on an "all or nothing" basis, that is, they succeed or fail but they always should let the database into a consistent state. Of course, in Oracle databases the rules are the same, but the interesting part I want to refer to is in connection with PL/SQL modules (procedures, functions or packages). &lt;br /&gt;&lt;br /&gt;A PL/SQL module is some kind of "all or nothing" component. If the procedure fails it rollbacks the uncommited work it has done. Suppose we have the following procedure:&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE OR REPLACE PROCEDURE test AS &lt;br /&gt;BEGIN&lt;br /&gt;  insert into yyy values (1);&lt;br /&gt;  raise_application_error(-20000, 'I am a cute error!');&lt;br /&gt;END test;&lt;/pre&gt;&lt;br /&gt;Let's see what happens:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; truncate table yyy;&lt;br /&gt;&lt;br /&gt;Table truncated.&lt;br /&gt;&lt;br /&gt;SQL&gt; exec test;&lt;br /&gt;BEGIN test; END;&lt;br /&gt;&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-20000: I am a cute error!&lt;br /&gt;ORA-06512: at "TALEK.TEST", line 4&lt;br /&gt;ORA-06512: at line 1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from yyy;&lt;br /&gt;&lt;br /&gt;no rows selected&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nice... we didn't explicitly rollback, but Oracle was smart enough to do the cleanup job for us. This makes sense and proves that PLSQL modules are, in a way, "all or nothing" components.&lt;br /&gt;&lt;br /&gt;Now, let's say we have an oracle job which calls our "test" procedure and if an error occurs it has to log it into another table. A possible implementation of the job PLSQL caller block may be:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql"&gt;begin&lt;br /&gt;  test;&lt;br /&gt;exception&lt;br /&gt;  when others then&lt;br /&gt;    insert into log values (dbms_utility.format_error_stack);&lt;br /&gt;    commit;&lt;br /&gt;    raise;&lt;br /&gt;end;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above code may seem harmless: the test procedure is called and if it raises an error the exception part of the PL/SQL caller block is executed which further inserts the error into our log table. Of course, we commit the log entry we just inserted and we re-raise the originating error. We know that if test procedure fails then it rollbacks its uncommited work as we seen above. After all, it's an "all or nothing" piece, right? Well, here's the pitfall: if you catch the exception then the procedure which raised the error will not clean up anything as long as you are within the EXCEPTION section. Even the whole anonymous block will fail because of re-raising the original error, the COMMIT statement from the EXCEPTION section will actually commit the incomplete work done by our "TEST" procedure. So, in most cases you should look twice to such EXCEPTION WHEN THEN ... COMMIT definitions... otherwise you may end up with nasty bugs. In the above example, in order to avoid this problem, a ROLLBACK should be performed before logging the error. Of course, there are smarter logging solutions which use autonomous transactions but, anyway, the goal was just to reveal the pitfall.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8560023977738414187?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8560023977738414187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8560023977738414187' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8560023977738414187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8560023977738414187'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/02/plsql-all-or-nothing-pitfall.html' title='PLSQL &quot;All or Nothing&quot; Pitfall'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8513130263732267506</id><published>2010-02-24T02:12:00.000-08:00</published><updated>2010-02-25T04:15:45.686-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><category scheme='http://www.blogger.com/atom/ns#' term='ASM'/><title type='text'>INS-32018 Warning for Standalone Server</title><content type='html'>When it comes to installing Oracle you should always follow the procedures written into the installation guides. As you already know, Oracle 11.2 packages ASM within a new separate component called Oracle Grid Infrastructure. So, if you want to install the database files into ASM then you must install Grid Infrastructure. As a good practice, Oracle recommends to install it under a different user, typically named "grid".&lt;br /&gt;As far as the OFA directories structure is concerned the installation guide recommends:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;to create an "/u01/app/grid" directory to be used as an ORACLE_BASE for this "grid" user;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;to create an "/u01/app/11.2.0/grid" directory to be used as an ORACLE_HOME for this "grid" user.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;If you're like me, the above configuration looks a little bit weird because I used to think that the ORACLE_HOME should be somewhere under the ORACLE_BASE directory. Nevertheless, the documentation clearly states the following:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Caution:&lt;/b&gt;&lt;br/&gt;&lt;br /&gt;&lt;i&gt;For grid infrastructure for a cluster installations, the Grid home must not be placed under one of the Oracle base directories, or under Oracle home directories of Oracle Database installation owners, or in the home directory of an installation owner. During installation, ownership of the path to the Grid home is changed to root. This change causes permission errors for other installations.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;However, the above applies just to cluster installations. If you just want ASM installed for a single instance database then it's fine (and recommended) to place the ORACLE_HOME under the ORACLE_BASE. If not doing so, you'll get the following warning:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gGEccZZIMqc/S4UBc6E_7zI/AAAAAAAAACY/kWEA-3PJAj0/s1600-h/ins-32018.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 239px;" src="http://2.bp.blogspot.com/_gGEccZZIMqc/S4UBc6E_7zI/AAAAAAAAACY/kWEA-3PJAj0/s320/ins-32018.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5441757320885301042" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, to sum up the above ideas, remember that if you are going to install a RAC then you need to create the grid ORACLE_HOME out of the ORACLE_BASE of any oracle software owner. If you choose to install the Oracle Grid Infrastructure for a standalone server then the ORACLE_HOME of the grid user should be under its ORACLE_BASE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8513130263732267506?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8513130263732267506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8513130263732267506' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8513130263732267506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8513130263732267506'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/02/ins-32018-warning-for-standalone-server.html' title='INS-32018 Warning for Standalone Server'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gGEccZZIMqc/S4UBc6E_7zI/AAAAAAAAACY/kWEA-3PJAj0/s72-c/ins-32018.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-3504538045715332980</id><published>2010-02-17T00:47:00.000-08:00</published><updated>2010-02-22T02:25:27.953-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>ALL_TABLES versus ALL_ALL_TABLES</title><content type='html'>If you ever wondered what's the difference between ALL_TABLES and ALL_ALL_TABLES then here's the answer: both views provide all tables to which the current user has access to but, in addition to the tables returned by ALL_TABLES, the ALL_ALL_TABLES will also return all object tables (system generated or not) accessible by the current user.&lt;br /&gt;&lt;br /&gt;Pay attention that this may be an interview question (e.g. how can you get all tables you have access to?) and you may leave a good impression if you respond with another question: "Do you also want object tables to be included?". :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-3504538045715332980?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/3504538045715332980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=3504538045715332980' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3504538045715332980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3504538045715332980'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2010/02/alltables-versus-allalltables.html' title='ALL_TABLES versus ALL_ALL_TABLES'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5800320865990607033</id><published>2009-12-16T12:05:00.000-08:00</published><updated>2010-05-26T10:58:58.821-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>A DDL statement may fire a DML trigger</title><content type='html'>Maybe you know this, maybe you don't. Because it's not quite obvious it deserves a little attention. We all know about DML triggers. Remember? Yea, yea... the before/after insert/update/delete each row triggers. We use to think that the INSERT, UPDATE or DELETE statements fire the corresponding triggers (of course, if any are defined). That's true with one (as far as I know) important note: a DDL statement which adds a new column with a default value will also fire the UPDATE trigger.&lt;br /&gt;&lt;br /&gt;For example, let's create a dummy table:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; create table muc  (col1 integer primary key, modify_date timestamp);&lt;br /&gt;&lt;br /&gt;Table created.&lt;/pre&gt;&lt;br /&gt;Then, the corresponding trigger:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; create or replace trigger trg_muc_mod_dt before update on muc for each row&lt;br /&gt;2  begin&lt;br /&gt;3  :new.modify_date := systimestamp;&lt;br /&gt;4  end;&lt;br /&gt;5  /&lt;/pre&gt;&lt;br /&gt;Add some records:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; insert into muc values (1, systimestamp);&lt;br /&gt;&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;SQL&gt; insert into muc values (2, systimestamp);&lt;br /&gt;&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;SQL&gt; commit;&lt;/pre&gt;&lt;br /&gt;We end up having:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; select * from muc;&lt;br /&gt;&lt;br /&gt;    COL1 MODIFY_DATE&lt;br /&gt;---------- ------------------------------&lt;br /&gt;       1 16-DEC-09 09.54.03.804223 PM&lt;br /&gt;       2 16-DEC-09 09.54.41.815575 PM&lt;/pre&gt;&lt;br /&gt;Now, the moment of truth:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; alter table muc add (active integer default '0');&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from muc;&lt;br /&gt;&lt;br /&gt;    COL1 MODIFY_DATE                        ACTIVE&lt;br /&gt;---------- ------------------------------ ----------&lt;br /&gt;       1 16-DEC-09 09.55.53.836113 PM            0&lt;br /&gt;       2 16-DEC-09 09.55.53.840896 PM            0&lt;/pre&gt;&lt;br /&gt;Take a look at the MODIFY_DATE and see the new timestamp. The update trigger was invoked in response to our DDL statement. This is important to know. Think to a deposit table which has a column named LAST_UPATED and a trigger which updates it whenever something within a deposit changes. Now, suppose the business logic dictates that a new column must be added with a default value. You run the DDL statement to add that column and... suddenly, all information regarding when a particular deposit was last upated is lost. Ups. So, I should write down one hundred times: "Think twice before adding new columns with default values on a table with UPDATE triggers".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5800320865990607033?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5800320865990607033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5800320865990607033' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5800320865990607033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5800320865990607033'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/12/ddl-statement-may-fire-dml-trigger.html' title='A DDL statement may fire a DML trigger'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8867741545132854519</id><published>2009-11-29T11:19:00.000-08:00</published><updated>2010-02-22T02:26:36.661-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>Strange RMAN snapshot controlfile issue</title><content type='html'>A strange thing happen today. I executed a delete obsolete command on my RMAN prompt and it reported the snapshot controlfile as obsolete. I don't know under which circumstances this problem occurs and I couldn't find any relevant information on forums or metalink (oh! sorry "my oracle support") about this.&lt;br /&gt;&lt;br /&gt;Below is the output of the DELETE OBSOLETE command:&lt;br /&gt;&lt;pre&gt;RMAN&gt; delete obsolete;&lt;br /&gt;&lt;br /&gt;RMAN retention policy will be applied to the command&lt;br /&gt;RMAN retention policy is set to redundancy 1&lt;br /&gt;using channel ORA_DISK_1&lt;br /&gt;using channel ORA_DISK_2&lt;br /&gt;Deleting the following obsolete backups and copies:&lt;br /&gt;Type                 Key    Completion Time    Filename/Handle&lt;br /&gt;-------------------- ------ ------------------ --------------------&lt;br /&gt;Control File Copy     36     29-11-2009 12:35:33 /u01/app/oracle/product/11.2.0/&lt;br /&gt;                                                 dbhome_1/dbs/snapcf_tetris.f&lt;br /&gt;&lt;br /&gt;Do you really want to delete the above objects (enter YES or NO)? y&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-03009: failure of delete command on ORA_DISK_2 channel at 11/29/2009 21:11:16&lt;br /&gt;ORA-19606: Cannot copy or restore to snapshot control file&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Indeed, this is the default configured snapshot controlfile:&lt;br /&gt;&lt;pre&gt;RMAN&gt; show snapshot controlfile name;               &lt;br /&gt;&lt;br /&gt;RMAN configuration parameters for database with db_unique_name TETRIS are:&lt;br /&gt;CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/u01/app/oracle/product/11.2.0/&lt;br /&gt;dbhome_1/dbs/snapcf_tetris.f';&lt;/pre&gt;&lt;br /&gt;It seems I'm in a kind of deadlock here. The snapshot controlfile is reported as obsolete but it can't be deleted as it is used by RMAN. The only solution I found was to change the RMAN configuration to use another snapshot controlfile, to remove then the reported obsolete one and to switch back to the default. However, the question remains: why the snapshot controlfile is reported as obsolete?&lt;br /&gt;&lt;br /&gt;PS: This happend on a 11gR2 database installed under a Linux x86 platform.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update:&lt;/strong&gt; Apparently this is encountered after executing a DUPLICATE database from ACTIVE DATABASE. Furthermore, the snapshot controlfile is reported as a "datafile copy" when a CROSSCHECK is suggested. See below:&lt;br /&gt;&lt;pre&gt;RMAN&gt; delete obsolete;                                                                                                                                                                                           &lt;br /&gt;&lt;br /&gt;RMAN retention policy will be applied to the command&lt;br /&gt;RMAN retention policy is set to redundancy 1&lt;br /&gt;using channel ORA_DISK_1&lt;br /&gt;using channel ORA_DISK_2&lt;br /&gt;Deleting the following obsolete backups and copies:&lt;br /&gt;Type                 Key    Completion Time    Filename/Handle&lt;br /&gt;-------------------- ------ ------------------ --------------------&lt;br /&gt;Control File Copy     40     30-11-2009 18:41:15 /u01/app/oracle/product/11.2.0/dbhome_1&lt;br /&gt;                                                 /dbs/snapcf_tetris.f&lt;br /&gt;&lt;br /&gt;Do you really want to delete the above objects (enter YES or NO)? y                                                                                                                                              &lt;br /&gt;&lt;br /&gt;RMAN-06207: WARNING: 1 objects could not be deleted for DISK channel(s) due&lt;br /&gt;RMAN-06208:          to mismatched status.  Use CROSSCHECK command to fix status&lt;br /&gt;RMAN-06210: List of Mismatched objects&lt;br /&gt;RMAN-06211: ==========================&lt;br /&gt;RMAN-06212:   Object Type   Filename/Handle&lt;br /&gt;RMAN-06213: --------------- ---------------------------------------------------&lt;br /&gt;RMAN-06214: Datafile Copy   /u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f&lt;/pre&gt;&lt;br /&gt;Obviously, that can't be a datafile copy. So, let's try a crosscheck as suggested:&lt;br /&gt;&lt;pre&gt;RMAN&gt; crosscheck datafilecopy '/u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f';                                                                                                                     &lt;br /&gt;&lt;br /&gt;using target database control file instead of recovery catalog&lt;br /&gt;allocated channel: ORA_DISK_1&lt;br /&gt;channel ORA_DISK_1: SID=148 device type=DISK&lt;br /&gt;allocated channel: ORA_DISK_2&lt;br /&gt;channel ORA_DISK_2: SID=140 device type=DISK&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-03002: failure of crosscheck command at 11/30/2009 19:09:43&lt;br /&gt;RMAN-20230: datafile copy not found in the repository&lt;br /&gt;RMAN-06015: error while looking up datafile copy name: /u01/app/oracle/product/11.2.0&lt;br /&gt;/dbhome_1/dbs/snapcf_tetris.f&lt;/pre&gt;&lt;br /&gt;Okey, this was expected as I don't have any datafilecopy with that name despite of what RMAN says. So, let's try a crosscheck for the controlfile copy:&lt;br /&gt;&lt;pre&gt;RMAN&gt; crosscheck controlfilecopy '/u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f';                                                                                                                  &lt;br /&gt;&lt;br /&gt;released channel: ORA_DISK_1&lt;br /&gt;released channel: ORA_DISK_2&lt;br /&gt;allocated channel: ORA_DISK_1&lt;br /&gt;channel ORA_DISK_1: SID=148 device type=DISK&lt;br /&gt;allocated channel: ORA_DISK_2&lt;br /&gt;channel ORA_DISK_2: SID=140 device type=DISK&lt;br /&gt;validation failed for control file copy&lt;br /&gt;control file copy file name=/u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f &lt;br /&gt;RECID=40 STAMP=704313675&lt;br /&gt;Crosschecked 1 objects&lt;/pre&gt;&lt;br /&gt;As it can be seen the validation fails, although the file exists on that location:&lt;br /&gt;&lt;pre&gt;$ ls -al /u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f&lt;br /&gt;-rw-r----- 1 oracle oinstall 10436608 Nov 30 18:57 /u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_tetris.f&lt;/pre&gt;&lt;br /&gt;I don't know if this is documented somewhere but it looks to me like a bug. No idea why the snapshot control file is messed up after a DUPLICATE TARGET DATABASE ... FROM ACTIVE DATABASE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8867741545132854519?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8867741545132854519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8867741545132854519' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8867741545132854519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8867741545132854519'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/strange-rman-snapshot-controlfile-issue.html' title='Strange RMAN snapshot controlfile issue'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7439682897062496536</id><published>2009-11-27T13:08:00.000-08:00</published><updated>2010-02-22T02:27:13.014-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>TSPITR to recover a dropped tablespace</title><content type='html'>A nice feature of Oracle 11gR2 is the ability to recover a dropped tablespace using TSPITR. Of course, in order to succeed this, you need valid backups. Let's test this! First of all, just to be on the safe side, take a fresh backup of the database:&lt;br /&gt;&lt;pre&gt;BACKUP DATABASE PLUS ARCHIVELOG;&lt;/pre&gt;&lt;br /&gt;Then supposing you have a "MUCI" tablespace, simply drop it:&lt;br /&gt;&lt;pre&gt;drop tablespace MUCI including contents;&lt;/pre&gt;&lt;br /&gt;Let's try to recover "MUCI" tablespace. You'll need the nearest timestamp or SCN before the tablespace was dropped.&lt;br /&gt;&lt;br /&gt;If you are tempted to use fully automatic TSPITR then be prepared for troubles. This is what happen to me when I tried it:&lt;br /&gt;&lt;pre&gt;RMAN&gt; recover tablespace muci until scn 2240386 auxiliary destination '/u01/app/backup';&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-03002: failure of recover command at 11/27/2009 21:57:13&lt;br /&gt;RMAN-06965: Datapump job has stopped&lt;br /&gt;RMAN-06961:    IMPDP&gt; Job "SYS"."TSPITR_IMP_hilc" stopped due to fatal error at 21:57:09&lt;br /&gt;RMAN-06961:    IMPDP&gt; ORA-39123: Data Pump transportable tablespace job aborted&lt;br /&gt;ORA-01565: error in identifying file '/u01/app/oracle/oradata/TETRIS/datafile/o1_mf_muci_5k0bwdmb_.dbf'&lt;br /&gt;ORA-27037: unable to obtain file status&lt;br /&gt;Linux Error: 2: No such file or directory&lt;br /&gt;Additional information: 3&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I google it and found &lt;a href="http://ocpdba.wordpress.com/2009/09/17/recovering-a-dropped-tablespace-with-tspitr-in-11gr2/"&gt;this&lt;/a&gt; post which recommends to drop the tablespace without "AND DATAFILES" but, as far as I'm concerned, it didn't work.&lt;br /&gt;Nevertheless, setting a new name for the datafile which belongs to the dropped datafile did the job.&lt;br /&gt;&lt;pre&gt;RMAN&gt; run {&lt;br /&gt;2&gt; set newname for datafile 6 to new;&lt;br /&gt;3&gt; recover tablespace muci until scn 2240386 auxiliary destination '/u01/app/backup';&lt;br /&gt;4&gt; }&lt;/pre&gt;&lt;br /&gt;A direct consequence of this in 11gR2 is that you can apply multiple TSPITR for the same tablespace without using a recovery catalog. If you chosen a wrong SCN and you already brought the recovered tablespace ONLINE then you can simply drop it and try again with another SCN.&lt;br /&gt;&lt;br /&gt;Awesome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7439682897062496536?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7439682897062496536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7439682897062496536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7439682897062496536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7439682897062496536'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/tspitr-to-recover-dropped-tablespace.html' title='TSPITR to recover a dropped tablespace'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-2426115674961340837</id><published>2009-11-27T11:02:00.000-08:00</published><updated>2010-05-26T11:06:49.731-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Annoying Tablespaces Quotas</title><content type='html'>There's one thing about tablespace quotas which I really don't like. If I allocate quota on a tablespace to a user and then I drop that tablespace the quota is not automatically revoked. It still can be seen in DBA_TS_QUOTAS view but with the DROPPED column set as YES. However, if i create afterwards a tablespace with the same name as the one previously dropped the old quota is auto-magically reactivated on this new tablespace which might not be my intention. Let's see it in action:&lt;br /&gt;&lt;br /&gt;1. first of all, let's create a dummy tablespace:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; create tablespace test_tbs datafile size 20M;                                                                               &lt;br /&gt;&lt;br /&gt;Tablespace created.&lt;/pre&gt;&lt;br /&gt;2. let's also create a user and grant quota on the TEST_TBS tablespace:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; create user gogu identified by xxx quota unlimited on users;                                                                &lt;br /&gt;&lt;br /&gt;User created.&lt;br /&gt;&lt;br /&gt;SQL&gt; alter user gogu quota unlimited on test_tbs;                                                                                &lt;br /&gt;&lt;br /&gt;User altered.&lt;/pre&gt;&lt;br /&gt;3. take a look at quotas:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; select * from dba_ts_quotas where username='GOGU';                                                                          &lt;br /&gt;&lt;br /&gt;TABLESPACE_NAME USERNAME             BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS DRO&lt;br /&gt;--------------- --------------- ---------- ---------- ---------- ---------- ---&lt;br /&gt;USERS           GOGU                     0         -1          0         -1 NO&lt;br /&gt;TEST_TBS        GOGU                     0         -1          0         -1 NO&lt;/pre&gt;&lt;br /&gt;4. now drop the TEST_TBS tablespace and look again at quotas:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; drop tablespace test_tbs including contents and datafiles;                                                                  &lt;br /&gt;&lt;br /&gt;Tablespace dropped.&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from dba_ts_quotas where username='GOGU';                                                                          &lt;br /&gt;&lt;br /&gt;TABLESPACE_NAME USERNAME             BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS DRO&lt;br /&gt;--------------- --------------- ---------- ---------- ---------- ---------- ---&lt;br /&gt;USERS           GOGU                     0         -1          0         -1 NO&lt;br /&gt;TEST_TBS        GOGU                     0         -1          0         -1 YES&lt;/pre&gt;&lt;br /&gt;Just notice that the DROPPED column is now set to YES for the TEST_TBS tablespace. This I don't like and if I want to revoke the quota oracle complains that it doesn't know anything about the TEST_TBS tablespace. &lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; alter user gogu quota 0 on test_tbs;                                                                                        &lt;br /&gt;alter user gogu quota 0 on test_tbs&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-00959: tablespace 'TEST_TBS' does not exist&lt;/pre&gt;&lt;br /&gt;Obvious, but then why preserving that quota in DBA_TS_QUOTAS anyway?&lt;br /&gt;&lt;br /&gt;5. Let's recreate the TEST_TBS tablespace and then look at quotas:&lt;br /&gt;&lt;pre class="brush: sql"&gt;SQL&gt; create tablespace test_tbs datafile size 20M;                                                                               &lt;br /&gt;&lt;br /&gt;Tablespace created.&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from dba_ts_quotas where username='GOGU';                                                                          &lt;br /&gt;&lt;br /&gt;TABLESPACE_NAME USERNAME             BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS DRO&lt;br /&gt;--------------- --------------- ---------- ---------- ---------- ---------- ---&lt;br /&gt;USERS           GOGU                     0         -1          0         -1 NO&lt;br /&gt;TEST_TBS        GOGU                     0         -1          0         -1 NO&lt;/pre&gt;&lt;br /&gt;See how the "DROPPED" column is now back on "NO". But wait... this TEST_TBS tablespace is a new tablespace which just happen to be named like an old dropped tbs. Bleah... ugly!&lt;br /&gt;&lt;br /&gt;So, this boils down to the conclusion that when you are about to drop a tablespace is a good thing to check the quotas allocated to users and to revoke them before dropping the tablespace. Otherwise they will remain in DBA_TS_QUOTAS and they'll be reactivated when a tablespace with the same name is created. Furthermore, I don't know how you can get rid of them if the tablespace no longer exists. Of course, you can create a dummy tablespace with the same name, revoke quotas and after that to drop the dummy tablespace. But this is an awful workaround.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update:&lt;/strong&gt; Yet, I see an advantage of the above behaviour. In 11gR2 you can recover a dropped tablespace with TSPITR. After the TSPITR successfully completes and the dropped tablespace is recovered, the old quotas are also reactivated which is a good thing for the users who had objects in that tablespace.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-2426115674961340837?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/2426115674961340837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=2426115674961340837' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/2426115674961340837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/2426115674961340837'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/annoying-tablespaces-quotas.html' title='Annoying Tablespaces Quotas'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-6394599931208997961</id><published>2009-11-18T00:54:00.000-08:00</published><updated>2010-02-22T02:28:18.609-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>Do archivelogs become obsolete if they contain blocks from an BEGIN BACKUP operation?</title><content type='html'>Of course, not every possible case is described within the docs therefore some of them have to be simply tried. So, today I was wondering what would happen if I leave a tablespace in BEGIN BACKUP mode and I will continue to backup the database using:&lt;br /&gt;&lt;pre&gt;RUN {&lt;br /&gt;  BACKUP DATABASE PLUS ARCHIVELOG; &lt;br /&gt;  DELETE NOPROMPT OBSOLETE.&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;As you already know, if a tablespace is put in BEGIN BACKUP mode then all subsequent changes will force the dirty blocks to be written into the redologs which will be eventually archived. My main concern here was regarding the DELETE OBSOLETE command. Is RMAN smart enough to know that those archives are not going to become obsolete as long as the BEGIN BACKUP status is in place? After some tests I can conclude: RMAN knows this and will NOT consider those archives as obsolete. This was kind of obvious but, you know... it's always good to try and to see by your own eyes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-6394599931208997961?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/6394599931208997961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=6394599931208997961' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6394599931208997961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6394599931208997961'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/do-archivelogs-become-obsolete-if-they.html' title='Do archivelogs become obsolete if they contain blocks from an BEGIN BACKUP operation?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8471793181312049577</id><published>2009-11-15T03:43:00.000-08:00</published><updated>2010-05-26T11:08:45.774-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>High Availability Guaranteed Restore Points</title><content type='html'>I like the flashback database feature introduced by Oracle 10g and especially the guaranteed restore points. We intended to use it on our 10g production database to create guaranteed restore points before major upgrades but without enabling flashback logging because we wanted to affect at least as possible the whole database performance. What really bothered me at the time was the fact that I couldn't create my first guaranteed restore point if the database was open which, in my opinion, affects the high availability goal. The solution to this was to already have at least one guaranteed restore point before creating the next ones with the database open, but this always felt like an ugly workaround. &lt;br /&gt;So, the question is: what do you choose: the overhead of always having the flashback logging enabled or the downtime produced by the creation of a guaranteed restore point? Hmmm... &lt;br /&gt;As many Oracle new features they seem to be a little bit unpolished when just launched but they tend to become better an better. The same here. I've just had a nice surprise to see that in 11gR2 (I don't know if it's also in R1) you can create guaranteed restore points with the database open, without flashback logging enabled and without any previous guaranteed restore points:&lt;br /&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;SQL&gt; select name from v$restore_point;                                                        &lt;br /&gt;&lt;br /&gt;no rows selected&lt;br /&gt;&lt;br /&gt;SQL&gt; select flashback_on from v$database;                                                     &lt;br /&gt;&lt;br /&gt;FLASHBACK_ON&lt;br /&gt;------------------&lt;br /&gt;NO&lt;br /&gt;&lt;br /&gt;SQL&gt; select status from v$instance;                                                           &lt;br /&gt;&lt;br /&gt;STATUS&lt;br /&gt;------------&lt;br /&gt;OPEN&lt;br /&gt;&lt;br /&gt;SQL&gt; create restore point before_upgrade guarantee flashback database;                        &lt;br /&gt;&lt;br /&gt;Restore point created.&lt;br /&gt;&lt;br /&gt;SQL&gt; select name from v$restore_point;                                                        &lt;br /&gt;&lt;br /&gt;NAME&lt;br /&gt;---------------------------------------------------&lt;br /&gt;BEFORE_UPGRADE&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nice and good to know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8471793181312049577?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8471793181312049577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8471793181312049577' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8471793181312049577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8471793181312049577'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/high-availability-guaranteed-restore.html' title='High Availability Guaranteed Restore Points'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1775092953935296088</id><published>2009-11-01T11:07:00.000-08:00</published><updated>2009-11-01T12:19:01.663-08:00</updated><title type='text'>RMAN Retention Policy with Corrupted Backups</title><content type='html'>I always assumed that RMAN is smart enough to take care of my database obsolete backups. I give it the retention policy and it's done: whenever I invoke the DELETE OBSOLETE command rman will identify those backups out of the scope of my retention policy and will safely delete them. Nevertheless, there is at least one big exception: when the taken backup is corrupted.&lt;br /&gt;&lt;br /&gt;The following is quite self explanatory. Lets assume we have a retention policy of redundancy 1 and we take a new backup of the database.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;RMAN&gt; backup database;&lt;br /&gt;&lt;br /&gt;Starting backup at 01-11-2009 11:20:53&lt;br /&gt;using channel ORA_DISK_1&lt;br /&gt;using channel ORA_DISK_2&lt;br /&gt;channel ORA_DISK_1: starting compressed full datafile backup set&lt;br /&gt;channel ORA_DISK_1: specifying datafile(s) in backup set&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;channel ORA_DISK_1: backup set complete, elapsed time: 00:01:26&lt;br /&gt;Finished backup at 01-11-2009 11:22:20&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, we have two backups and, according to the configured retention policy, the previous one becomes obsolete. However, let's suppose that the backup we just taken is corrupted. We can simulate this using dd (we're zeroing 1MB somewhere in between):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;dd if=/dev/zero of=o1_mf_nnndf_TAG20091101T232053_5gvyxpwt_.bkp bs=1M seek=10 count=1&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Okey! As a good practice it's nice to validate the backup using the "RESTORE VALIDATE BACKUP" so let's do it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;RMAN&gt; restore validate database;&lt;br /&gt;&lt;br /&gt;Starting restore at 01-11-2009 11:30:10&lt;br /&gt;using target database control file instead of recovery catalog&lt;br /&gt;allocated channel: ORA_DISK_1&lt;br /&gt;channel ORA_DISK_1: SID=42 device type=DISK&lt;br /&gt;allocated channel: ORA_DISK_2&lt;br /&gt;channel ORA_DISK_2: SID=37 device type=DISK&lt;br /&gt;&lt;br /&gt;channel ORA_DISK_1: starting validation of datafile backup set&lt;br /&gt;channel ORA_DISK_2: starting validation of datafile backup set&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;ORA-19599: block number 1280 is corrupt in backup piece &lt;br /&gt;/opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/backupset/2009_11_01/o1_mf_nnndf_TAG20091101T232053_5gvyxpwt_.bkp&lt;br /&gt;&lt;br /&gt;channel ORA_DISK_2: piece handle=/opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/backupset/2009_11_01/o1_mf_nnndf_TAG20091101T232053_5gvyxp3o_.bkp &lt;br /&gt;tag=TAG20091101T232053&lt;br /&gt;channel ORA_DISK_2: restored backup piece 1&lt;br /&gt;channel ORA_DISK_2: validation complete, elapsed time: 00:00:35&lt;br /&gt;failover to previous backup&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;Finished restore at 01-11-2009 11:31:13&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see the BACKUP VALIDATE worked as expected. It identified the corrupted backupset and failed over to the previous valid one. However, what if at the end of the backup script there's a "delete noprompt obsolete" command?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;RMAN&gt; delete noprompt obsolete;&lt;br /&gt;&lt;br /&gt;RMAN retention policy will be applied to the command&lt;br /&gt;RMAN retention policy is set to redundancy 1&lt;br /&gt;using channel ORA_DISK_1&lt;br /&gt;using channel ORA_DISK_2&lt;br /&gt;Deleting the following obsolete backups and copies:&lt;br /&gt;Type                 Key    Completion Time    Filename/Handle&lt;br /&gt;-------------------- ------ ------------------ --------------------&lt;br /&gt;Archive Log          2      01-11-2009 10:40:27 /opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/archivelog/2009_11_01/o1_mf_1_6_5gvwkv55_.arc&lt;br /&gt;Backup Set           10     01-11-2009 11:19:57&lt;br /&gt;  Backup Piece       10     01-11-2009 11:19:57 /opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/backupset/2009_11_01/o1_mf_nnndf_TAG20091101T231814_5gvyrqdc_.bkp&lt;br /&gt;Backup Set           9      01-11-2009 11:19:53&lt;br /&gt;  Backup Piece       9      01-11-2009 11:19:53 /opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/backupset/2009_11_01/o1_mf_nnndf_TAG20091101T231814_5gvyrqtm_.bkp&lt;br /&gt;Backup Set           11     01-11-2009 11:20:04&lt;br /&gt;  Backup Piece       11     01-11-2009 11:20:04 /opt/oracle/app/oracle/flash_recovery_area&lt;br /&gt;/VENUSDB/autobackup/2009_11_01/o1_mf_s_701824802_5gvyw3h1_.bkp&lt;br /&gt;deleted archived log&lt;br /&gt;archived log file name=/opt/oracle/app/oracle/flash_recovery_area/VENUSDB/archivelog/&lt;br /&gt;2009_11_01/o1_mf_1_6_5gvwkv55_.arc RECID=2 STAMP=701822427&lt;br /&gt;deleted backup piece&lt;br /&gt;backup piece handle=/opt/oracle/app/oracle/flash_recovery_area/VENUSDB/backupset/&lt;br /&gt;2009_11_01/o1_mf_nnndf_TAG20091101T231814_5gvyrqdc_.bkp RECID=10 STAMP=701824695&lt;br /&gt;deleted backup piece&lt;br /&gt;backup piece handle=/opt/oracle/app/oracle/flash_recovery_area/VENUSDB/backupset/&lt;br /&gt;2009_11_01/o1_mf_nnndf_TAG20091101T231814_5gvyrqtm_.bkp RECID=9 STAMP=701824695&lt;br /&gt;deleted backup piece&lt;br /&gt;backup piece handle=/opt/oracle/app/oracle/flash_recovery_area/VENUSDB/autobackup/&lt;br /&gt;2009_11_01/o1_mf_s_701824802_5gvyw3h1_.bkp RECID=11 STAMP=701824803&lt;br /&gt;Deleted 4 objects&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Uuups! It just deleted our valid backupset. The proof:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;RMAN&gt; restore validate database;&lt;br /&gt;&lt;br /&gt;Starting restore at 01-11-2009 11:35:03&lt;br /&gt;using channel ORA_DISK_1&lt;br /&gt;using channel ORA_DISK_2&lt;br /&gt;&lt;br /&gt;channel ORA_DISK_1: starting validation of datafile backup set&lt;br /&gt;channel ORA_DISK_2: starting validation of datafile backup set&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============&lt;br /&gt;RMAN-00571: ===========================================================&lt;br /&gt;RMAN-03002: failure of restore command at 11/01/2009 23:35:40&lt;br /&gt;RMAN-06026: some targets not found - aborting restore&lt;br /&gt;RMAN-06023: no backup or copy of datafile 5 found to restore&lt;br /&gt;RMAN-06023: no backup or copy of datafile 3 found to restore&lt;br /&gt;RMAN-06023: no backup or copy of datafile 2 found to restore&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I don't know if the above behavior is clearly mentioned in the Oracle backup and recovery documentation but this should be taken into account when defining the backup and recovery strategy. Of course a RETENTION POLICY of 1 is not a setting to be used in productive systems but, anyway, I expect troubles even if the retention policy is set to a higher redundancy. In my option, it would be great if RMAN could label somehow the corrupted backups at the time the restore validate is invoked and then to take into account this when the retention policy is applied.&lt;br /&gt;&lt;br /&gt;Meanwhile, in order to avoid the above scenario within your backup scripts, it's advisable to group the RESTORE VALIDATE and DELETE NOPROMPT OBSOLETE within a RUN { ... } command. If the first command fails then the DELETE command will never be executed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1775092953935296088?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1775092953935296088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1775092953935296088' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1775092953935296088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1775092953935296088'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/11/rman-retention-policy-with-corrupted.html' title='RMAN Retention Policy with Corrupted Backups'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1803906280225196784</id><published>2009-04-28T22:51:00.000-07:00</published><updated>2010-02-22T02:30:26.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>CREATE VIEW with FORCE does not work</title><content type='html'>Yesterday I loaded an oracle dump in our 10.2.0.4 database... and guess what? Not all the views were created. I took a look into the impdp log and I saw some errors complaining that: ORA-00980: synonym translation is no longer valid. So what? The CREATE VIEW statements were issued with the FORCE clause therefore it should have been created, right?&lt;br /&gt;&lt;br /&gt;Well, after some diggings on metalink I found &lt;a href="https://metalink2.oracle.com/metalink/plsql/f?p=130:14:1113444823878836480::::p14_database_id,p14_docid,p14_show_header,p14_show_help,p14_b"&gt;this&lt;/a&gt;. It basically says that there is a(nother) bug and according to their description: &lt;code&gt;create force view using a synonym for a table fails to create the view if the synonym is invalid.&lt;/code&gt; The 10.2.0.3 and 10.2.0.4 databases are confirmed to be affected and this bug is supposed to be fixed in 10.2.0.5 and 11.2.&lt;br /&gt;&lt;br /&gt;In my case, the solution was to fix the synonyms problem and after that to reimport just the views using the INCLUDE parameter of the impdp utility.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1803906280225196784?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1803906280225196784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1803906280225196784' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1803906280225196784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1803906280225196784'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/04/create-view-with-force-does-not-work.html' title='CREATE VIEW with FORCE does not work'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5603812309021987227</id><published>2009-02-12T01:05:00.000-08:00</published><updated>2010-02-22T02:49:32.031-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WTF'/><title type='text'>WTF is that? (ep. 2)</title><content type='html'>Today, the next episode of the Oracle WTF stories. One of my colleague brought to my attention the fact that the DECODE function doesn't work as expected when used with dates. He had a very simple test case:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create table muci (my_date date);&lt;br /&gt;&lt;br /&gt;insert into muci&lt;br /&gt;  select decode(to_date('30/12/2099', 'dd/mm/yyyy'),&lt;br /&gt;                sysdate,&lt;br /&gt;                null,&lt;br /&gt;                to_date('30/12/2099', 'dd/mm/yyyy')) from dual;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;He asked me: what we'll have in "MUCI" table after running the statements above? I didn't think too much. I realized that SYSDATE is not likely to be 30/12/2099, even the possibility of having a wrong setting in the OS clock couldn't be excluded, but anyway, I simply said that the final result should be 30/12/2099.&lt;br /&gt;&lt;br /&gt;Let's take a look:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select to_char(my_date, 'dd/mm/yyyy') from muci;&lt;br /&gt; &lt;br /&gt;TO_CHAR(MY_DATE,'DD/MM/YYYY')&lt;br /&gt;-----------------------------&lt;br /&gt;30/12/1999&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, this was unexpected.. WTF? What's wrong with the YEAR? Even with a wrong OS clock setting this shouldn't happen. The reason must be somewhere else. Because I remembered that the result of DECODE depends on the type of the arguments, I said: let's look into docs! Yeap, the answer was there: "&lt;span style="font-style:italic;"&gt;if the first result is null, then Oracle converts the return value to the datatype VARCHAR2&lt;/span&gt;". How this applies to our test case? It's simple: in fact, the whole result of the DECODE is a VARCHAR2 and not a DATE as one might think. The VARCHAR2 representation of a plain date value depends on the NLS_DATE_FORMAT, which on our server was: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select value from nls_session_parameters &lt;br /&gt;where parameter='NLS_DATE_FORMAT';&lt;br /&gt; &lt;br /&gt;VALUE&lt;br /&gt;----------------------------------------&lt;br /&gt;DD-MON-RR&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, when the INSERT was done, the inserted value was '30/12/99' which was further automatically casted to a DATE according to the NLS_DATE_FORMAT setting and we ended up with a “wrong” year in the final result. Lovely!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5603812309021987227?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5603812309021987227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5603812309021987227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5603812309021987227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5603812309021987227'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2009/02/wtf-is-that-ep-2.html' title='WTF is that? (ep. 2)'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1805125025973862799</id><published>2008-10-07T03:09:00.000-07:00</published><updated>2010-02-22T02:30:26.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Remotely Connect to a RESTRICT Opened Database</title><content type='html'>Lately, I have this sub-conscience mantra which basically says: don’t believe everything Oracle Official Docs say but try and prove those facts! For example, one thing to try is starting an instance in restricted mode and prove after that what Oracle says in the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/start001.htm#i1006368"&gt;Administration Guide 11g/Starting Up a Database&lt;/a&gt; chapter:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;when the instance is in restricted mode, a database administrator cannot access the instance remotely through an Oracle Net listener, but can only access the instance locally from the machine that the instance is running on.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Lets try! On the server:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; startup restrict&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  835104768 bytes&lt;br /&gt;Fixed Size                  2149000 bytes&lt;br /&gt;Variable Size             595592568 bytes&lt;br /&gt;Database Buffers          230686720 bytes&lt;br /&gt;Redo Buffers                6676480 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;Database opened.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On the client, using an admin user:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Enter user-name: admin@tbag&lt;br /&gt;Enter password:&lt;br /&gt;ERROR:&lt;br /&gt;ORA-12526: TNS:listener: all appropriate instances are in restricted mode&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What they forget to say here is the fact that this behavior is obtained just with dynamic listener registration. If I’m going to explicitly specify the SID_LIST within my listener.ora file then I can connect remotely without problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1805125025973862799?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1805125025973862799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1805125025973862799' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1805125025973862799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1805125025973862799'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/10/remotely-connect-to-restrict-opened.html' title='Remotely Connect to a RESTRICT Opened Database'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-6003820161502546627</id><published>2008-06-12T02:17:00.000-07:00</published><updated>2010-02-22T02:49:53.606-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Oracle Linux Date</title><content type='html'>&lt;p&gt;If you’ll ever need to get the current Linux time from Oracle then you might be interested in the following solution. First of all, the Linux epoch time is expressed as the number of seconds since 1970-01-01 00:00:00 UTC and can be obtain by using the &lt;code&gt;date +'%s'&lt;/code&gt; command. For example:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;oracle@oxg:~$ date +'%s'&lt;br /&gt;1213261534&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;From Oracle you can use the following custom function:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;create or replace function current_linux_date return integer is&lt;br /&gt;  l_crr_date timestamp(9) := SYS_EXTRACT_UTC(systimestamp);&lt;br /&gt;  l_ref_date timestamp(9) := to_date('01011970', 'ddmmyyyy');&lt;br /&gt;  l_seconds integer;&lt;br /&gt;begin&lt;br /&gt;  l_seconds := extract(day from (l_crr_date - l_ref_date)) * 24 * 3600 +&lt;br /&gt;               extract(hour from (l_crr_date - l_ref_date)) * 3600 +&lt;br /&gt;               extract(minute from (l_crr_date - l_ref_date)) * 60 +&lt;br /&gt;               extract(second from (l_crr_date - l_ref_date));&lt;br /&gt;  return(l_seconds);&lt;br /&gt;end current_linux_date;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now, you should get the same result from Oracle:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select current_linux_date from dual;&lt;br /&gt; &lt;br /&gt;CURRENT_LINUX_DATE&lt;br /&gt;------------------&lt;br /&gt;        1213261993&lt;br /&gt;&lt;br /&gt;oracle@oxg:~$ date +'%s'&lt;br /&gt;1213261993&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Have fun!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-6003820161502546627?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/6003820161502546627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=6003820161502546627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6003820161502546627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6003820161502546627'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/06/oracle-linux-date.html' title='Oracle Linux Date'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-6921069521197119118</id><published>2008-05-12T03:44:00.000-07:00</published><updated>2010-02-22T02:50:27.951-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tuning'/><title type='text'>Profiling the new SIMPLE_INTEGER type</title><content type='html'>Oracle 11g comes with a new PLSQL type called SIMPLE_INTEGER. The official documentation says that this type yield significant performance compared to PLS_INTEGER type. Because I want to see this with my own eyes I’ve decided to test it using another new 11g component called hierarchical profiler which I also want to see how it’s working.&lt;br /&gt;&lt;br /&gt; First of all, let’s setup the environment:&lt;br /&gt;&lt;br /&gt;1. on the database server create a new directory to be used for creating profiler trace files:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;oracle@obi:oracle$ mkdir profiler&lt;br /&gt;oracle@obi:oracle$ chmod o-rx profiler/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. create the DIRECTORY object in the database too, and grant read/write privileges to the testing user (in our case TALEK user):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; create directory profiler_dir as '/opt/oracle/profiler';&lt;br /&gt;&lt;br /&gt;Directory created.&lt;br /&gt;&lt;br /&gt;SQL&gt; grant read, write on directory profiler_dir to talek;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. grant execute privilege for DBMS_HPROF package to the TALEK user:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; grant execute on dbms_hprof to talek;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. connect using TALEK user and create the following package (the only difference between the first and second approach is the type of the l_count variable):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;create or replace package trash is&lt;br /&gt;&lt;br /&gt;  procedure approach_1;&lt;br /&gt;  &lt;br /&gt;  procedure approach_2;&lt;br /&gt;&lt;br /&gt;end trash;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;create or replace package body trash is&lt;br /&gt;&lt;br /&gt;  procedure approach_1 as&lt;br /&gt;    l_count pls_integer := 0;&lt;br /&gt;  begin&lt;br /&gt;    for i in 1..10000 loop&lt;br /&gt;      l_count := l_count + 1;&lt;br /&gt;    end loop;&lt;br /&gt;    dbms_output.put_line(l_count);&lt;br /&gt;  end;&lt;br /&gt;  &lt;br /&gt;  procedure approach_2 as&lt;br /&gt;    l_count simple_integer := 0;&lt;br /&gt;  begin&lt;br /&gt;    for i in 1..10000 loop&lt;br /&gt;      l_count := l_count + 1;&lt;br /&gt;    end loop;&lt;br /&gt;    dbms_output.put_line(l_count);&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;end trash;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;5. Profile the approaches:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; exec dbms_hprof.start_profiling(location =&gt; 'PROFILER_DIR', filename =&gt; 'test.trc');&lt;br /&gt; &lt;br /&gt;PL/SQL procedure successfully completed&lt;br /&gt; &lt;br /&gt;SQL&gt; exec trash.approach_1;&lt;br /&gt; &lt;br /&gt;PL/SQL procedure successfully completed&lt;br /&gt; &lt;br /&gt;SQL&gt; exec trash.approach_2;&lt;br /&gt; &lt;br /&gt;PL/SQL procedure successfully completed&lt;br /&gt; &lt;br /&gt;SQL&gt; exec dbms_hprof.stop_profiling;&lt;br /&gt; &lt;br /&gt;PL/SQL procedure successfully completed&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;6. Analyze the generated trace file. For this we’ll use the "plshprof" command line utility.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;oracle@obi:profiler$ plshprof -output report test.trc&lt;br /&gt;PLSHPROF: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production&lt;br /&gt;[8 symbols processed]&lt;br /&gt;[Report written to 'report.html']&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Aaaaand, the WINNER is:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;TALEK.TRASH.APPROACH_1 -&gt; 5713 (microseconds)&lt;br /&gt;TALEK.TRASH.APPROACH_2 -&gt; 100706 (microseconds)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well… this is unexpected. According to Oracle docs, the SIMPLE_INTEGER should be faster. Ok, back to official doc: &lt;i&gt;"The new PL/SQL SIMPLE_INTEGER data type is a binary integer for use with native compilation which is neither null checked nor overflow checked"&lt;/i&gt;. Ahaaa… native compilation! Let’s check this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; show parameter plsql_code_type&lt;br /&gt;&lt;br /&gt;NAME                                 TYPE        VALUE&lt;br /&gt;------------------------------------ ----------- ------------------------------&lt;br /&gt;plsql_code_type                      string      INTERPRETED&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, we have a first clue and a first conclusion. If the database doesn’t use NATIVE compilation the SIMPLE_INTEGER type is actually much slower.&lt;br /&gt;&lt;br /&gt;Let’s switch to native compilation. This can be easily done because the "plsql_code_type" parameter is dynamic:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter system set plsql_code_type=native scope=both;&lt;br /&gt;&lt;br /&gt;System altered.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It is important to compile once again the package because otherwise the old PLSQL byte code will be used (you can use "alter package trash compile plsql_code_type=native;"), then repeat the profiler tests.&lt;br /&gt;&lt;br /&gt;The new results are:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;TALEK.TRASH.APPROACH_2 -&gt; 3927 (microseconds)&lt;br /&gt;TALEK.TRASH.APPROACH_1 -&gt; 12556 (microseconds)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, the second approach with SIMPLE_INTEGER is much faster and, interestingly, the PLS_INTEGER approach is slightly slower on native compilation compared with the same approach on the initial PLSQL interpreted environment.&lt;br /&gt;&lt;br /&gt;Okey, one more thing. I really enjoy using the new 11g hierarchical profiler. From my point of view is a big step forward compared with the old DBMS_PROFILER, and the provided HTML reports produced by "plshprof" are quite lovely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-6921069521197119118?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/6921069521197119118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=6921069521197119118' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6921069521197119118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6921069521197119118'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/05/profiling-new-simpleinteger-type.html' title='Profiling the new SIMPLE_INTEGER type'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7637591608066392329</id><published>2008-05-11T11:56:00.000-07:00</published><updated>2010-02-22T02:49:32.031-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WTF'/><title type='text'>WTF is that? (ep. 1)</title><content type='html'>I've just decided to put here some posts about the (...well, you know) Oracle WTF stories, those moments (... hours, and sometimes days) when being at my desk, I'm just staring at that stupid SQLPLUS&gt; prompt couldn't figure out what the hell is happening.&lt;br /&gt;&lt;br /&gt;Today, episode 1:&lt;br /&gt;&lt;br /&gt;The scenario is very simple. I have two nice users: TALEK and SIM. TALEK has a table and gives UPDATE rights to SIM.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; connect talek&lt;br /&gt;Enter password: &lt;br /&gt;Connected.&lt;br /&gt;&lt;br /&gt;SQL&gt; create table muci (col1 varchar2(10));&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;SQL&gt; insert into muci values ('abc')&lt;br /&gt;  2  /&lt;br /&gt;&lt;br /&gt;1 row created.&lt;br /&gt;&lt;br /&gt;SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete.&lt;br /&gt;&lt;br /&gt;SQL&gt; grant update on muci to sim;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;br /&gt;&lt;br /&gt;SQL&gt; connect sim&lt;br /&gt;Enter password: &lt;br /&gt;Connected.&lt;br /&gt;&lt;br /&gt;SQL&gt; update talek.muci set col1='xyz' where col1='abc';&lt;br /&gt;update talek.muci set col1='xyz' where col1='abc'&lt;br /&gt;             *&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-01031: insufficient privileges&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, this is the WTF moment. Why the UPDATE failed? The first thing to do is to check the DBA_TAB_PRIVS view for a confirmation that the UPDATE privilege is still there. (I'm pretty sure that no one was so fast to revoke meanwhile the granted privilege but, just in case...)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select grantee, owner, table_name, privilege &lt;br /&gt;from dba_tab_privs where table_name='MUCI' and owner='TALEK';&lt;br /&gt;&lt;br /&gt;GRANT OWNER TABLE_NAM PRIVILEGE&lt;br /&gt;----- ----- --------- ----------&lt;br /&gt;SIM   TALEK MUCI      UPDATE&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And yes, the privilege is there. Hmmm... what's next? Usually the next thought is that another Oracle bug makes fun of me. But, this sounds too scary to be true. Finally, the stupid answer comes to light.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; show parameter sql92_security&lt;br /&gt;&lt;br /&gt;NAME                                 TYPE        VALUE&lt;br /&gt;------------------------------------ ----------- ------------------------------&lt;br /&gt;sql92_security                       boolean     TRUE&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The database reference documentation says the following:&lt;br /&gt;&lt;i&gt;"The SQL92 standards specify that security administrators should be able to require that users have SELECT privilege on a table when executing an UPDATE or DELETE statement that references table column values in a WHERE or SET clause. SQL92_SECURITY specifies whether users must have been granted the SELECT object privilege in order to execute such UPDATE or DELETE statements."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;With the above sql92_security parameter set, actually the "where col1='abc'" filter from the UPDATE statement complains about "insufficient privileges" and not the UPDATE itself. Without a filter the update executes as expected:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; update talek.muci set col1='xyz';&lt;br /&gt;&lt;br /&gt;1 row updated.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, another lesson has been learned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7637591608066392329?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7637591608066392329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7637591608066392329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7637591608066392329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7637591608066392329'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/05/wtf-is-that-ep-1.html' title='WTF is that? (ep. 1)'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-3651212628204022909</id><published>2008-05-09T04:43:00.000-07:00</published><updated>2010-02-22T02:51:05.296-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grid Manager'/><title type='text'>Obsolete Policy Violation</title><content type='html'>This is quite funny. Starting with 10g the LOG_ARCHIVE_START parameter is obsolete. Nevertheless, into the "Database Control" of a new installed 11g database I have a policy rule violation called "Use of Automatic Log Archival Features". The description of this policy rule says: "This policy ensures that archiving of redo logs is done automatically and prevents suspension of instance operations when redo logs fill. Only applicable if database is in archivelog mode". &lt;br /&gt;&lt;br /&gt;Well, my database is already configured to run in archivelog mode:&lt;br /&gt;&lt;pre&gt;SQL&gt; archive log list&lt;br /&gt;Database log mode              Archive Mode&lt;br /&gt;Automatic archival             Enabled&lt;br /&gt;Archive destination            USE_DB_RECOVERY_FILE_DEST&lt;br /&gt;Oldest online log sequence     15&lt;br /&gt;Next log sequence to archive   17&lt;br /&gt;Current log sequence           17&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, where is the problem? The action suggested by "Database Control" console is "Set the value of the LOG_ARCHIVE_START initialization parameter to TRUE". Hmmm, that is to set an obsolete parameter... no, thanks!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; Actually, I discovered that there are a lot of non-relevant/obsolete policies for 11g, like SGA_TARGET is not used, or PGA_AGGREGATE_TARGET should be used etc. It seems that many default settings from the "Database Control" do not take into consideration the actual version of the managed database therefore you have to manually suppress these policy/rule violations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-3651212628204022909?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/3651212628204022909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=3651212628204022909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3651212628204022909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/3651212628204022909'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/05/obsolete-policy-violation.html' title='Obsolete Policy Violation'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1783869331837693754</id><published>2008-03-27T06:22:00.000-07:00</published><updated>2010-02-22T02:50:27.951-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tuning'/><title type='text'>TKPROF Everywhere</title><content type='html'>Lately, I was searching for a solution to let developers to “tkprof” their statements in the most non-intrusive way possible. Of course, a quite appealing solution I found was the one suggested by Tom Kyte in his “Effective Oracle by Design” book. The solution involves reading the user trace file from the server and returning the content of that trace through a pipelined table function. The result may be spooled into a file on the client side and, after that, “tkprof” may be executed for this local file. However, the problem I have is that me, personally, I use oracle instant client and I don't have tkprof on my local machine. Furthermore, I don't use sqlplus all the time, therefore I would really like to get the formatted tkprof output directly within a simple SQL-SELECT statement.&lt;br /&gt;&lt;br /&gt;The solution is quite simple: instead of returning the raw trace file it's enough to run tkprof utility on the server with the user dump trace file as a parameter and, eventually, to return the final output.&lt;br /&gt;&lt;br /&gt;In order to setup the needed environment we'll have to:&lt;br /&gt;&lt;br /&gt;1.create the user which will own the “tkprof” framework:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grant create session, alter session, create procedure to tools identified by xxx;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2.grant additional privileges for this user:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grant select on sys.v_$process to tools;&lt;br /&gt;grant select on sys.v_$session to tools;&lt;br /&gt;exec dbms_java.grant_permission( 'TOOLS', &lt;br /&gt;  'SYS:java.lang.RuntimePermission', writeFileDescriptor', '' );&lt;br /&gt;exec dbms_java.grant_permission( 'TOOLS', &lt;br /&gt;  'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '' );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;3.create the following java source object. This is needed in order to execute an external program in the OS environment (thanks again Tom for this, see the &lt;a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:952229840241"&gt;Java procedure for host calls on Unix environment&lt;/a&gt; question.):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create or replace and compile java source named util as&lt;br /&gt;import java.io.*;&lt;br /&gt;import java.lang.*;&lt;br /&gt;&lt;br /&gt;public class Util extends Object&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt; public static int RunThis(String args)&lt;br /&gt; {&lt;br /&gt; Runtime rt = Runtime.getRuntime();&lt;br /&gt; int        rc = -1;&lt;br /&gt;&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;    Process p = rt.exec(args);&lt;br /&gt;&lt;br /&gt;    int bufSize = 4096;&lt;br /&gt;    BufferedInputStream bis =&lt;br /&gt;     new BufferedInputStream(p.getInputStream(), bufSize);&lt;br /&gt;    int len;&lt;br /&gt;    byte buffer[] = new byte[bufSize];&lt;br /&gt;&lt;br /&gt;    // Echo back what the program spit out&lt;br /&gt;    while ((len = bis.read(buffer, 0, bufSize)) != -1)&lt;br /&gt;       System.out.write(buffer, 0, len);&lt;br /&gt;&lt;br /&gt;    rc = p.waitFor();&lt;br /&gt; }&lt;br /&gt; catch (Exception e)&lt;br /&gt; {&lt;br /&gt;    e.printStackTrace();&lt;br /&gt;    rc = -1;&lt;br /&gt; }&lt;br /&gt; finally&lt;br /&gt; {&lt;br /&gt;    return rc;&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4.Create the package which embeds the whole tracing logic:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create or replace package tkprof &lt;br /&gt;/**&lt;br /&gt;  Provides the tkprof tracing feature to developers. This package is&lt;br /&gt;  supposed to be used in developing environments only.&lt;br /&gt;  &lt;br /&gt;  Required rights (the owner of this package is supposed to be TOOLS):&lt;br /&gt;  &lt;br /&gt;  grant alter session to tools;&lt;br /&gt;  grant select on sys.v_$process to tools;&lt;br /&gt;  grant select on sys.v_$session to tools;&lt;br /&gt;  &lt;br /&gt;  exec dbms_java.grant_permission( 'TOOLS', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '' );&lt;br /&gt;  exec dbms_java.grant_permission( 'TOOLS', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '' );&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;is&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;    The complete path along the name of the tkprof utility. Change this constant to fit to your&lt;br /&gt;    environment. After that the following right is required:&lt;br /&gt;    &lt;br /&gt;    exec dbms_java.grant_permission( 'TOOLS', 'SYS:java.io.FilePermission', TKPROF.TKPROF_EXECUTABLE, 'execute' );&lt;br /&gt;    &lt;br /&gt;    If a RAC configuration is used than the path should be the same accross all nodes. If the ORACLE_HOME&lt;br /&gt;    env variable is different between the RAC nodes then the value of the ORACLE_HOME should be get dynamically&lt;br /&gt;    by using, for example, the DBMS_SYSTEM.get_env procedure or symbolinc links may be created in the OS&lt;br /&gt;    environment of every RAC node.&lt;br /&gt;  */&lt;br /&gt;  TKPROF_EXECUTABLE constant varchar2(300) := '/opt/oracle/product/10.2.0/db_1/bin/tkprof';&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;    The directory where the user trace files are stored. May be found out using:&lt;br /&gt;&lt;br /&gt;    show parameter user_dump_dest&lt;br /&gt;    &lt;br /&gt;    If a RAC configuration is used than the path should be the same accross all nodes. If not, then the value&lt;br /&gt;    should be fetch dynamically from v$parameter view. Another approach would be to create symbolic links in the&lt;br /&gt;    OS environment of every RAC node.&lt;br /&gt;  */&lt;br /&gt;  UDUMP_PATH constant varchar2(300) := '/opt/oracle/admin/rfd/udump';&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;    The name of the oracle directory object which points out to the above&lt;br /&gt;    path. The owner of this package must have read privileges on this&lt;br /&gt;    directory:&lt;br /&gt;    &lt;br /&gt;    create directory UDUMP_DIR as '/opt/oracle/admin/rfd/udump';&lt;br /&gt;    grant read on directory UDUMP_DIR to tools;&lt;br /&gt;  */&lt;br /&gt;  UDUMP_DIR constant varchar2(30) := 'UDUMP_DIR';&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;    A simple type used to return the tkprof_output.&lt;br /&gt;  */&lt;br /&gt;  type tkprof_output is table of varchar2(4000);&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;    Enable tracing for the current session. &lt;br /&gt;  */&lt;br /&gt;  procedure enable;&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;    Disable tracing for the current session.&lt;br /&gt;  */&lt;br /&gt;  procedure disable;&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;    Get the status of the tracing for the current session.&lt;br /&gt;    &lt;br /&gt;    #return 'TRUE' if the trace is enabled, 'FALSE' otherwise.&lt;br /&gt;  */&lt;br /&gt;  function is_enabled return varchar2;&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;    Get the tkprof content thorough a pipelined table function.&lt;br /&gt;&lt;br /&gt;    #pi_tkprof_params additional parameters to tkprof&lt;br /&gt;  */&lt;br /&gt;  function output(pi_tkprof_params varchar2 := '') return tkprof_output pipelined;&lt;br /&gt;&lt;br /&gt;end tkprof;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;create or replace package body tkprof is&lt;br /&gt;&lt;br /&gt;  g_unique_session_id varchar2(100);&lt;br /&gt;  g_trace_file_name   varchar2(4000);&lt;br /&gt;  g_is_enabled        boolean;&lt;br /&gt;&lt;br /&gt;  function run(pi_cmd in varchar2) return number as&lt;br /&gt;    language java name 'Util.RunThis(java.lang.String) return integer';&lt;br /&gt;&lt;br /&gt;  procedure enable as&lt;br /&gt;  begin&lt;br /&gt;    execute immediate 'alter session set tracefile_identifier=''' ||&lt;br /&gt;                      g_unique_session_id || '''';&lt;br /&gt;    execute immediate 'alter session set timed_statistics=true';&lt;br /&gt;    execute immediate 'alter session set max_dump_file_size=unlimited';&lt;br /&gt;    execute immediate 'alter session set events ''10046 trace name context forever, level 12''';&lt;br /&gt;    g_is_enabled := true;&lt;br /&gt;    dbms_output.put_line('session tracing enabled under ' ||&lt;br /&gt;                         g_unique_session_id || ' identifier.');&lt;br /&gt;  end;&lt;br /&gt;  &lt;br /&gt;  function is_enabled return varchar2 as&lt;br /&gt;  begin&lt;br /&gt;    if g_is_enabled then&lt;br /&gt;      return 'TRUE';&lt;br /&gt;    else&lt;br /&gt;      return 'FALSE';&lt;br /&gt;    end if;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  procedure disable as&lt;br /&gt;  begin&lt;br /&gt;    execute immediate 'alter session set events ''10046 trace name context off''';&lt;br /&gt;    g_is_enabled := false;&lt;br /&gt;    dbms_output.put_line('session tracing disabled');&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  function output(pi_tkprof_params varchar2 := '') return tkprof_output&lt;br /&gt;    pipelined as&lt;br /&gt;    l_status  pls_integer;&lt;br /&gt;    l_bfile   bfile := bfilename(UDUMP_DIR, g_trace_file_name || '.prf');&lt;br /&gt;    l_last    pls_integer := 1;&lt;br /&gt;    l_current pls_integer;&lt;br /&gt;  begin&lt;br /&gt;    dbms_java.set_output(10000);&lt;br /&gt;    l_status := run(TKPROF_EXECUTABLE || ' ' || UDUMP_PATH || '/' ||&lt;br /&gt;                    g_trace_file_name || ' ' || UDUMP_PATH || '/' ||&lt;br /&gt;                    g_trace_file_name || '.prf ' || pi_tkprof_params);&lt;br /&gt;    if l_status != 0 then&lt;br /&gt;      dbms_output.put_line('status: ' || l_status);&lt;br /&gt;      dbms_output.put_line('ERROR: cannot produce the tkprof trace!');&lt;br /&gt;      return;&lt;br /&gt;    else&lt;br /&gt;      dbms_lob.fileopen(l_bfile);&lt;br /&gt;      loop&lt;br /&gt;        l_current := dbms_lob.instr(l_bfile, '0A', l_last, 1);&lt;br /&gt;        exit when(nvl(l_current, 0) = 0);&lt;br /&gt;        pipe row(utl_raw.cast_to_varchar2(dbms_lob.substr(l_bfile,&lt;br /&gt;                                                          l_current -&lt;br /&gt;                                                          l_last + 1,&lt;br /&gt;                                                          l_last)));&lt;br /&gt;        l_last := l_current + 1;&lt;br /&gt;      end loop;&lt;br /&gt;      dbms_lob.fileclose(l_bfile);&lt;br /&gt;    end if;&lt;br /&gt;  exception&lt;br /&gt;    when others then&lt;br /&gt;      if dbms_lob.isopen(l_bfile) != 0 then&lt;br /&gt;        dbms_lob.fileclose(l_bfile);&lt;br /&gt;      end if;&lt;br /&gt;      raise;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;begin&lt;br /&gt;  g_unique_session_id := sys_context('userenv', 'sessionid');&lt;br /&gt;  select sys_context('userenv', 'instance_name') || '_ora_' ||&lt;br /&gt;         ltrim(to_char(a.spid)) || '_' || g_unique_session_id || '.trc'&lt;br /&gt;    into g_trace_file_name&lt;br /&gt;    from v$process a, v$session b&lt;br /&gt;   where a.addr = b.paddr&lt;br /&gt;     and b.audsid = sys_context('userenv', 'sessionid');&lt;br /&gt;end tkprof;&lt;br /&gt;/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;5.Change the TKPROF_EXECUTABLE and UDUMP_PATH constants to fit with your environment.&lt;br /&gt;6.Create the UDUMP_DIR directory:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create directory UDUMP_DIR as '/opt/oracle/admin/rfd/udump';&lt;br /&gt;grant read on directory UDUMP_DIR to tools;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;7.Grant execute rights for tkprof executable:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;exec dbms_java.grant_permission( 'TOOLS', 'SYS:java.io.FilePermission', &lt;br /&gt;TKPROF.TKPROF_EXECUTABLE, 'execute' );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;8.Make the TKPROF package available to everybody:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grant execute on tools.tkprof to public;&lt;br /&gt;create public synonym tkprof for tools.tkprof;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Okey, that's it! Now, let's test it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;fits_cr@RFD&gt; exec tkprof.enable&lt;br /&gt;&lt;br /&gt;session tracing enabled under 7154134 identifier.&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;fits_cr@RFD&gt; select count(1) from rolmda;&lt;br /&gt;&lt;br /&gt;  COUNT(1)&lt;br /&gt;----------&lt;br /&gt;        95&lt;br /&gt;&lt;br /&gt;fits_cr@RFD&gt; exec tkprof.disable;&lt;br /&gt;session tracing disabled&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;fits_cr@RFD&gt; select * from table(tkprof.output);&lt;br /&gt;&lt;br /&gt;COLUMN_VALUE&lt;br /&gt;--------------------------------------------------------------------------------------&lt;br /&gt;TKPROF: Release 10.2.0.3.0 - Production on Thu Mar 27 15:13:06 2008&lt;br /&gt;Copyright (c) 1982, 2005, Oracle.  All rights reserved.&lt;br /&gt;Trace file: /opt/oracle/admin/rfd/udump/rfd3_ora_26618_7154134.trc&lt;br /&gt;Sort options: default&lt;br /&gt;&lt;br /&gt;********************************************************************************&lt;br /&gt;count    = number of times OCI procedure was executed&lt;br /&gt;cpu      = cpu time in seconds executing&lt;br /&gt;elapsed  = elapsed time in seconds executing&lt;br /&gt;disk     = number of physical reads of buffers from disk&lt;br /&gt;query    = number of buffers gotten for consistent read&lt;br /&gt;current  = number of buffers gotten in current mode (usually for update)&lt;br /&gt;rows     = number of rows processed by the fetch or execute call&lt;br /&gt;********************************************************************************&lt;br /&gt;&lt;br /&gt;select /*+ index(idl_sb4$ i_idl_sb41) +*/ piece#,length,piece&lt;br /&gt;from&lt;br /&gt; idl_sb4$ where obj#=:1 and part=:2 and version=:3 order by piece#&lt;br /&gt;&lt;br /&gt;call     count       cpu    elapsed       disk      query    current        rows&lt;br /&gt;------- ------  -------- ---------- ---------- ---------- ----------  ----------&lt;br /&gt;Parse        1      0.00       0.00          0          0          0           0&lt;br /&gt;Execute      1      0.00       0.00          0          0          0           0&lt;br /&gt;Fetch        1      0.00       0.00          0          2          0           0&lt;br /&gt;------- ------  -------- ---------- ---------- ---------- ----------  ----------&lt;br /&gt;total        3      0.00       0.00          0          2          0           0&lt;br /&gt;&lt;br /&gt;... and so on ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I'm sure this package can be improved but as a proof of concept I think that it's more than enough. Likewise, I have to mention that this was tested on a 10gR2 database therefore I don't know if you can use it without any changes on a different Oracle database version.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1783869331837693754?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1783869331837693754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1783869331837693754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1783869331837693754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1783869331837693754'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/03/tkprof-everywhere.html' title='TKPROF Everywhere'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-6076579793595459822</id><published>2008-03-22T03:53:00.000-07:00</published><updated>2010-02-22T02:30:26.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>What's Wrong with Oracle TIMESTAMP WITH TIME ZONE Data-type?</title><content type='html'>First of all, let's start by recalling what a TIMESTAMP WITH TIME ZONE data-type is. According to the Oracle official documentation "a TIMESTAMP WITH TIME ZONE is a variant of TIMESTAMP that includes a time zone region name or time zone offset in its value. The time zone offset is the difference (in hours and minutes) between local time and UTC (Coordinated Universal Time, formerly Greenwich Mean Time)".&lt;br /&gt;&lt;br /&gt;Well, very nice... this is a data-type which might be very useful in a distributed environment across all over the world where, unlike its counterpart TIMESTAMP WITH LOCAL TIME ZONE data-type, is also important to record the time zone from which, a transaction or whatsoever information has been inputed into the system. A potential suitable case for using this timezone information might be the producing of a report with all peak hours of activity in the context of a specific timezone area. &lt;br /&gt;&lt;br /&gt;So far so good. What I really don't like about this data-type is that I cannot create a primary/unique constraint on a such a column. The Oracle documentation clear states that "none of the columns in the unique/primary key can be of LOB, LONG, LONG RAW, VARRAY, NESTED TABLE, OBJECT, REF, &lt;bold&gt;TIMESTAMP WITH TIME ZONE&lt;/bold&gt;, or user-defined type. However, the unique/primary key can contain a column of TIMESTAMP WITH LOCAL TIME ZONE".&lt;br /&gt;&lt;br /&gt;Furthermore, any index created for such a column is actually converted into a functional index. Behind the scenes, Oracle automatically normalize all the values of a TIMESTAMP WITH TIME ZONE column using the SYS_EXTRACT_UTC() function. In a way, this makes sens. Suppose we have to order the result-set of a SQL-SELECT using a TIMESTAMP WITH TIME ZONE column. Having for example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;TIMESTAMP '2003-01-01 2:00:00 -08:00&lt;br /&gt;TIMESTAMP '2003-01-01 2:00:00 -02:00&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;what record should be the first one? According to what point of reference? The solution is to normalize all values and only after that to compare the values. Oracle transparently does this.&lt;br /&gt;Now, what if I want that the values to be unique in a TIMESTAMP WITH TIME ZONE column? Well, you can't create a unique constraint but you can create a unique index.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; create table muci_test (&lt;br /&gt;  2   col1 timestamp with time zone,&lt;br /&gt;  3   constraint uk_muci_test_col1 unique(col1)&lt;br /&gt;  4  );&lt;br /&gt;&lt;br /&gt;create table muci_test (&lt;br /&gt; col1 timestamp with time zone,&lt;br /&gt; constraint uk_muci_test_col1 unique(col1)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;ORA-02329: column of datatype TIME/TIMESTAMP WITH TIME ZONE &lt;br /&gt;cannot be unique or a primary key&lt;br /&gt;SQL&gt; create table muci_test (&lt;br /&gt;  2   col1 timestamp with time zone&lt;br /&gt;  3  );&lt;br /&gt;&lt;br /&gt;Table created&lt;br /&gt;&lt;br /&gt;Executed in 0,204 seconds&lt;br /&gt;&lt;br /&gt;SQL&gt; create unique index ix_muci_text_col1 on muci_test(col1);&lt;br /&gt;&lt;br /&gt;Index created&lt;br /&gt;&lt;br /&gt;Executed in 0,25 seconds&lt;br /&gt;&lt;br /&gt;SQL&gt; insert into muci_test values (to_timestamp('22-MAR-08 11.25.39.457137'));&lt;br /&gt;&lt;br /&gt;1 row inserted&lt;br /&gt;&lt;br /&gt;Executed in 0,031 seconds&lt;br /&gt;&lt;br /&gt;SQL&gt; insert into muci_test values (to_timestamp('22-MAR-08 11.25.39.457137'));&lt;br /&gt;&lt;br /&gt;insert into muci_test values (to_timestamp('22-MAR-08 11.25.39.457137'))&lt;br /&gt;&lt;br /&gt;ORA-00001: unique constraint (ADMIN.IX_MUCI_TEXT_COL1) violated&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As I already said, Oracle has actually created a functional index and this can be easily checked:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select index_type from user_indexes where index_name = 'IX_MUCI_TEXT_COL1';&lt;br /&gt;&lt;br /&gt;INDEX_TYPE&lt;br /&gt;---------------------------&lt;br /&gt;FUNCTION-BASED NORMAL&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you don't feel very comfortable with functional indexes or you really want a primary/unique key constraint then the application design should take into consideration this limitation. Me personally, I would choose a TIMESTAMP WITH LOCAL TIME ZONE data-type and an additional VARCHAR2 column to store the originating TIME ZONE offsets. Using this approach it is possible to enforce a multi-column primary/unique key.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-6076579793595459822?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/6076579793595459822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=6076579793595459822' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6076579793595459822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/6076579793595459822'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/03/whats-wrong-with-oracle-timestamp-with.html' title='What&apos;s Wrong with Oracle TIMESTAMP WITH TIME ZONE Data-type?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-7129594291303032846</id><published>2008-02-10T03:58:00.000-08:00</published><updated>2010-02-22T02:30:26.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>ORA_ROWSCN pitfall for optimistic locking</title><content type='html'>I can see lately that there's a big enthusiasm around this new 10g pseudo-column called ORA_ROWSCN, one of its great benefit being for implementing an optimistic locking mechanism. From a simplistic point of view, this mechanism consists of:&lt;br /&gt;&lt;br /&gt;1.on the application server or on the client side we have an entity class which is mapped on a particular table. Instances of that class (objects) reflect rows on that particular table.&lt;br /&gt;2.Every entity object has also a version field which maps to the ORA_ROWSCN pseudo-column.&lt;br /&gt;3.At the very beginning, we are loading our entities using SELECT T.*, ORA_ROWSCN FROM TABLE T so that every entity has the corresponding values and version.&lt;br /&gt;4.Now, suppose that the user changes some attributes from the entity through the application front-end. This changes have to be propagated into the database, most likely using an UPDATE statement, but taking care of the version field. That is, we need to be sure that meanwhile, the version of the entity we are about to persist didn't change within the database. So, all is narrowing down  on performing something like : UPDATE TABLE set COLUMN = [value from the entity] where PK_COLUMN = [id from the entity] and ORA_ROWSCN = [version from the entity]. If the above UPDATE will return “0 rows updated” we'll know for sure that somebody else has changed the record into the database and the application will throw an “Optimistic Lock Exception”.&lt;br /&gt;&lt;br /&gt;So, everything seems to work nicely: no more timestamp version columns, no more OLD and NEW column values comparisons, no more row hashes. In 10g, it seems that Oracle offered us a bullet proof solution. BUUUT, there's a pitfall here. Every decent application is working with transactions therefore every DML is nicely encapsulated into an Oracle transaction. What happens if on the 4th step our update succeeds? Well, in this case the version of the entity will have to be updated accordingly. But, our update is not yet committed therefore we don't have access to the new value of the ORA_ROWSCN which will be available only after COMMIT. This means that, in order to refresh our entity, we'll have to issue an SQL-SELECT after COMMIT, something like: SELECT T.*, ORA_ROWSCN FROM TABLE T WHERE PK_COLUMN=[id from the entity]. The main problem here is the fact that between our COMMIT and the SQL-SELECT there is a tiny time frame within which a lot of nasty things may happen: somebody else may delete our record or may update it once again. Furthermore, the fact that I have to issue an SQL-SELECT after the UPDATE doesn't sound to me very appealing as involves additional work for the database and might affect the whole scalability. In addition I would really like to use the RETURNING clause of the INSERT/UPDATE statements and to refresh my entity in one step.&lt;br /&gt;&lt;br /&gt;In conclusion, if you are designing an WEB application which doesn't reuse entities across WEB pages then using ORA_ROWSCN for implementing optimistic locking is fine as long as the working flow is the following:&lt;br /&gt;&lt;br /&gt;1.the user select the record he/she wants to change from a grid;&lt;br /&gt;2.the application loads the entity and assigns the ORA_ROWSCN value as version;&lt;br /&gt;3.the user performs the required changes and press the SAVE button;&lt;br /&gt;4.the application performs the UPDATE into the database taking care of the ORA_ROWSCN values (WHERE ... and ORA_ROWSCN=[version from the entity]) and COMMITs the changes.&lt;br /&gt;5.the application display once again the initial grid re-querying the database.&lt;br /&gt;&lt;br /&gt;However, if you are designing an application which is required to take advantage of caching (most likely a stand-alone rich client application) then the ORA_ROWSCN is not the right solution. For example:&lt;br /&gt;&lt;br /&gt;1.the application loads a grid and every grid record has the corresponding entity attached;&lt;br /&gt;2.the user select the record he/she wants to change from the grid;&lt;br /&gt;3.the application relies on the data from the corresponding entity therefore it doesn't query the database;&lt;br /&gt;4.the user performs the changes and press the SAVE button;&lt;br /&gt;6.the application performs the UPDATE into the database taking care of the ORA_ROWSCN values (WHERE ... and ORA_ROWSCN=[version from the entity]) and COMMIT the changes.&lt;br /&gt;7.If the UPDATE returns “1 record updated” then our entity is stale because the new version from the database doesn't reflect the old one from the entity. A new SELECT, outside of the UPDATE transaction is required in order to refresh the entity which, of course, is not convenient at all.&lt;br /&gt;&lt;br /&gt;So for this second kind of application I would use a regular version-column or hashing techniques which allows to use the RETURNING clause of the INSERT/UPDATE statements or to refresh the entity within the same modifying transaction.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-7129594291303032846?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/7129594291303032846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=7129594291303032846' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7129594291303032846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/7129594291303032846'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2008/02/orarowscn-pitfall-for-optimistic.html' title='ORA_ROWSCN pitfall for optimistic locking'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-8914791495318484471</id><published>2007-12-06T04:35:00.000-08:00</published><updated>2010-02-22T02:30:26.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>DEFAULT and NOT NULL become friends in 11g</title><content type='html'>If somebody would ask me to add a new column to a production table the first thing I would check is how many active transactions on that table are or, in other words, how hot it is from the concurrency point of view. This is because,  if there are any active transactions on that table, my attempt to change its structure will simply fail. Of course, an online redefinition could be the right solution but is far more complicated than a simple ALTER TABLE. However, with Oracle 11g things change. My decision of using an ALTER TABLE statement instead of a DBMS_REDEFINITION operation when I am about to add new columns should be driven by the answers to the following questions:&lt;br /&gt;1. Is it appropriate for the new column to be NOT NULL and to have a DEFAULT clause?&lt;br /&gt;OR&lt;br /&gt;2. Is it appropriate for the new column to allow NULLs without having a DEFAULT clause?&lt;br /&gt;OR&lt;br /&gt;3. Is it about a virtual column?&lt;br /&gt;If the answer is YES you can safety go on with the ALTER TABLE ADD COLUMN statement.&lt;br /&gt;&lt;br /&gt;Below is the proof:&lt;br /&gt;&lt;br /&gt;1. create a dummy table:&lt;br /&gt;&lt;pre&gt;create table muci (col1 number, col2 number);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. from another sqlplus session run the following anonymous block which simulates a mixed workload with: INSERTs, UPDATEs and DELETEs:&lt;br /&gt;&lt;pre&gt;-- simulate a workload with a mix of INSERTs, UPDATEs and DELTEs&lt;br /&gt;-- close the sqlplus window in order to terminate&lt;br /&gt;declare&lt;br /&gt;  l_option pls_integer;&lt;br /&gt;begin&lt;br /&gt;  loop&lt;br /&gt;    l_option := round(dbms_random.value(1, 3));&lt;br /&gt;    if l_option = 1 then&lt;br /&gt;       update muci set col2 = dbms_random.value &lt;br /&gt;          where rowid in (select rowid from muci where rownum &lt;= 1);&lt;br /&gt;    elsif l_option = 2 then&lt;br /&gt;       insert into muci (col1, col2) values (dbms_random.value, dbms_random.value);&lt;br /&gt;    else&lt;br /&gt;       delete from muci where rowid in (select rowid from muci where rownum &lt;= 1);&lt;br /&gt;    end if;&lt;br /&gt;    commit;&lt;br /&gt;  end loop;&lt;br /&gt;end;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. now, run the following statements:&lt;br /&gt;&lt;pre&gt;SQL&gt; set timing on&lt;br /&gt;SQL&gt; alter table muci add (col3 number default 0 not null);&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:01.32&lt;br /&gt;SQL&gt; alter table muci add (col4 number);&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:03.36&lt;br /&gt;SQL&gt; alter table muci add (col5 number as (col1+col2) virtual);&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:00.21&lt;br /&gt;SQL&gt; alter table muci add(col6 number default 0);&lt;br /&gt;alter table muci add(col6 number default 0)&lt;br /&gt;            *&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:00.10&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Very nice, except for the last case, when trying to add a column which allows NULLs and also have a DEFAULT clause. Why did not work? The answer relies, for sure, in the way the ALTER TABLE ADD COLUMN was implemented.&lt;br /&gt;&lt;br /&gt;If the new column allows NULLs and has no DEFAULT clause then, anyway, the value of the new added column is NULL and being the last one it is not stored therefore no "data reorganization" is required within the table blocks. The rows from the "MUCI" table continue to have the following structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_gGEccZZIMqc/R1fs7tqVw8I/AAAAAAAAAAk/QVJOmmlfZkg/s1600-h/null.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_gGEccZZIMqc/R1fs7tqVw8I/AAAAAAAAAAk/QVJOmmlfZkg/s320/null.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5140838010280330178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;However, Oracle knows that there is a third column but its NULL value is not stored within the row.&lt;br /&gt;&lt;br /&gt;When a new column is added having the NOT NULL constraint with a DEFAULT clause, the default value for this new column is stored just once as a table metadata. In a way it's the same like in the table compression feature where for repeated values of a column just one single value is stored, being further referenced when the table is queried. In this case, the rows from the MUCI table will still have the same structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_gGEccZZIMqc/R1ftEtqVw9I/AAAAAAAAAAs/eE3rUX9O-9U/s1600-h/notnull_default.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_gGEccZZIMqc/R1ftEtqVw9I/AAAAAAAAAAs/eE3rUX9O-9U/s320/notnull_default.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5140838164899152850" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The nice part is that Oracle knows that there is a third column which, on the row structure level, is like a "last column with NULLs". But how this could be true? The column was defined with a NOT NULL constraint. Well, if the row representation is like a "last column with NULLs" but the column was defined as NOT NULL then Oracle will simply take the default value which is stored in the metadata of the table and that value will be returned.&lt;br /&gt;&lt;br /&gt;We can easily test that the rows layout remains the same:&lt;br /&gt;&lt;br /&gt;1. create a dummy table:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; create table my_table as select * from all_objects;&lt;br /&gt;&lt;br /&gt;Table created.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. check the corresponding segment size:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select bytes/1024 from user_segments where segment_name='MY_TABLE';&lt;br /&gt;&lt;br /&gt;BYTES/1024&lt;br /&gt;----------&lt;br /&gt;      8192&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. add a new "last column with NULLs":&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter table my_table add (my_column1 char(2000));&lt;br /&gt;&lt;br /&gt;Table altered.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. check the segment size.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select bytes/1024 from user_segments where segment_name='MY_TABLE';&lt;br /&gt;&lt;br /&gt;BYTES/1024&lt;br /&gt;----------&lt;br /&gt;      8192&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Please notice that the size is the same.&lt;br /&gt;&lt;br /&gt;4. add a new NOT NULL column with a default value:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter table my_table add (my_column2 char(2000) default 'xxx' not null);&lt;br /&gt;&lt;br /&gt;Table altered.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. check the segment size:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select bytes/1024 from user_segments where segment_name='MY_TABLE';&lt;br /&gt;&lt;br /&gt;BYTES/1024&lt;br /&gt;----------&lt;br /&gt;      8192&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Please notice that the segment size is unchanged.&lt;br /&gt;&lt;br /&gt;So far so good... but what happens when you try do add a column which allows NULLs and also have a DEFAULT clause? In this case Oracle cannot decide if the value of the new added column should be NULL or the default value. For the previous two cases, it was a black&amp;white approach but now, allowing DEFAULTS and NULLS turns out to be a gray problem and it cannot be handled in the same way. I mean, how could ever Oracle figure out whenever it's about a DEFAULT value or a NULL one? There's no possibility therefore the old approach will be used which actually implies re-organizations within the Oracle table blocks that is allocating the extra storage within each oracle block which belongs to the target table in order to accommodate space for the new column with the specified default value.&lt;br /&gt;&lt;br /&gt;Let's check:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter table my_table add (my_column3 char(10) default 'xxx');&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select bytes/1024 from user_segments where segment_name='MY_TABLE';&lt;br /&gt;&lt;br /&gt;BYTES/1024&lt;br /&gt;----------&lt;br /&gt;      9216&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yes, the segment size has increased. Lovely!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-8914791495318484471?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/8914791495318484471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=8914791495318484471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8914791495318484471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/8914791495318484471'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/12/default-and-not-null-become-friends-in.html' title='DEFAULT and NOT NULL become friends in 11g'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gGEccZZIMqc/R1fs7tqVw8I/AAAAAAAAAAk/QVJOmmlfZkg/s72-c/null.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5281965071539842563</id><published>2007-11-07T11:24:00.000-08:00</published><updated>2010-02-22T02:30:26.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Playing with Flashback Archives</title><content type='html'>Today I've decided to play a little bit with a new Oracle 11g feature called "Flashback Archive". The "Flashback" term is not new at all. I heard about it, for the very first time, in Oracle 9i. At that time, the "flashback" feature it was on its very beginning and allowed just to query a table "AS OF" a previous moment in time, taking into consideration, especially, UNDO segments constraints. As far as I remember there was no possibility to guarantee that the UNDO will really deliver the requested information as there was no GUARANTEE option for the UNDO tablespaces. However, Oracle 10g continued to refine this feature and brought a plenty of improvements: guarantee option for UNDOs, flashback database and flashback table, flashback transactions and others. Now, Oracle 11g adds a new component to the "flashback suite" which is this "flashback archive".&lt;br /&gt;The "flashback archive" is nothing more than a repository which, of course, requires storage provided through one or more tablespaces and it has a well defined retention policy. This archive may be used to keep track of all changes performed on several configured tables. It is important to notice that you can setup more than one flashback archives which, interestingly, may share the same underlying tablespaces.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;SQL&gt; create tablespace test_arch_tbs datafile size 100M;&lt;br /&gt;&lt;br /&gt;Tablespace created&lt;br /&gt;&lt;br /&gt;SQL&gt; create flashback archive test_archive tablespace test_arch_tbs retention 1 month;&lt;br /&gt;&lt;br /&gt;Flashback archive created.&lt;br /&gt;&lt;br /&gt;SQL&gt; create flashback archive test_archive2 tablespace test_arch_tbs retention 1 month;&lt;br /&gt;&lt;br /&gt;Flashback archive created.&lt;/pre&gt;&lt;br /&gt;Please notice that both "test_archive" and "test_archive2" share the same "test_arch_tbs" tablespace. In addition, you can configure a quota for every flashback archive you create, otherwise unlimited is supposed to be the default option.&lt;br /&gt;Another important thing to notice is that you can configure a default flashback archive. You can do this at the archive creation time by specifying the "DEFAULT" option or afterwards using an "ALTER FLASHBACK ARCHIVE... SET DEFAULT". For both operations you need to be logged in as SYSDBA. Of course, you cannot have more than one default flashback archive.&lt;br /&gt;Now, lets create a table with the flashback archive option enabled:&lt;br /&gt;&lt;pre&gt;SQL&gt; create table customers (&lt;br /&gt;  2    cust_id    integer,&lt;br /&gt;  3    cust_name  varchar2(100),&lt;br /&gt;  4    country_id varchar2(2)&lt;br /&gt;  5  ) flashback archive test_archive;&lt;br /&gt;&lt;br /&gt;Table created&lt;/pre&gt;&lt;br /&gt;If the archive name is not explicitly specified then the default archive (if previously setup) will be used. It's time now to insert some records into our customers table. The question which arises is which time-stamp is used when flashback query the table: the one which corresponds to the INSERT itself or the one corresponding to the COMMIT statement. We'll figure out shortly:&lt;br /&gt;&lt;pre&gt;SQL&gt; insert into customers values (1, 'synapstec', 'ro');&lt;br /&gt;&lt;br /&gt;1 row inserted&lt;br /&gt;&lt;br /&gt;SQL&gt; select systimestamp from dual;&lt;br /&gt;&lt;br /&gt;SYSTIMESTAMP&lt;br /&gt;-------------------------------------------------&lt;br /&gt;07-NOV-07 05.50.01.383321 PM +02:00&lt;br /&gt;&lt;br /&gt;SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;SQL&gt; select systimestamp from dual;&lt;br /&gt;&lt;br /&gt;SYSTIMESTAMP&lt;br /&gt;-------------------------------------------------&lt;br /&gt;07-NOV-07 05.50.15.130301 PM +02:00&lt;br /&gt;&lt;br /&gt;SQL&gt; select /* INSERT TIME */ count(1)&lt;br /&gt;  2    from customers&lt;br /&gt;  3    as of timestamp to_timestamp('07-NOV-07 05.50.01.383321 PM',&lt;br /&gt;  4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;  COUNT(1)&lt;br /&gt;----------&lt;br /&gt;         0&lt;br /&gt;&lt;br /&gt;SQL&gt; select /* COMMIT TIME */ count(1)&lt;br /&gt;  2    from customers&lt;br /&gt;  3    as of timestamp to_timestamp('07-NOV-07 05.50.15.130301 PM',&lt;br /&gt;  4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;  COUNT(1)&lt;br /&gt;----------&lt;br /&gt;         1&lt;/pre&gt;&lt;br /&gt;As you can see the COMMIT time is taken into consideration when the table is flashback queried, which is the expected behavior. This means that, for example, several UPDATES onto the same column will not be stored into the archive but the last committed one.&lt;br /&gt;Likewise, you may encounter problems if you need to flashback query at very precise timestamps. Please have a look to the above example:&lt;br /&gt;&lt;pre&gt;6:21:38 PM SQL&gt; update customers set country_id = 'fr';&lt;br /&gt;&lt;br /&gt;1 row updated&lt;br /&gt;&lt;br /&gt;6:21:38 PM SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;6:21:38 PM SQL&gt; select systimestamp from dual;&lt;br /&gt;&lt;br /&gt;SYSTIMESTAMP&lt;br /&gt;-------------------------------------------------&lt;br /&gt;07-NOV-07 06.16.16.506341 PM +02:00&lt;br /&gt;&lt;br /&gt;6:21:38 PM SQL&gt; update customers set country_id = 'en';&lt;br /&gt;&lt;br /&gt;1 row updated&lt;br /&gt;&lt;br /&gt;6:21:38 PM SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;6:21:38 PM SQL&gt; select systimestamp from dual;&lt;br /&gt;&lt;br /&gt;SYSTIMESTAMP&lt;br /&gt;-------------------------------------------------&lt;br /&gt;07-NOV-07 06.16.16.669808 PM +02:00&lt;br /&gt;&lt;br /&gt;6:23:09 PM SQL&gt; select /* FIRST COMMIT */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of timestamp to_timestamp('07-NOV-07 06.16.16.506341 PM',&lt;br /&gt;             4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;ro&lt;br /&gt;&lt;br /&gt;6:23:10 PM SQL&gt;&lt;br /&gt;6:24:18 PM SQL&gt; select /* SECOND COMMIT */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of timestamp to_timestamp('07-NOV-07 06.16.16.669808 PM',&lt;br /&gt;             4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;ro&lt;br /&gt;&lt;br /&gt;6:27:56 PM SQL&gt; select /* AFTER 3 SECONDS */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of timestamp to_timestamp('07-NOV-07 06.16.19.669808 PM',&lt;br /&gt;             4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;ro&lt;br /&gt;&lt;br /&gt;6:29:27 PM SQL&gt; select /* AFTER SOME SECONDS */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of timestamp to_timestamp('07-NOV-07 06.16.21.669808 PM',&lt;br /&gt;             4    'dd-mon-yy hh.mi.ss.ff PM');&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;en&lt;/pre&gt;&lt;br /&gt;As you can see the rough time of each of the above commits doesn't return the correct flashback data. There is a delay between the COMMIT and the relative time to which the flashback archive may be queried. This drawback can be alleviated by using SCNs. So, we can replace timestamps with their corresponding, more precise, SCNs:&lt;br /&gt;&lt;pre&gt;8:58:50 PM SQL&gt; update customers set country_id = 'fr';&lt;br /&gt;&lt;br /&gt;1 row updated&lt;br /&gt;&lt;br /&gt;8:58:50 PM SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;8:58:50 PM SQL&gt; select dbms_flashback.get_system_change_number from dual;&lt;br /&gt;&lt;br /&gt;GET_SYSTEM_CHANGE_NUMBER&lt;br /&gt;------------------------&lt;br /&gt;                  611944&lt;br /&gt;&lt;br /&gt;8:58:51 PM SQL&gt; update customers set country_id = 'en';&lt;br /&gt;&lt;br /&gt;1 row updated&lt;br /&gt;&lt;br /&gt;8:58:51 PM SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;8:58:51 PM SQL&gt; select dbms_flashback.get_system_change_number from dual;&lt;br /&gt;&lt;br /&gt;GET_SYSTEM_CHANGE_NUMBER&lt;br /&gt;------------------------&lt;br /&gt;                  611947&lt;br /&gt;&lt;br /&gt;8:58:51 PM SQL&gt;&lt;br /&gt;9:00:13 PM SQL&gt; select /* FIRST COMMIT */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of scn 611944;&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;fr&lt;br /&gt;&lt;br /&gt;9:00:13 PM SQL&gt; select /* SECOND COMMIT */ country_id&lt;br /&gt;             2    from customers&lt;br /&gt;             3    as of scn 611947;&lt;br /&gt;&lt;br /&gt;COUNTRY_ID&lt;br /&gt;----------&lt;br /&gt;en&lt;/pre&gt;&lt;br /&gt;Nice!&lt;br /&gt;There are however some limitations as far as this feature is concerned. The ugliest ones, at least from my point of view, are:&lt;br /&gt;1. the fact that I cannot modify columns owned by a table which has the flashback archive option enabled along with&lt;br /&gt;2. the fact that we cannot perform partition operations for those tables.&lt;br /&gt;These, put together with a long retention period, become a little bit scary because it is quite likely that, in 5 years for example, the business logic to change leading to modifying the type of a column, for instance. These changes are difficult to predict therefore extreme care should be given for the design of those tables which require flashback archiving. Again, if you have a big transaction table which needs flashback archiving but it is also suitable for partitioning, which feature should we elect? Hard choice, right?&lt;br /&gt;If you ask me, I would, at least, prefer to have the possibility to temporary store the flashback archive records for a particular table into a temporary stage, with something like: "create table temp_stage as select * from {table} ... as of ...", then to disable the flashback archive, to do the maintenance stuff and then to have the possibility to reload the archive from the temporary stage. Well, it's just a thought... of course I have no idea about internal stuff and what this might imply.&lt;br /&gt;&lt;br /&gt;Okey, that's it for the moment. The feature is nice and fits to a lot of projects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5281965071539842563?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5281965071539842563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5281965071539842563' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5281965071539842563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5281965071539842563'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/11/playing-with-flashback-archives.html' title='Playing with Flashback Archives'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-83749462780604948</id><published>2007-11-06T09:32:00.000-08:00</published><updated>2010-02-22T02:30:26.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Preparing Parameters for 12g?</title><content type='html'>&lt;p&gt;Within all Oracle versions there were some features about I heard a lot something like: "well this feature is not quite ready now but it will be within the next Oracle version". This was the case for the "Oracle Resource Manager" in 9i, or for the "Oracle Managed Files" feature. Both of them were made available in 9i but many DBAs, including me, felt that they were not really ready for production. Only starting with Oracle 10g I could figure out that the strength of the OMF was especially in connection with ASM (Automatic Storage Management) and, just beginning with this version, the "Resource Manager" component had been improved quite enough to become appealing for a productive environment.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, I have the same feeling regarding the named and mixed notation for USER DEFINED PL/SQL functions, when they are invoked in a SQL context. For me, it was a common error in Oracle previous releases to write something like:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;select dbms_random.string(opt =&gt; 'L', len =&gt; 10) from dual;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Of course, an error was raised because the SQL context doesn't know how to handle named parameters, but there is also true that when you are using an IDE like PL/SQL Developer or other powerful tools which provide code completion, it is almost impossible not to be tempted by such a feature, being sometimes hard to avoid the above mistake. However, the above code is perfectly valid in Oracle 11g. What really bothers me here is that I cannot use this approach for all functions. For example:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select regexp_count(srcstr =&gt; 'tralala', pattern =&gt; 'a') from dual;&lt;br /&gt;&lt;br /&gt;select regexp_count(srcstr =&gt; 'tralala', pattern =&gt; 'a') from dual&lt;br /&gt;&lt;br /&gt;ORA-00907: missing right parenthesis&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Bleah, ugly! At least it is working for DBMS packages which is a great plus. But, anyway, for me it's a feature which is not "quite ready" but I hope it will be in Oracle 12g... maybe.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-83749462780604948?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/83749462780604948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=83749462780604948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/83749462780604948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/83749462780604948'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/11/preparing-parameters-for-12g.html' title='Preparing Parameters for 12g?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-2791888812555520079</id><published>2007-11-05T10:09:00.000-08:00</published><updated>2010-02-22T02:30:26.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Describe REFCURSORs</title><content type='html'>In Oracle 11g, I really like the interoperability between DBMS_SQL cursors and REFCURSORs. Thanks God, they are finally friends and can "talk" to each other.&lt;br /&gt;I remember that a few months ago I needed a feature through which to be able to describe a weak ref cursor, that is to know how many columns are in the result set along with the corresponding types for every column. Of course, I knew that DBMS_SQL package provides such a feature but it didn't apply to ref cursors therefore, bad luck!&lt;br /&gt;Now, with the new Oracle 11g, it is possible to convert a ref cursor into a DBMS_SQL cursor and vice-versa so, virtually, this opens new gates, right?... including my problem with describing ref cursors.&lt;br /&gt;Lets take a very simple example. Suppose we have a basic procedure which receives a ref cursor as a parameter and it has to know the structure of that cursor. Well, not a big deal in 11g. Just see below how it works:&lt;br /&gt;&lt;pre&gt;SQL&gt; create or replace procedure desc_refcursor(pi_cursor sys_refcursor) is&lt;br /&gt;  2    l_ref sys_refcursor;&lt;br /&gt;  3    l_cursor integer;&lt;br /&gt;  4    l_cols_count integer;&lt;br /&gt;  5    l_desc_tab dbms_sql.desc_tab;&lt;br /&gt;  6 &lt;br /&gt;  7  begin&lt;br /&gt;  8    l_ref := pi_cursor;&lt;br /&gt;  9    l_cursor := dbms_sql.to_cursor_number(l_ref);&lt;br /&gt; 10    dbms_sql.describe_columns(l_cursor, l_cols_count, l_desc_tab);&lt;br /&gt; 11    dbms_output.put_line('number of columns = ' || l_cols_count);&lt;br /&gt; 12    dbms_output.new_line;&lt;br /&gt; 13    dbms_output.put_line('DESCRIBE CURSOR');&lt;br /&gt; 14    dbms_output.put_line('===========================');&lt;br /&gt; 15    for i in 1..l_cols_count&lt;br /&gt; 16    loop&lt;br /&gt; 17      dbms_output.put_line(l_desc_tab(i).col_name);&lt;br /&gt; 18    end loop;&lt;br /&gt; 19    dbms_sql.close_cursor(l_cursor);&lt;br /&gt; 20  exception&lt;br /&gt; 21    when others then&lt;br /&gt; 22      if dbms_sql.is_open(l_cursor) then&lt;br /&gt; 23        dbms_sql.close_cursor(l_cursor);&lt;br /&gt; 24      end if;&lt;br /&gt; 25      raise;&lt;br /&gt; 26  end desc_refcursor;&lt;br /&gt; 27  /&lt;br /&gt;&lt;br /&gt;Procedure created&lt;/pre&gt;&lt;br /&gt;The whole trick consists in using the new DMBS_SQL.TO_CURSOR_NUMBER function (see line 9). Maybe you wonder why this function was not used against the pi_cursor parameter and why that additional assignment at the line 8. That's because the TO_CURSOR_NUMBER function expects an input/output parameter and because pi_cursor is read only the compiler will complain.&lt;br /&gt;&lt;br /&gt;Now, lets test the above procedure:&lt;br /&gt;&lt;pre&gt;SQL&gt; set serveroutput on&lt;br /&gt;SQL&gt; declare&lt;br /&gt;  2    l_cursor sys_refcursor;&lt;br /&gt;  3  begin&lt;br /&gt;  4    open l_cursor for select * from user_tables;&lt;br /&gt;  5    desc_refcursor(l_cursor);&lt;br /&gt;  6  end;&lt;br /&gt;  7  /&lt;br /&gt;&lt;br /&gt;number of columns = 50&lt;br /&gt;&lt;br /&gt;DESCRIBE CURSOR&lt;br /&gt;===========================&lt;br /&gt;TABLE_NAME&lt;br /&gt;TABLESPACE_NAME&lt;br /&gt;CLUSTER_NAME&lt;br /&gt;IOT_NAME&lt;br /&gt;STATUS&lt;br /&gt;PCT_FREE&lt;br /&gt;PCT_USED&lt;br /&gt;INI_TRANS&lt;br /&gt;MAX_TRANS&lt;br /&gt;INITIAL_EXTENT&lt;br /&gt;NEXT_EXTENT&lt;br /&gt;MIN_EXTENTS&lt;br /&gt;MAX_EXTENTS&lt;br /&gt;PCT_INCREASE&lt;br /&gt;FREELISTS&lt;br /&gt;FREELIST_GROUPS&lt;br /&gt;LOGGING&lt;br /&gt;BACKED_UP&lt;br /&gt;NUM_ROWS&lt;br /&gt;BLOCKS&lt;br /&gt;EMPTY_BLOCKS&lt;br /&gt;AVG_SPACE&lt;br /&gt;CHAIN_CNT&lt;br /&gt;AVG_ROW_LEN&lt;br /&gt;AVG_SPACE_FREELIST_BLOCKS&lt;br /&gt;NUM_FREELIST_BLOCKS&lt;br /&gt;DEGREE&lt;br /&gt;INSTANCES&lt;br /&gt;CACHE&lt;br /&gt;TABLE_LOCK&lt;br /&gt;SAMPLE_SIZE&lt;br /&gt;LAST_ANALYZED&lt;br /&gt;PARTITIONED&lt;br /&gt;IOT_TYPE&lt;br /&gt;TEMPORARY&lt;br /&gt;SECONDARY&lt;br /&gt;NESTED&lt;br /&gt;BUFFER_POOL&lt;br /&gt;ROW_MOVEMENT&lt;br /&gt;GLOBAL_STATS&lt;br /&gt;USER_STATS&lt;br /&gt;DURATION&lt;br /&gt;SKIP_CORRUPT&lt;br /&gt;MONITORING&lt;br /&gt;CLUSTER_OWNER&lt;br /&gt;DEPENDENCIES&lt;br /&gt;COMPRESSION&lt;br /&gt;COMPRESS_FOR&lt;br /&gt;DROPPED&lt;br /&gt;READ_ONLY&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed&lt;/pre&gt;&lt;br /&gt;As you can see we were able to obtain the structure of the REF CURSOR and with a minimum effort. However, there are some pseudo-limitations when using this feature and the most important one is that, as soon as you convert the REF CURSOR into the DBMS_SQL cursor representation then you cannot switch back to REF CURSOR without explicit conversion. This means that a scenario in which you'd want to describe the REF CURSOR and after that you would like to continue with your REF CURSOR using FETCH, CLOSE etc. (REF CURSOR specific), those operations will simply not work. You'll have to do the whole further cursor handling using DBMS_SQL package. However, you can re-convert to the REF CURSOR using DBMS_SQL.TO_REFCURSOR. So, the DESCRIBE_REFCURSOR procedure can be modified like this:&lt;br /&gt;&lt;pre&gt;SQL&gt; create or replace procedure desc_refcursor(pio_cursor in out sys_refcursor) is&lt;br /&gt;  2    l_cursor integer;&lt;br /&gt;  3    l_cols_count integer;&lt;br /&gt;  4    l_desc_tab dbms_sql.desc_tab;&lt;br /&gt;  5  begin&lt;br /&gt;  6    l_cursor := dbms_sql.to_cursor_number(pio_cursor);&lt;br /&gt;  7    dbms_sql.describe_columns(l_cursor, l_cols_count, l_desc_tab);&lt;br /&gt;  8    dbms_output.put_line('number of columns = ' || l_cols_count);&lt;br /&gt;  9    dbms_output.new_line;&lt;br /&gt; 10    dbms_output.put_line('DESCRIBE CURSOR');&lt;br /&gt; 11    dbms_output.put_line('===========================');&lt;br /&gt; 12    for i in 1..l_cols_count&lt;br /&gt; 13    loop&lt;br /&gt; 14      dbms_output.put_line(l_desc_tab(i).col_name);&lt;br /&gt; 15    end loop;&lt;br /&gt; 16    pio_cursor := dbms_sql.to_refcursor(l_cursor);&lt;br /&gt; 17  end desc_refcursor;&lt;br /&gt; 18  /&lt;/pre&gt;&lt;br /&gt;Now the invoking anonymous block can continue using ref cursor operations:&lt;br /&gt;&lt;pre&gt;SQL&gt; set serveroutput on&lt;br /&gt;SQL&gt; declare&lt;br /&gt;  2    l_cursor sys_refcursor;&lt;br /&gt;  3  begin&lt;br /&gt;  4    open l_cursor for select * from cat;&lt;br /&gt;  5    desc_refcursor(l_cursor);&lt;br /&gt;  6    close l_cursor; -- REFCURSOR operation&lt;br /&gt;  7  end;&lt;br /&gt;  8  /&lt;br /&gt;&lt;br /&gt;number of columns = 2&lt;br /&gt;&lt;br /&gt;DESCRIBE CURSOR&lt;br /&gt;===========================&lt;br /&gt;TABLE_NAME&lt;br /&gt;TABLE_TYPE&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed&lt;/pre&gt;&lt;br /&gt;Yes, that's it! Nice feature!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-2791888812555520079?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/2791888812555520079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=2791888812555520079' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/2791888812555520079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/2791888812555520079'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/11/describe-refcursors.html' title='Describe REFCURSORs'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1835857563254371900</id><published>2007-11-04T07:28:00.000-08:00</published><updated>2010-02-22T02:30:26.273-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>DBMS_XA and Four Eyes Principle</title><content type='html'>I am simply amazed by the new DBMS_XA package available in Oracle 11g. It offers the possibility to define global transactions and to manage them from within different sessions using a 2PC (Two Phase Commit) approach. One of the great benefit I see now is for those systems which require the implementation of a "four eyes principle", that is somebody puts a transaction into the system but somebody else checks it and finally approves it. Without this approval that transaction is not visible which, from the business point of view, it's not committed.&lt;br /&gt;&lt;br /&gt;Let's walk through a very simple and basic example.&lt;br /&gt;First of all we'll need an Oracle user:&lt;br /&gt;&lt;pre&gt;grant connect, resource, force any transaction to fep identified by xxx;&lt;/pre&gt;&lt;br /&gt;Pay attention to the special right "foce any transaction". It is needed in order to be able to manage transactions created by other users.&lt;br /&gt;Now, lets create a simple table which is supposed to store invoices.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; connect fep/xxx@testdb&lt;br /&gt;Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.6.0&lt;br /&gt;Connected as fep&lt;br /&gt;&lt;br /&gt;SQL&gt;&lt;br /&gt;SQL&gt; create table invoices (&lt;br /&gt;  2   inv_number integer,&lt;br /&gt;  3   inv_text   varchar2(100),&lt;br /&gt;  4   inv_date   date,&lt;br /&gt;  5   inv_value  number(20, 6)&lt;br /&gt;  6  );&lt;br /&gt;&lt;br /&gt;Table created&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, assume that somebody books in a new invoice. This means that a new record has to be added to the "INVOICES" table but, being subject to "four eyes principle" it must not be committed till somebody else will check it. In the DBMS_XA package light this should be done like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; DECLARE&lt;br /&gt;  2    l_rc  PLS_INTEGER;&lt;br /&gt;  3    l_oer PLS_INTEGER;&lt;br /&gt;  4    e_xae EXCEPTION;&lt;br /&gt;  5  BEGIN&lt;br /&gt;  6    l_rc := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMNOFLAGS);&lt;br /&gt;  7 &lt;br /&gt;  8    IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt;  9      RAISE e_xae;&lt;br /&gt; 10    END IF;&lt;br /&gt; 11 &lt;br /&gt; 12    insert into invoices values (1, 'buy a TV', sysdate, 1000);&lt;br /&gt; 13 &lt;br /&gt; 14    l_rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUSPEND);&lt;br /&gt; 15 &lt;br /&gt; 16    IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 17      RAISE e_xae;&lt;br /&gt; 18    END IF;&lt;br /&gt; 19 &lt;br /&gt; 20  EXCEPTION&lt;br /&gt; 21    WHEN OTHERS THEN&lt;br /&gt; 22      l_rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);&lt;br /&gt; 23      l_rc := DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(123));&lt;br /&gt; 24   &lt;br /&gt; 25      IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 26        l_oer := DBMS_XA.XA_GETLASTOER();&lt;br /&gt; 27        raise_application_error(-20001,&lt;br /&gt; 28                                'ORA-' || l_oer ||&lt;br /&gt; 29                                ' error in rolling back a failed transaction');&lt;br /&gt; 30      END IF;&lt;br /&gt; 31   &lt;br /&gt; 32      raise_application_error(-20002,&lt;br /&gt; 33                              'error in transaction processing, transaction rolled back');&lt;br /&gt; 34  END;&lt;br /&gt; 35  /&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;SQL&gt; disconnect&lt;br /&gt;Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production&lt;br /&gt;With the Partitioning and Real Application Testing options&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lets have a look at the above piece of code. At the 6th line a new global transaction is started. The 123 is the global transaction identifier and should be provided by the application and it is required to be unique. If the transaction has been successfully started then returning value must be DBMS_XA.XA_OK,otherwise an error has occurred. Then, the insert into our "INVOICES" table is made and the global transaction is simply suspended. Pay attention that no COMMIT is issued. Of course, it is important to note how the status of each DBMS_XA operation is checked and how the exception handler is written. Finally, the session is ended by effectively disconnecting.&lt;br /&gt;&lt;br /&gt;Now, suppose that the second person must take over the previous transaction, to check it and to approve it. This can be done like shown below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; connect fep/xxx@testdb&lt;br /&gt;Connected.&lt;br /&gt;SQL&gt; select * from invoices;&lt;br /&gt;&lt;br /&gt;no rows selected&lt;br /&gt;&lt;br /&gt;SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete.&lt;br /&gt;&lt;br /&gt;SQL&gt; set serveroutput on&lt;br /&gt;SQL&gt;&lt;br /&gt;SQL&gt; DECLARE&lt;br /&gt;  2    l_rc  PLS_INTEGER;&lt;br /&gt;  3    l_oer PLS_INTEGER;&lt;br /&gt;  4    e_xae EXCEPTION;&lt;br /&gt;  5    l_inv_no  invoices.inv_number%type;&lt;br /&gt;  6    l_inv_dat invoices.inv_date%type;&lt;br /&gt;  7    l_inv_txt invoices.inv_text%type;&lt;br /&gt;  8    l_inv_val invoices.inv_value%type;&lt;br /&gt;  9  BEGIN&lt;br /&gt; 10    -- resume global transaction&lt;br /&gt; 11    l_rc := DBMS_XA.XA_START(DBMS_XA_XID(123), DBMS_XA.TMRESUME);&lt;br /&gt; 12    IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 13      RAISE e_xae;&lt;br /&gt; 14    END IF;&lt;br /&gt; 15 &lt;br /&gt; 16    select *&lt;br /&gt; 17      into l_inv_no, l_inv_txt, l_inv_dat, l_inv_val&lt;br /&gt; 18      from invoices i&lt;br /&gt; 19     where i.inv_number = 1;&lt;br /&gt; 20 &lt;br /&gt; 21    dbms_output.put_line('invoice number = ' || l_inv_no);&lt;br /&gt; 22    dbms_output.put_line('invoice text = ' || l_inv_txt);&lt;br /&gt; 23    dbms_output.put_line('invoice date = ' || l_inv_dat);&lt;br /&gt; 24    dbms_output.put_line('invoice value = ' || l_inv_val);&lt;br /&gt; 25 &lt;br /&gt; 26    -- end global transaction&lt;br /&gt; 27    l_rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);&lt;br /&gt; 28    IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 29      RAISE e_xae;&lt;br /&gt; 30    END IF;&lt;br /&gt; 31 &lt;br /&gt; 32    -- commit global transaction&lt;br /&gt; 33    l_rc := DBMS_XA.XA_COMMIT(DBMS_XA_XID(123), TRUE);&lt;br /&gt; 34    IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 35      RAISE e_xae;&lt;br /&gt; 36    END IF;&lt;br /&gt; 37 &lt;br /&gt; 38  EXCEPTION&lt;br /&gt; 39    WHEN OTHERS THEN&lt;br /&gt; 40      l_rc := DBMS_XA.XA_END(DBMS_XA_XID(123), DBMS_XA.TMSUCCESS);&lt;br /&gt; 41      l_rc := DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(123));&lt;br /&gt; 42   &lt;br /&gt; 43      IF l_rc != DBMS_XA.XA_OK THEN&lt;br /&gt; 44        l_oer := DBMS_XA.XA_GETLASTOER();&lt;br /&gt; 45        raise_application_error(-20001,&lt;br /&gt; 46                                'ORA-' || l_oer ||&lt;br /&gt; 47                                ' error in rolling back a failed transaction');&lt;br /&gt; 48      END IF;&lt;br /&gt; 49   &lt;br /&gt; 50      raise_application_error(-20002,&lt;br /&gt; 51                              'error in transaction processing, transaction rolled back');&lt;br /&gt; 52  END;&lt;br /&gt; 53  /&lt;br /&gt;invoice number = 1&lt;br /&gt;invoice text = buy a TV&lt;br /&gt;invoice date = 04-NOV-07&lt;br /&gt;invoice value = 1000&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;SQL&gt; disconnect&lt;br /&gt;Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production&lt;br /&gt;With the Partitioning and Real Application Testing options&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pay attention to the COMMIT statement just above the anonymous block. That's needed in order the anonymous block to start within a new fresh transaction, otherwise an error may occur.&lt;br /&gt;&lt;br /&gt;So, using DBMS_XA package we were able to resume an uncommitted transaction made from another session, to see the data and to commit the changes. Of course, we can connect once again to see if the data is really committed.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; connect fep/xxx@testdb&lt;br /&gt;Connected.&lt;br /&gt;SQL&gt; set linesize 120&lt;br /&gt;SQL&gt; column inv_text format a10&lt;br /&gt;SQL&gt; select * from invoices;&lt;br /&gt;&lt;br /&gt;INV_NUMBER INV_TEXT   INV_DATE   INV_VALUE&lt;br /&gt;---------- ---------- --------- ----------&lt;br /&gt;         1 buy a TV   04-NOV-07       1000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lovely! The data is there!&lt;br /&gt;&lt;br /&gt;However, there are some additional areas which I still have to investigate in order to validate this model for a MAYBE "four eyes principle" system:&lt;br /&gt;1) where I can see all suspended XA transactions? it seems that DBA_PENDING_TRANSACTIONS, V$GLOBAL_TRANSACTION, DBA_2PC_PENDING or DBA_2PC_NEIGHBORS doesn't show any suspended transaction.&lt;br /&gt;2) are the suspended global transactions persistent across database restarts? Apparently, as far as I could test, it's really not the case.&lt;br /&gt;3) what about the global transaction timeout for a session? If a global transaction should never expire than we have a problem as I don't see any special value for the timeout parameter of the DBMS_XA.XA_SETTIMOUT function (e.g. zero means forever). So the maximum timeout we can set is the upper bound of the PLS_INTEGER type which is 2147483647. That means approximately 24855 days. However, without persistence across database restarts it's, anyway, useless.&lt;br /&gt;4) no idea how this component behaves in a RAC configuration. For example starting a transaction on one instance and resuming it on another one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1835857563254371900?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1835857563254371900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1835857563254371900' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1835857563254371900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1835857563254371900'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/11/dbmsxa-and-four-eyes-principle.html' title='DBMS_XA and Four Eyes Principle'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-1424750284809770794</id><published>2007-08-06T03:13:00.000-07:00</published><updated>2010-02-22T02:50:27.951-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tuning'/><title type='text'>PGA Diagnostics</title><content type='html'>&lt;p&gt;Do not forget a very important Oracle memory buffer which is the PGA (Program Global Area)! Most of us are tempted to look first of all at the SGA, especially at the library cache, whenever users complain that their SQLs run poorly. Of course, the library cache is a proper place to look at for problems, as well as the disk activity, CPU load and so many, many others. However, do NOT forget the PGA, because an inappropriate configuration can lead to a lot of performance issues.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, reading through the "Database Performance Tuning Guide" I have found the section which talk about the tuning of the PGA. I am reading it quite often but it's still difficult to remember all the related fixed views and queries which are in connection with this topic. Therefore I have decided to put all the nice queries into a script which should give me a rough image of the PGA configuration.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Below is the script which I would like to share with all whom might be interested:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-- PGA Report&lt;br /&gt;-- Displays various statistics regarding the PGA usage&lt;br /&gt;&lt;br /&gt;set linesize 140&lt;br /&gt;set pagesize 9999&lt;br /&gt;set heading off&lt;br /&gt;set feedback off&lt;br /&gt;&lt;br /&gt;-- general statistics&lt;br /&gt;select 'SECTION 1: GENERAL STATISTICS FOR THE PGA' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;&lt;br /&gt;set heading on&lt;br /&gt;select name,&lt;br /&gt;       decode(unit, 'bytes', round(value / 1024 / 1024, 2), value) value,&lt;br /&gt;       decode(unit, 'bytes', 'MB', '') unit&lt;br /&gt;  from v$pgastat;&lt;br /&gt;&lt;br /&gt;set heading off&lt;br /&gt;select 'Check the following:' from dual;&lt;br /&gt;select '  - "aggregate PGA auto target" should not be too small in comparison ' &lt;br /&gt;  || 'with the "aggregate PGA target parameter"' from dual;&lt;br /&gt;select '  - "global memory bound" should not be lower than 1M' from dual;&lt;br /&gt;select '  - "over allocation count" should be near 0 or should not increasing in time' from dual;&lt;br /&gt;select '  - the bigger "cache hit percentage", the better' from dual;&lt;br /&gt;select '' from dual;&lt;br /&gt;&lt;br /&gt;set heading on&lt;br /&gt;SELECT name profile, cnt, decode(total, 0, 0, round(cnt*100/total)) percentage&lt;br /&gt;    FROM (SELECT name, value cnt, (sum(value) over ()) total&lt;br /&gt;    FROM V$SYSSTAT &lt;br /&gt;    WHERE name like 'workarea exec%');&lt;br /&gt;set heading off&lt;br /&gt;&lt;br /&gt;-- PGA used by all DB processes&lt;br /&gt;select 'SECTION 2: PGA USED BY CURRENT DB PROCESSES (IN MB), ORDER BY PGA_ALLOC_MEM' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;&lt;br /&gt;break on report;&lt;br /&gt;compute sum label '--&gt; TOTAL' of pga_used_mem on report;&lt;br /&gt;compute sum label '--&gt; TOTAL' of pga_alloc_mem on report;&lt;br /&gt;compute sum label '--&gt; TOTAL' of pga_freeable_mem on report;&lt;br /&gt;compute sum label '--&gt; TOTAL' of pga_max_mem on report;&lt;br /&gt;&lt;br /&gt;SELECT PROGRAM,&lt;br /&gt;       round(PGA_USED_MEM / 1024 / 1024, 2) pga_used_mem,&lt;br /&gt;       round(PGA_ALLOC_MEM / 1024 / 1024, 2) pga_alloc_mem,&lt;br /&gt;       round(PGA_FREEABLE_MEM / 1024 / 1024, 2) pga_freeable_mem,&lt;br /&gt;       round(PGA_MAX_MEM / 1024 / 1024, 2) pga_max_mem&lt;br /&gt;  FROM V$PROCESS&lt;br /&gt; order by pga_alloc_mem desc;&lt;br /&gt;  &lt;br /&gt;set heading off&lt;br /&gt;select 'The columns have the following meaning:' from dual;&lt;br /&gt;select '  - PGA_USED_MEM = PGA memory currently used by the process' from dual;&lt;br /&gt;select '  - PGA_ALLOC_MEM = PGA memory currently allocated by the process (including free ' &lt;br /&gt;  || 'PGA memory not yet released to the operating system by the server process)' from dual;&lt;br /&gt;select '  - PGA_FREEABLE_MEM = Allocated PGA memory which can be freed' from dual;&lt;br /&gt;select '  - PGA_MAX_MEM = Maximum PGA memory ever allocated by the process' from dual;&lt;br /&gt;select '' from dual;&lt;br /&gt;&lt;br /&gt;set feedback off;&lt;br /&gt;select 'SECTION 3: USED PGA MEMORY BY CATHEGORIES (VALUES IN MB ORDER DESC BY ALLOCATED_MB).' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;select category,&lt;br /&gt;       round(sum(allocated) / 1024 / 1024, 2) allocated_mb,&lt;br /&gt;       round(sum(used) / 1024 / 1024, 2) used_mb,&lt;br /&gt;       round(sum(max_allocated) / 1024 / 1024, 2) max_allocated_mb&lt;br /&gt;  from v$process_memory&lt;br /&gt; group by category&lt;br /&gt; order by 2 desc;&lt;br /&gt;&lt;br /&gt;set heading off&lt;br /&gt;select '' from dual;&lt;br /&gt;&lt;br /&gt;-- workareas histogram&lt;br /&gt;select 'SECTION 4: SQL WORKAREAS HISTOGRAM' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;SELECT LOW_OPTIMAL_SIZE/1024 low_kb,&lt;br /&gt;       (HIGH_OPTIMAL_SIZE+1)/1024 high_kb,&lt;br /&gt;       OPTIMAL_EXECUTIONS, ONEPASS_EXECUTIONS, MULTIPASSES_EXECUTIONS&lt;br /&gt;  FROM V$SQL_WORKAREA_HISTOGRAM&lt;br /&gt; WHERE TOTAL_EXECUTIONS != 0;&lt;br /&gt;&lt;br /&gt;set heading off&lt;br /&gt;select '' from dual;&lt;br /&gt;&lt;br /&gt;-- active workareas&lt;br /&gt;select 'SECTION 5: CURRENTLY ACTIVE WORKAREAS' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;set feedback on&lt;br /&gt;SELECT to_number(decode(SID, 65535, NULL, SID)) sid,&lt;br /&gt;       operation_type OPERATION,&lt;br /&gt;       trunc(EXPECTED_SIZE/1024) ESIZE,&lt;br /&gt;       trunc(ACTUAL_MEM_USED/1024) MEM,&lt;br /&gt;       trunc(MAX_MEM_USED/1024) "MAX MEM",&lt;br /&gt;       NUMBER_PASSES PASS,&lt;br /&gt;       trunc(TEMPSEG_SIZE/1024/1024) TSIZE_MB&lt;br /&gt;  FROM V$SQL_WORKAREA_ACTIVE&lt;br /&gt; ORDER BY 1,2;&lt;br /&gt;set heading off&lt;br /&gt;set feedback off&lt;br /&gt;select 'The meaning of the above columns is:' from dual;&lt;br /&gt;select '  - SID = the active session identifier' from dual;&lt;br /&gt;select '  - OPERATION = the type of the operation' from dual;&lt;br /&gt;select '  - ESIZE = the expected size for the sql workarea' from dual;&lt;br /&gt;select '  - MEM = Amount of PGA memory (in KB) currently allocated on behalf of this work area.' from dual;&lt;br /&gt;select '  - MAX MEM = Maximum memory amount (in KB) used by this work area' from dual;&lt;br /&gt;select '  - PASS = Number of passes corresponding to this work area (0 if running in OPTIMAL mode)' from dual;&lt;br /&gt;select '  - TSIZE_MB = Size (in megabytes) of the temporary segment used on behalf of this work area. '&lt;br /&gt;  || 'This column is NULL if this work area has not (yet) spilled to disk.' from dual;&lt;br /&gt;select '' from dual;&lt;br /&gt;&lt;br /&gt;-- top 10 sql with gurmand sql areas&lt;br /&gt;select 'SECTION 6: OP 10 WORK AREAS REQUIRING MOST CACHE MEMORY' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;SELECT *&lt;br /&gt;  FROM (SELECT distinct s.sql_id,&lt;br /&gt;                        substr(s.SQL_TEXT, 1, 50) sql_text,&lt;br /&gt;                        operation_type,&lt;br /&gt;                        estimated_optimal_size,&lt;br /&gt;                        max_tempseg_size&lt;br /&gt;          FROM V$SQL_WORKAREA a, V$SQLSTATS s&lt;br /&gt;         WHERE a.SQL_ID = s.SQL_ID&lt;br /&gt;         ORDER BY estimated_optimal_size)&lt;br /&gt; WHERE ROWNUM &lt;= 10;&lt;br /&gt;&lt;br /&gt;set heading off&lt;br /&gt;select 'SECTION 7: SQLs WITH WORK AREAS THAT HAVE BEEN EXECUTED IN ONE OR EVEN MULTIPLE PASSES' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;set heading on&lt;br /&gt;set feedback on&lt;br /&gt;SELECT sql_text, sum(ONEPASS_EXECUTIONS) onepass_cnt,&lt;br /&gt;       sum(MULTIPASSES_EXECUTIONS) mpass_cnt &lt;br /&gt;FROM V$SQL s, V$SQL_WORKAREA wa &lt;br /&gt;WHERE s.address = wa.address &lt;br /&gt;GROUP BY sql_text &lt;br /&gt;HAVING sum(ONEPASS_EXECUTIONS+MULTIPASSES_EXECUTIONS)&gt;0;&lt;br /&gt;set feedback off&lt;br /&gt;set heading off&lt;br /&gt;&lt;br /&gt;select 'SECTION 8: PGA TARGET ADVCE' from dual;&lt;br /&gt;select '=================================================================='&lt;br /&gt;  || '=========================' from dual;&lt;br /&gt;show parameter pga_aggregate_target;&lt;br /&gt;set heading on&lt;br /&gt;SELECT round(PGA_TARGET_FOR_ESTIMATE/1024/1024) target_mb,&lt;br /&gt;       ESTD_PGA_CACHE_HIT_PERCENTAGE cache_hit_perc,&lt;br /&gt;       ESTD_OVERALLOC_COUNT&lt;br /&gt;  FROM V$PGA_TARGET_ADVICE;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;set heading off&lt;br /&gt;select '' from dual;&lt;br /&gt;pause press any key to exit...&lt;br /&gt;exit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Have fun!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-1424750284809770794?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/1424750284809770794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=1424750284809770794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1424750284809770794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/1424750284809770794'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/08/pga-diagnostics.html' title='PGA Diagnostics'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5777823403240033980</id><published>2007-08-02T02:49:00.000-07:00</published><updated>2010-02-22T02:50:27.952-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tuning'/><title type='text'>Automatic Shared Memory Management</title><content type='html'>&lt;p&gt;Well, it's been a while since the last post... However, I'm back and I am going to dig a little bit on the “Automatic Shared Memory Management” 10g feature.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As you already (probably) know, every Oracle instance has a big shared buffer called SGA (System Global Area). This big memory buffer is further divided in several slices, each of them being used for special kind of memory allocations. Till Oracle 9i, the only possibility to adjust their sizes were to manually set a couple of initialization parameters like: DB_CACHE_SIZE, SHARED_POOL_SIZE, JAVA_POOL_SIZE etc. However, in 10g some buffers from the SGA were endowed with a nice capability to resize themselves according to the current workload and other parameters.&lt;/p&gt;&lt;p&gt;The figure below depicts a regular section through the SGA.&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_gGEccZZIMqc/RrGpL8Xdc_I/AAAAAAAAAAU/54__enJmdBw/s1600-h/asmm.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_gGEccZZIMqc/RrGpL8Xdc_I/AAAAAAAAAAU/54__enJmdBw/s320/asmm.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5094038676180923378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;As you can see the maximum size upon to which the whole SGA may extend is given by the SGA_MAX_SIZE parameter. However, the SGA_TARGET parameter is the one which actually set the amount of memory to be used  by all SGA buffers.&lt;br /&gt;The correlation between the values of the SGA_MAX_SIZE and the SGA_TARGET parameters is important mostly when you query the V$SGA_DYNAMIC_FREE_MEMORY. &lt;br /&gt;Lets have a look onto the following output:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; show parameter sga_target;&lt;br /&gt;&lt;br /&gt;NAME                                 TYPE                             VALUE&lt;br /&gt;------------------------------------ -------------------------------- ------------------------------&lt;br /&gt;sga_target                           big integer                      1504M&lt;br /&gt;&lt;br /&gt;SQL&gt; select current_size/1024/1024 size_M from v$sga_dynamic_free_memory;&lt;br /&gt;&lt;br /&gt;    SIZE_M&lt;br /&gt;----------&lt;br /&gt;       544&lt;br /&gt;&lt;br /&gt;SQL&gt; show parameter sga_max_size&lt;br /&gt;&lt;br /&gt;NAME                                 TYPE                             VALUE&lt;br /&gt;------------------------------------ -------------------------------- ------------------------------&lt;br /&gt;sga_max_size                         big integer                      2G&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;At the very first sight you may think that from the SGA_TARGET which is 1504M, about 544M are free which, of course, is not true because the Oracle server will always try to expand SGA buffers so that the whole SGA_TARGET amount to be allocated. The free memory reported by the V$SGA_DYNAMIC_FREE_MEMORY view is the difference between the SGA_MAX_SIZE and the SGA_TARGET, which should be read as: “I still have 544M free from the whole SGA_MAX_SIZE which I can use for further expansions of the SGA_TARGET”.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A nice view which I also like to query when I want to find out a brief summary of the SGA composition is the V$SGAINFO.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from v$sgainfo;&lt;br /&gt;&lt;br /&gt;NAME                                     BYTES RES&lt;br /&gt;----------------------------------- ---------- ---&lt;br /&gt;Fixed SGA Size                         2074152 No&lt;br /&gt;Redo Buffers                          14700544 No&lt;br /&gt;Buffer Cache Size                    671088640 Yes&lt;br /&gt;Shared Pool Size                     838860800 Yes&lt;br /&gt;Large Pool Size                       16777216 Yes&lt;br /&gt;Java Pool Size                        16777216 Yes&lt;br /&gt;Streams Pool Size                     16777216 Yes&lt;br /&gt;Granule Size                          16777216 No&lt;br /&gt;Maximum SGA Size                    2147483648 No&lt;br /&gt;Startup overhead in Shared Pool      100663296 No&lt;br /&gt;Free SGA Memory Available            570425344&lt;br /&gt;&lt;br /&gt;11 rows selected.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Please notice that I can also look at the size of the so-called “granules”, which are the allocation units for the SGA memory. The size of one granule varies according to the whole size of the SGA, operation system and platform. You can also find the size of the granule by querying the V$SGA_DYNAMIC_COMPONENTS.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select granule_size from v$sga_dynamic_components where rownum &lt;= 1;&lt;br /&gt;&lt;br /&gt;GRANULE_SIZE&lt;br /&gt;------------&lt;br /&gt;    16777216&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Another important thing to remember is that if you set values for the parameters which controls the size of the dynamic buffers into the SGA then, those values will be taken as minimum thresholds which means that Oracle server will try to adjust the size of the buffers when necessary but will never decrease them under the manually set value.&lt;br /&gt;Of course, there is also the possibility to disable the “Automatic Shared Memory Management” feature by simply setting the SGA_TARGET value to zero. Likewise, this feature will also be disabled if the STATISTICS_LEVEL parameter is NONE, but this is not recommended at all as it disables other Oracle features too (ADDM, for example).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Well, that's it... not very new information but just a short review.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5777823403240033980?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5777823403240033980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5777823403240033980' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5777823403240033980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5777823403240033980'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/08/automatic-shared-memory-management.html' title='Automatic Shared Memory Management'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gGEccZZIMqc/RrGpL8Xdc_I/AAAAAAAAAAU/54__enJmdBw/s72-c/asmm.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5332037650630935685</id><published>2007-06-21T06:46:00.000-07:00</published><updated>2010-02-22T02:51:39.669-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grid Manager'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>/etc/oratab or /etc/rc.d/rc3.d/S99gcstartup?</title><content type='html'>&lt;p&gt;&lt;br /&gt;A few days ago I had updated the Oracle Grid Control and its database located on a RedHat AS4 server. Everything worked fine till the server was rebooted and I had the “nice” surprise to see that the repository database was restarted but using the old ORACLE_HOME. At this point it is important to review the steps I had followed as part of the upgrading task: &lt;/p&gt;&lt;br /&gt;1. stop agent&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10ag&lt;br /&gt;emctl stop agent&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2. stop opmn stack&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10gr&lt;br /&gt;$ORACLE_HOME/opmn/bin/opmnctl stopall&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;3. stop listener&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10db&lt;br /&gt;lsnrctl stop&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4. stop database&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sqlplus / as sysdba&lt;br /&gt;shutdown immediate&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;5. backup agent, database, oms homes&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cp -r /opt/oracle/product/10.2.0/agent /opt/oracle/backup/&lt;br /&gt;cp -r /opt/oracle/product/10.2.0/db10g /opt/oracle/backup/&lt;br /&gt;cp -r /opt/oracle/product/10.2.0/oms10g /opt/oracle/backup/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;6. apply patch for 4329444&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;oracle@aut-vie-racman:kits$ unzip p4329444_10104_LINUX.zip&lt;br /&gt;Archive: p4329444_10104_LINUX.zip&lt;br /&gt;creating: 4329444/&lt;br /&gt;creating: 4329444/files/&lt;br /&gt;creating: 4329444/files/lib/&lt;br /&gt;creating: 4329444/files/lib/libserver10.a/&lt;br /&gt;inflating: 4329444/files/lib/libserver10.a/qerix.o&lt;br /&gt;creating: 4329444/etc/&lt;br /&gt;creating: 4329444/etc/config/&lt;br /&gt;inflating: 4329444/etc/config/inventory&lt;br /&gt;inflating: 4329444/etc/config/actions&lt;br /&gt;creating: 4329444/etc/xml/&lt;br /&gt;inflating: 4329444/etc/xml/GenericActions.xml&lt;br /&gt;inflating: 4329444/etc/xml/ShiphomeDirectoryStructure.xml&lt;br /&gt;inflating: 4329444/README.txt&lt;br /&gt;oracle@aut-vie-racman:kits$ cd 4329444/&lt;br /&gt;oracle@aut-vie-racman:4329444$ /opt/oracle/product/10.2.0/db10g/OPatch/opatch apply&lt;br /&gt;Invoking OPatch 10.2.0.1.0&lt;br /&gt;Oracle interim Patch Installer version 10.2.0.1.0&lt;br /&gt;Copyright (c) 2005, Oracle Corporation. All rights reserved..&lt;br /&gt;Oracle Home : /opt/oracle/product/10.2.0/db10g&lt;br /&gt;Central Inventory : /opt/oracle/oraInventory&lt;br /&gt;from : /opt/oracle/product/10.2.0/db10g/oraInst.loc&lt;br /&gt;OPatch version : 10.2.0.1.0&lt;br /&gt;OUI version : 10.2.0.1.0&lt;br /&gt;OUI location : /opt/oracle/product/10.2.0/db10g/oui&lt;br /&gt;Log file location : /opt/oracle/product/10.2.0/db10g/cfgtoollogs/opatch/opatch-&lt;br /&gt;2007_Jun_19_16-16-19-CEST_Tue.log&lt;br /&gt;ApplySession applying interim patch '4329444' to OH&lt;br /&gt;'/opt/oracle/product/10.2.0/db10g'&lt;br /&gt;Invoking fuser to check for active processes.&lt;br /&gt;Invoking fuser on "/opt/oracle/product/10.2.0/db10g/bin/oracle"&lt;br /&gt;OPatch detected non-cluster Oracle Home from the inventory and will patch the local&lt;br /&gt;system only.&lt;br /&gt;Please shutdown Oracle instances running out of this ORACLE_HOME on the local&lt;br /&gt;system.&lt;br /&gt;(Oracle Home = '/opt/oracle/product/10.2.0/db10g')&lt;br /&gt;Is the local system ready for patching?&lt;br /&gt;Do you want to proceed? [y|n]&lt;br /&gt;y&lt;br /&gt;User Responded with: Y&lt;br /&gt;Backing up files and inventory (not for auto-rollback) for the Oracle Home&lt;br /&gt;Backing up files affected by the patch '4329444' for restore. This might take a&lt;br /&gt;while...&lt;br /&gt;Backing up files affected by the patch '4329444' for rollback. This might take a&lt;br /&gt;while...&lt;br /&gt;Patching component oracle.rdbms, 10.1.0.4.0...&lt;br /&gt;Updating archive file "/opt/oracle/product/10.2.0/db10g/lib/libserver10.a" with&lt;br /&gt;"lib/libserver10.a/qerix.o"&lt;br /&gt;Running make for target ioracle&lt;br /&gt;ApplySession adding interim patch '4329444' to inventory&lt;br /&gt;The local system has been patched and can be restarted.&lt;br /&gt;OPatch succeeded.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;7. Start db listener&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;oracle@aut-vie-racman:4329444$ 10db&lt;br /&gt;oracle@aut-vie-racman:4329444$ lsnrctl start&lt;br /&gt;LSNRCTL for Linux: Version 10.1.0.4.0 - Production on 19-JUN-2007 16:18:42&lt;br /&gt;Copyright (c) 1991, 2004, Oracle. All rights reserved.&lt;br /&gt;Starting /opt/oracle/product/10.2.0/db10g/bin/tnslsnr: please wait...&lt;br /&gt;TNSLSNR for Linux: Version 10.1.0.4.0 - Production&lt;br /&gt;System parameter file is /opt/oracle/product/10.2.0/db10g/network/admin/listener.ora&lt;br /&gt;Log messages written to /opt/oracle/product/10.2.0/db10g/network/log/listener.log&lt;br /&gt;Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))&lt;br /&gt;Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=aut-vieracman.&lt;br /&gt;bankgutmann.co.at)(PORT=1521)))&lt;br /&gt;Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC)))&lt;br /&gt;STATUS of the LISTENER&lt;br /&gt;------------------------&lt;br /&gt;Alias LISTENER&lt;br /&gt;Version TNSLSNR for Linux: Version 10.1.0.4.0 - Production&lt;br /&gt;Start Date 19-JUN-2007 16:18:43&lt;br /&gt;Uptime 0 days 0 hr. 0 min. 0 sec&lt;br /&gt;Trace Level off&lt;br /&gt;Security ON: Local OS Authentication&lt;br /&gt;SNMP OFF&lt;br /&gt;Listener Parameter File&lt;br /&gt;/opt/oracle/product/10.2.0/db10g/network/admin/listener.ora&lt;br /&gt;Listener Log File /opt/oracle/product/10.2.0/db10g/network/log/listener.log&lt;br /&gt;Listening Endpoints Summary...&lt;br /&gt;(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))&lt;br /&gt;(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=aut-vieracman.&lt;br /&gt;bankgutmann.co.at)(PORT=1521)))&lt;br /&gt;Services Summary...&lt;br /&gt;Service "PLSExtProc" has 1 instance(s).&lt;br /&gt;Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...&lt;br /&gt;The command completed successfully&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;8. start emrep database&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;oracle@aut-vie-racman:4329444$ sqlplus / as sysdba&lt;br /&gt;SQL*Plus: Release 10.1.0.4.0 - Production on Tue Jun 19 16:20:27 2007&lt;br /&gt;Copyright (c) 1982, 2005, Oracle. All rights reserved.&lt;br /&gt;Connected to an idle instance.&lt;br /&gt;SQL&gt; startup&lt;br /&gt;ORACLE instance started.&lt;br /&gt;Total System Global Area 536870912 bytes&lt;br /&gt;Fixed Size 780056 bytes&lt;br /&gt;Variable Size 275781864 bytes&lt;br /&gt;Database Buffers 260046848 bytes&lt;br /&gt;Redo Buffers 262144 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;Database opened.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;9. Patch OMS.&lt;br /&gt;10. Patch agent&lt;br /&gt;11. Start agent&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10ag&lt;br /&gt;emctl start agent&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;12. Start oms&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10gr&lt;br /&gt;$ORACLE_HOME/opmn/bin/opmnctl startall&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The Grid Control was patched and it worked just fine. The only problem was that the database&lt;br /&gt;remained at 10.1.0.4.0 version. So, I decided to upgrade the repository database too, following the steps below: &lt;/p&gt;&lt;br /&gt;1. stop agent&lt;br /&gt;2. stop oms&lt;br /&gt;3. stop database&lt;br /&gt;4. stop listener&lt;br /&gt;5. install 10.2.0.1 Oracle software into a new home&lt;br /&gt;6. upgrade to 10.2.0.3 the Oracle software&lt;br /&gt;7. upgrade the database using “dbua”&lt;br /&gt;8. start oms&lt;br /&gt;9. start agent&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Everything was normal until today when we had to shutdown the server for maintenance reasons. Unfortunately, on reboot the repository database continued to be started under the previous 10.1.0.4 oracle home and, of course, because of this the OEM couldn't be used. I had a look into /etc/oratab file and the entries were fine. The database was supposed to be started from the new upgraded ORACLE_HOME!!! Furthermore, changing the /etc/oratab file seemed to have no effect. In the end, I found the reason. Under the /etc/rc.d/rc3.d/ directory there is a script called S99gcstartup. This script calls the startup scripts for repository database, OMS and for the agent. It's enough to copy the startup script for the database under the new ORACLE_HOME directory and to change the ORACLE_HOME variable which is declared in that script. After these changes the repository database was/is started up with the correct ORACLE_HOME on every reboot.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-5332037650630935685?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5332037650630935685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5332037650630935685' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5332037650630935685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5332037650630935685'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/06/etcoratab-or-etcrcdrc3ds99gcstartup.html' title='/etc/oratab or /etc/rc.d/rc3.d/S99gcstartup?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-5608152125168957612</id><published>2007-06-08T07:14:00.000-07:00</published><updated>2010-02-22T02:53:47.806-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RAC'/><title type='text'>Losing One Voting Disk</title><content type='html'>Voting disks are used in a RAC configuration for maintaining nodes membership. They are critical pieces in a cluster configuration. Starting with ORACLE 10gR2, it is possible to mirror the OCR and the voting disks. Using the default mirroring template, the minimum number of voting disks necessary for a normal functioning is two.&lt;br /&gt;&lt;br /&gt;&lt;h3 class="western"&gt;Scenario Setup&lt;/h3&gt; &lt;p&gt;In this scenario it is simulated the crash of one voting disk by using the following steps:&lt;/p&gt; &lt;ol&gt;&lt;li&gt;&lt;p&gt;identify votings:&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p style="margin: 0.08in 0.2in 0in 0.5in;" align="justify"&gt; &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;crsctl query css votedisk&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.08in 0.2in 0in 0.5in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;0.     0    /dev/raw/raw1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.08in 0.2in 0in 0.5in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;1.     0    /dev/raw/raw2&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.08in 0.2in 0in 0.5in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;2.     0    /dev/raw/raw3&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="2"&gt;&lt;li&gt;&lt;p&gt;corrupt one of the voting disks (as root):&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;dd if=/dev/zero  /dev/raw/raw3 bs=1M&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;h3 class="western"&gt;Recoverability Steps&lt;/h3&gt; &lt;ol&gt;&lt;li value="1"&gt;&lt;p&gt;check the  “&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;$CRS_HOME/log/[hostname]/alert[hostname].log&lt;/span&gt;&lt;/span&gt;”  file. The following message should be written there which allows us  to determine which voting disk became corrupted:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="left"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;[cssd(9120)]CRS-1604:CSSD  voting file is offline: /opt/oracle/product/10.2.0/crs_1/Voting1.  Details in  /opt/oracle/product/10.2.0/crs_1/log/aut-arz-ractest1/cssd/ocssd.log.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;According to the above listing the Voting1 is the corrupted  disk. Shutdown the CRS stack:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;srvctl stop  database -d fitstest -o immediate&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;srvctl stop asm -n  aut-vie-ractest1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;srvctl stop asm -n  aut-arz-ractest1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;srvctl stop  nodeapps -n aut-vie-ractest1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;srvctl stop  nodeapps -n aut-arz-ractest1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;crs_stat -t&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;On every node as root:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;crsctl stop crs&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Pick a good voting from the remaining ones and copy it over  the corrupted one:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;dd if=/dev/raw/raw4  of=/dev/raw/raw3 bs=1M&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Start CRS (on every node as root):&lt;/p&gt;  &lt;ol&gt;&lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;   &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;crsctl start crs&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/ol&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Check log file  “&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;$CRS_HOME/log/[hostname]/alert[hostname].log&lt;/span&gt;&lt;/span&gt;”.  It should look like shown below:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;[cssd(14463)]CRS-1601:CSSD  Reconfiguration complete. Active nodes are aut-vie-ractest1  aut-arz-ractest1 .&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;2007-05-31  15:19:53.954&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;[crsd(14268)]CRS-1012:The  OCR service started on node aut-vie-ractest1.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;2007-05-31  15:19:53.987&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;[evmd(14228)]CRS-1401:EVMD  started on node aut-vie-ractest1.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-top: 0.08in; margin-bottom: 0in;" align="justify"&gt;  &lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;2007-05-31  15:19:55.861 [crsd(14268)]CRS-1201:&lt;span style="background: rgb(255, 255, 0) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;CRSD  started&lt;/span&gt; on node aut-vie-ractest1.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;After a couple of minutes check the status of the whole CRS  stack:&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;[oracle@aut-vie-ractest1  ~]$ crs_stat -t&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;Name            Type           Target    State     Host&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....SM2.asm  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....T1.lsnr  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.gsd  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.ons  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.vip  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....SM1.asm  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....T1.lsnr  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.gsd  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.ons  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....st1.vip  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....test.db  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....t1.inst  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-family:Courier New,monospace;"&gt;&lt;span style="font-size:85%;"&gt;ora....t2.inst  application    ONLINE    ONLINE    aut-...est1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p style="margin-right: 0.2in; margin-bottom: 0in;" align="justify"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-top: 0.17in; margin-bottom: 0in;" align="justify"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Note:&lt;/b&gt; &lt;i&gt;There's also possible to recover a lost voting disk from an old voting backup and to perform the “dd” command without shutting down the CRS stack.&lt;/i&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/36335310-5608152125168957612?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/5608152125168957612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=5608152125168957612' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5608152125168957612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/5608152125168957612'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/06/losing-one-voting-disk.html' title='Losing One Voting Disk'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-117066591423811724</id><published>2007-02-05T00:51:00.000-08:00</published><updated>2010-02-22T02:52:41.997-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>select * from XML</title><content type='html'>A few days ago, one of our programmers asked me how he can call a procedure from the database passing as a parameter an array of records. Oracle provides this feature on the server side by using, for example, collections of objects, but building such collections on the client side and passing them as parameters is not a trivial task at all (I don’t even know if this is possible with complex types, especially if we are taking into consideration that we use IBATIS to handle database connections, statements and so on, which of course makes this attempt more difficult). However, the first thing which came into my mind was the usage of XML. In the light of this approach, the client side has to build up a XML and pass it to the invoked procedure as a replacement of an array of records. This is not difficult as far as the client csharp code is concerned and, of course, is not a big deal to write a PL/SQL procedure which expects a CLOB parameter, which actually represents the XML content. However, being a SQL guy I must admit that I don’t feel very comfortable to manually parse the XML and to do a lot of DBMS_XML stuff in order to get the data from that XML. Instead, I would rather like to see the XML content as a regular table. Below is how you can do the trick:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  SELECT id, value&lt;br /&gt;   FROM XMLTABLE('/ROWSET/ROW'&lt;br /&gt;      PASSING xmltype('&lt;br /&gt;      &amp;lt;ROWSET&amp;gt;&lt;br /&gt;        &amp;lt;ROW&amp;gt;&lt;br /&gt;          &amp;lt;ID&amp;gt;1&amp;lt;/ID&amp;gt;&lt;br /&gt;          &amp;lt;VALUE&gt;aaa&amp;lt;/VALUE&amp;gt;&lt;br /&gt;        &amp;lt;/ROW&amp;gt;&lt;br /&gt;        &amp;lt;ROW&amp;gt;&lt;br /&gt;          &amp;lt;ID&amp;gt;2&amp;lt;/ID&amp;gt;&lt;br /&gt;          &amp;lt;VALUE&gt;bbb&amp;lt;/VALUE&amp;gt;&lt;br /&gt;        &amp;lt;/ROW&amp;gt;&lt;br /&gt;      &amp;lt;/ROWSET&amp;gt;')&lt;br /&gt;   COLUMNS &lt;br /&gt;           id INTEGER PATH 'ID',&lt;br /&gt;           value VARCHAR2(30) PATH 'VALUE') src;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you want to embed the above piece of code within a procedure with the XML taken as parameter then it’s just of matter of replacing the actual plain XML content with the corresponding CLOB parameter.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  SELECT id, value&lt;br /&gt;   FROM XMLTABLE('/ROWSET/ROW'&lt;br /&gt;      PASSING xmltype(p_clob_xml)&lt;br /&gt;   COLUMNS &lt;br /&gt;           id INTEGER PATH 'ID',&lt;br /&gt;           value VARCHAR2(30) PATH 'VALUE') src;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I have tested this on an Oracle 10.2.0.2 server. It might work on previous releases but I cannot offer any guarantees. Happy XMLing! :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-117066591423811724?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/117066591423811724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=117066591423811724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/117066591423811724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/117066591423811724'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/02/select-from-xml.html' title='select * from XML'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-117015233781435883</id><published>2007-01-30T02:18:00.000-08:00</published><updated>2010-02-22T02:53:03.800-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Get the “tnsnames.ora” from OPENLDAP</title><content type='html'>One thing which really bothers me is when I have to go to every client machine and I must edit the local “tnsnames.ora” file. If you have to deal with just a few clients is not a big issue but as soon as the number of clients exceed five or ten, this approach becomes ugly. The most convenient way would be to have these connection descriptors into a central place and every client to query that repository in order to get the requested descriptor. We have at least two possibilities here: to use “oranames” which is obsolete or to use a LDAP server as the recommended way. Oracle provides its own LDAP server known as OID (Oracle Internet Directory) but it is part of the Advanced Security option and you have to pay for it. In this case, when the whole goal is to use a LDAP server just as a replacement for the local “tnsnames.ora”, it’s not affordable to buy such a wide option for such a tiny functionality. We’ll use instead a free LDAP server which runs seemly on every UNIX platform and it is called OPENLDAP (there are OPENLDAP distributions for Windows as well).&lt;br /&gt;&lt;br /&gt;So, the first thing is to install the required packages. You’ll need: openldap, opeldap-servers and openldap-clients. On my Fedora server I can query the RPM repository as shown below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@ssafe:~# rpm -qa | grep openldap&lt;br /&gt;openldap-2.3.19-4&lt;br /&gt;openldap-devel-2.3.19-4&lt;br /&gt;openldap-clients-2.3.19-4&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see the openldap-servers package is missing therefore we have to install it. We’ll use YUM to do this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@ssafe:~# yum install openldap-servers&lt;br /&gt;Loading "installonlyn" plugin&lt;br /&gt;Setting up Install Process&lt;br /&gt;Setting up repositories&lt;br /&gt;core                                                                 [1/3]&lt;br /&gt;extras                                                               [2/3]&lt;br /&gt;updates                                                              [3/3]&lt;br /&gt;Reading repository metadata in from local files&lt;br /&gt;Parsing package install arguments&lt;br /&gt;Resolving Dependencies&lt;br /&gt;--&gt; Populating transaction set with selected packages. Please wait.&lt;br /&gt;---&gt; Package openldap-servers.i386 0:2.3.19-4 set to be updated&lt;br /&gt;--&gt; Running transaction check&lt;br /&gt;&lt;br /&gt;Dependencies Resolved&lt;br /&gt;&lt;br /&gt;=============================================================================&lt;br /&gt;Package                 Arch       Version          Repository        Size&lt;br /&gt;=============================================================================&lt;br /&gt;Installing:&lt;br /&gt;openldap-servers        i386       2.3.19-4         core              2.2 M&lt;br /&gt;&lt;br /&gt;Transaction Summary&lt;br /&gt;=============================================================================&lt;br /&gt;Install      1 Package(s)&lt;br /&gt;Update       0 Package(s)&lt;br /&gt;Remove       0 Package(s)&lt;br /&gt;Total download size: 2.2 M&lt;br /&gt;Is this ok [y/N]: y&lt;br /&gt;Downloading Packages:&lt;br /&gt;Running Transaction Test&lt;br /&gt;Finished Transaction Test&lt;br /&gt;Transaction Test Succeeded&lt;br /&gt;Running Transaction&lt;br /&gt;Installing: openldap-servers             ######################### [1/1]&lt;br /&gt;&lt;br /&gt;Installed: openldap-servers.i386 0:2.3.19-4&lt;br /&gt;Complete!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, we have a nice LDAP server installed on our server. The next step is to configure it. Oracle will need some special LDAP schemas which must be loaded into our server. These schema files are: oidbase.schema, oidrdbms.schema and oidnet.schema. Save them into a new created directory called, let’s say, “oracle-ldap”. Below is the content of the needed files:&lt;br /&gt;1. oidbase.schema:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.1 NAME 'orclVersion' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.2 NAME 'orclOracleHome' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.3 NAME 'orclSystemName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.4 NAME 'orclServiceType' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.5 NAME 'orclSid' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.7.1.6 NAME 'orclProductVersion' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectClass ( 2.16.840.1.113894.7.2.2 NAME 'orclContainer'   SUP 'top'  STRUCTURAL MUST ( cn )   )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectClass ( 2.16.840.1.113894.7.2.3 NAME 'orclContext'   SUP 'top'  STRUCTURAL MUST ( cn )   )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectClass ( 2.16.840.1.113894.7.2.6 NAME 'orclSchemaVersion'   SUP 'top'  STRUCTURAL MUST ( cn  $ orclProductVersion )   )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.3.1.12 NAME 'orclNetDescName' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;attributetype ( 2.16.840.1.113894.3.1.13 NAME 'orclNetDescString' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectClass ( 2.16.840.1.113894.7.2.1001 NAME 'orclService'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclServiceType $ orclOracleHome $ orclSystemName $ orclSid $ orclNetDescName $ orclNetDescString $ orclVersion $ Description ) )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;2. oidrdbms.schema file:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.1 NAME 'orclDBtrustedUser' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.2 NAME 'orclDBServerMember' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.3 NAME 'orclDBEntUser' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.4 NAME 'orclDBEntRoleAssigned' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.5 NAME 'orclDBServerRole' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.6 NAME 'orclDBTrustedDomain' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.7 NAME 'orclDBRoleOccupant' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.8 NAME 'orclDBDistinguishedName' EQUALITY distinguishedNameMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.9 NAME 'orclDBNativeUser' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.2.1.10 NAME 'orclDBGlobalName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.2.2.1 NAME 'orclDBServer' SUP 'orclService' STRUCTURAL MAY ( userCertificate $ orclDBtrustedUser $ orclDBGlobalName ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.2.2.2 NAME 'orclDBEnterpriseDomain' SUP top STRUCTURAL MUST cn MAY ( orclDBServerMember $ orclDBEntUser $ orclDBTrustedDomain ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.2.2.3 NAME 'orclDBEnterpriseRole' SUP top STRUCTURAL MUST cn MAY ( orclDBServerRole $ orclDBEntRoleAssigned $ description $ seeAlso $ o $ ou $ orclDBRoleOccupant ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.2.2.4 NAME 'orclDBEntryLevelMapping' SUP top STRUCTURAL  MUST cn MAY ( orclDBDistinguishedName $ orclDBNativeUser ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.2.2.5 NAME 'orclDBSubtreeLevelMapping' SUP top STRUCTURAL MUST cn  MAY ( orclDBDistinguishedName $ orclDBNativeUser ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3. oidnet.schema file:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.1 NAME 'orclNetSourceRoute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.5' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.2 NAME 'orclNetLoadBalance' SYNTAX '1.3.6.1.4.1.1466.115.121.1.5' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.3 NAME 'orclNetFailover' SYNTAX '1.3.6.1.4.1.1466.115.121.1.5' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.4 NAME 'orclNetSdu' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.5 NAME 'orclNetServer' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.6 NAME 'orclNetServiceName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.7 NAME 'orclNetInstanceName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.8 NAME 'orclNetHandlerName' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.9 NAME 'orclNetParamList' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.10 NAME 'orclNetAuthenticationType' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.11 NAME 'orclNetAuthParams' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.14 NAME 'orclNetAddressString' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.15 NAME 'orclNetProtocol' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.16 NAME 'orclNetShared' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.17 NAME 'orclNetAddrList' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15'  )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.18 NAME 'orclNetProtocolStack' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.19 NAME 'orclNetDescList' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.20 NAME 'orclNetConnParamList' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;attributetype ( 2.16.840.1.113894.3.1.21 NAME 'orclNetAuthenticationService' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.3.2.5 NAME 'orclNetService'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclNetDescName $ orclNetDescString $ orclVersion $ Description ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.3.2.4 NAME 'orclNetDescriptionList'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclNetDescList $  orclNetSourceRoute $ orclNetLoadBalance $ orclNetFailover $ orclNetShared $ orclVersion $ Description ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.3.2.3 NAME 'orclNetDescription'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclNetAddrList $ orclNetProtocolStack $ orclNetSdu $ orclSid $ orclNetServer $ orclNetServiceName $ orclNetInstanceName $ orclNetHandlerName $ orclOracleHome $ orclNetAuthenticationType $ orclNetAuthenticationService $ orclNetAuthParams $ orclNetParamList $ orclNetConnParamList $ orclNetSourceRoute $ orclNetLoadBalance $ orclNetFailover $ orclNetShared $ orclVersion $ Description ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.3.2.2 NAME 'orclNetAddressList'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclNetAddrList $ orclNetSourceRoute $ orclNetLoadBalance $ orclNetFailover $ orclNetShared $ orclVersion $ Description ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51);font-family:courier new;font-size:85%;"  &gt;objectClass ( 2.16.840.1.113894.3.2.1 NAME 'orclNetAddress'   SUP 'top'  STRUCTURAL MUST ( cn )  MAY (  orclNetAddressString $ orclNetProtocol $ orclNetShared $ orclVersion $ Description ) )&lt;/span&gt;&lt;span style="color: rgb(51, 51, 51);font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then, edit the slapd.conf file. On my installation this file can be found under /etc/openldap directory. Before changing something it is wise to make a copy of the original slapd.conf file.&lt;br /&gt;&lt;pre&gt;cp /etc/openldap/slapd.conf /etc/openldap/slapd.conf.bak&lt;/pre&gt;&lt;br /&gt;Now, open the /etc/openldap/slapd.conf file and change it as following (see the bolded lines):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# See slapd.conf(5) for details on configuration options.&lt;br /&gt;# This file should NOT be world readable.&lt;br /&gt;#&lt;br /&gt;include     /etc/openldap/schema/core.schema&lt;br /&gt;include     /etc/openldap/schema/cosine.schema&lt;br /&gt;include     /etc/openldap/schema/inetorgperson.schema&lt;br /&gt;include     /etc/openldap/schema/nis.schema&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;include         /oracle-ldap/oidbase.schema&lt;br /&gt;include         /oracle-ldap/oidrdbms.schema&lt;br /&gt;include         /oracle-ldap/oidnet.schema&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Allow LDAPv2 client connections.  This is NOT the default.&lt;br /&gt;allow bind_v2&lt;br /&gt;&lt;br /&gt;# Do not enable referrals until AFTER you have a working directory&lt;br /&gt;# service AND an understanding of referrals.&lt;br /&gt;#referral   ldap://root.openldap.org&lt;br /&gt;&lt;br /&gt;pidfile     /var/run/openldap/slapd.pid&lt;br /&gt;argsfile    /var/run/openldap/slapd.args&lt;br /&gt;&lt;br /&gt;# Load dynamic backend modules:&lt;br /&gt;# modulepath    /usr/lib/openldap&lt;br /&gt;# moduleload    back_bdb.la&lt;br /&gt;# moduleload    back_ldap.la&lt;br /&gt;# moduleload    back_ldbm.la&lt;br /&gt;# moduleload    back_passwd.la&lt;br /&gt;# moduleload    back_shell.la&lt;br /&gt;&lt;br /&gt;# The next three lines allow use of TLS for encrypting connections using a&lt;br /&gt;# dummy test certificate which you can generate by changing to&lt;br /&gt;# /etc/pki/tls/certs, running "make slapd.pem", and fixing permissions on&lt;br /&gt;# slapd.pem so that the ldap user or group can read it.  Your client software&lt;br /&gt;# may balk at self-signed certificates, however.&lt;br /&gt;# TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt&lt;br /&gt;# TLSCertificateFile /etc/pki/tls/certs/slapd.pem&lt;br /&gt;# TLSCertificateKeyFile /etc/pki/tls/certs/slapd.pem&lt;br /&gt;&lt;br /&gt;# Sample security restrictions&lt;br /&gt;#   Require integrity protection (prevent hijacking)&lt;br /&gt;#   Require 112-bit (3DES or better) encryption for updates&lt;br /&gt;#   Require 63-bit encryption for simple bind&lt;br /&gt;# security ssf=1 update_ssf=112 simple_bind=64&lt;br /&gt;&lt;br /&gt;# Sample access control policy:&lt;br /&gt;#   Root DSE: allow anyone to read it&lt;br /&gt;#   Subschema (sub)entry DSE: allow anyone to read it&lt;br /&gt;#   Other DSEs:&lt;br /&gt;#       Allow self write access&lt;br /&gt;#       Allow authenticated users read access&lt;br /&gt;#       Allow anonymous users to authenticate&lt;br /&gt;#   Directives needed to implement policy:&lt;br /&gt;# access to dn.base="" by * read&lt;br /&gt;# access to dn.base="cn=Subschema" by * read&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt; access to *&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#   by self write&lt;br /&gt;#   by users read&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;    by anonymous auth&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# if no access controls are present, the default policy&lt;br /&gt;# allows anyone and everyone to read anything but restricts&lt;br /&gt;# updates to rootdn.  (e.g., "access to * by * read")&lt;br /&gt;#&lt;br /&gt;# rootdn can always read and write EVERYTHING!&lt;br /&gt;&lt;br /&gt;#######################################################################&lt;br /&gt;# ldbm and/or bdb database definitions&lt;br /&gt;#######################################################################&lt;br /&gt;&lt;br /&gt;database    bdb&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;suffix      "dc=itfits,dc=biz"&lt;br /&gt;rootdn      "cn=Manager,dc=itfits,dc=biz"&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Cleartext passwords, especially for the rootdn, should&lt;br /&gt;# be avoided.  See slappasswd(8) and slapd.conf(5) for details.&lt;br /&gt;# Use of strong authentication encouraged.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;rootpw      secret&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# rootpw        {crypt}ijFYNcSNctBYg&lt;br /&gt;&lt;br /&gt;# The database directory MUST exist prior to running slapd AND&lt;br /&gt;# should only be accessible by the slapd and slap tools.&lt;br /&gt;# Mode 700 recommended.&lt;br /&gt;directory   /var/lib/ldap&lt;br /&gt;&lt;br /&gt;# Indices to maintain for this database&lt;br /&gt;index objectClass                       eq,pres&lt;br /&gt;index ou,cn,mail,surname,givenname      eq,pres,sub&lt;br /&gt;index uidNumber,gidNumber,loginShell    eq,pres&lt;br /&gt;index uid,memberUid                     eq,pres,sub&lt;br /&gt;index nisMapName,nisMapEntry            eq,pres,sub&lt;br /&gt;&lt;br /&gt;# Replicas of this database&lt;br /&gt;#replogfile /var/lib/ldap/openldap-master-replog&lt;br /&gt;#replica host=ldap-1.example.com:389 starttls=critical&lt;br /&gt;#     bindmethod=sasl saslmech=GSSAPI&lt;br /&gt;#     authcId=host/ldap-master.example.com@EXAMPLE.COM&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The “suffix” and “rootdn” should be changed according to your specific domain. It’s time to start the “slapd” daemon by simply typing slapd &lt;enter&gt;. Now our LDAP server is ready for incoming requests but we’ll have to create the initial structure of the LDAP tree. In order to do this we’ll need some so called “ldif” files which will be used to specify LDAP entries along with their attributes.&lt;br /&gt;&lt;br /&gt;Let’s create the following ldif files:&lt;br /&gt;1. base.ldif, with the following content:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;dn: dc=itfits,dc=biz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectclass: dcObject&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectclass: organization&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;o: ITFITS Network&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;dc: itfits&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;2. manager.ldif with the following content:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;dn: cn=Manager,dc=itfits,dc=biz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectClass: organizationalRole&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cn: Manager&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;3. OracleContext.ldif with the following content:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;dn: cn=OracleContext,dc=itfits,dc=biz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectclass: orclContext&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cn: OracleContext&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;4. pdmdb.ldif with the following content:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;dn: cn=pdmdb,cn=OracleContext,dc=itfits,dc=biz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectclass: top&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;objectclass: orclNetService&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cn: pdmdb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;orclNetDescString: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ops)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=PDMDB)))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;After we have created the above files we must use them to alter the LDAP tree structure:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@ssafe:oracle-ldap# ldapadd -x -D "cn=Manager,dc=itfits,dc=biz" -w secret -f base.ldif&lt;br /&gt;adding new entry "dc=itfits,dc=biz"&lt;br /&gt;&lt;br /&gt;root@ssafe:oracle-ldap# ldapadd -x -D "cn=Manager,dc=itfits,dc=biz" -w secret -f manager.ldif&lt;br /&gt;adding new entry "cn=Manager,dc=itfits,dc=biz"&lt;br /&gt;&lt;br /&gt;root@ssafe:oracle-ldap# ldapadd -x -D "cn=Manager,dc=itfits,dc=biz" -w secret -f OracleContext.ldif&lt;br /&gt;adding new entry "cn=OracleContext,dc=itfits,dc=biz"&lt;br /&gt;&lt;br /&gt;root@ssafe:oracle-ldap# ldapadd -x -D "cn=Manager,dc=itfits,dc=biz" -w secret -f pdmdb.ldif&lt;br /&gt;adding new entry "cn=pdmdb,cn=OracleContext,dc=itfits,dc=biz"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Oookey, the LDAP server is ready to serve our oracle clients. However, our oracle clients might not be prepared for talking with a LDAP server therefore we should spend some time to configure them. It is always recommended to use the provided graphical tools therefore we’ll use “netca”. Choose “Naming Method configuration” and add “Directory naming” from the available methods as a “Selected Naming” method. The “Directory naming” should be the only selected method or at least should be the first one.&lt;br /&gt;Perfect! Now, we must create an “$ORACLE_HOME/network/admin/ldap.ora” file, with the following content:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DIRECTORY_SERVERS= (ssafe:389:636)&lt;br /&gt;DEFAULT_ADMIN_CONTEXT = "dc=itfits,dc=biz"&lt;br /&gt;DIRECTORY_SERVER_TYPE = OID&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;“ssafe” is the DNS name of the machine where the LDAP server was installed.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Now, let’s test the configuration:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;C:\Documents and Settings\alec&gt;tnsping pdmdb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;TNS Ping Utility for 32-bit Windows: Version 10.2.0.1.0 - Production on 30-JAN-2007 12:07:27&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Copyright (c) 1997, 2005, Oracle.  All rights reserved.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Used parameter files:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;C:\oracle\product\10.2.0\client_1\network\admin\sqlnet.ora&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Used LDAP adapter to resolve the alias&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Attempting to contact (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ops)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=PDMDB)))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;OK (0 msec)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Lovely! From now on our oracle clients will get the network descriptors from the LDAP repository. No more “tnsnames.ora” is required.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-117015233781435883?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/117015233781435883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=117015233781435883' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/117015233781435883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/117015233781435883'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/get-tnsnamesora-from-openldap.html' title='Get the “tnsnames.ora” from OPENLDAP'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116945310087587215</id><published>2007-01-22T00:02:00.000-08:00</published><updated>2010-02-22T02:54:13.629-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grid Manager'/><title type='text'>Recreating the Database Control Repository</title><content type='html'>I don’t know why, but after I upgraded my database to 10.2.0.2, the DB Console started to behave quite unusual. For example, I was not able to submit backup jobs because it was complaining that the host privileges were not set up. Trying to manually set those privileges within the “Preferences/Host Preferred Credentials” was unsuccessful because the displayed page was simply empty. So, I decided to recreate the repository and this fixed my problem. Below are the steps I followed:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;drop the repository:&lt;/li&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; emca -deconfig dbcontrol db -repos drop&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;li&gt;recreate the repository using dbca.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116945310087587215?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116945310087587215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116945310087587215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116945310087587215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116945310087587215'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/recreating-database-control-repository.html' title='Recreating the Database Control Repository'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116859370594238458</id><published>2007-01-12T01:21:00.000-08:00</published><updated>2007-01-12T01:33:18.133-08:00</updated><title type='text'>Writing PLSQL Developer Plugins in CSHARP</title><content type='html'>Few months ago I decided to write a plugin for the well known PLSQL Developer environment, using csharp. Form the very beginning, I must admit that I haven’t a large experience with this programming language as “deep inside” I’m an Oracle guy, but sometimes is nice to play around with it, especially if you have former knowledge with Java. At that time my plans were to develop a Microsoft Source Safe plugin using InteropSSafeTypeLib. The main problem was the fact that my plugin was not seen by the PLSQL Developer IDE, despite that from the outside it looked like a regular DLL (it turned out that I was wrong). So, below is the class from which I started my research:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;namespace test_plugin&lt;br /&gt;{&lt;br /&gt;    public class VSSPlugin&lt;br /&gt;    {&lt;br /&gt;        public static string IdentifyPlugIn(int ID)&lt;br /&gt;        {&lt;br /&gt;            string result = "Hello from c#";&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This compiles nicely into a self-packaged DLL but, as I previously said, it is not suitable to be used as a PL/SQL Developer plugin. The problem actually resides in the way the DLL is built-up, its structure being designed to handle managed code which cannot be directly handled by an external application written in C or Delphi. The workaround is to decompile the DLL into its pure code called MSIL to make some changes and to recompile again providing the modified MSIL code for our DLL.&lt;br /&gt;&lt;br /&gt;So, to decompile you have to use the following command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ildasm.exe /OUT:test_plugin.il test_plugin.dll&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will create in the current directory two files: “test_plugin.il” and “test_plugin.res”. The file which is interesting for us is “test_plugin.il” and it contains the MSIL code. You’ll obtain something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;//  Microsoft (R) .NET Framework IL Disassembler.  Version 2.0.50727.42&lt;br /&gt;//  Copyright (c) Microsoft Corporation.  All rights reserved.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Metadata version: v2.0.50727&lt;br /&gt;.assembly extern mscorlib&lt;br /&gt;{&lt;br /&gt;  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) &lt;br /&gt;  .ver 2:0:0:0&lt;br /&gt;}&lt;br /&gt;.assembly test_plugin&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;...bla bla bla...&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;.module test_plugin.dll&lt;br /&gt;// MVID: {CA976282-5C4E-46F5-A770-39DF57596ECE}&lt;br /&gt;.imagebase 0x00400000&lt;br /&gt;.file alignment 0x00001000&lt;br /&gt;.stackreserve 0x00100000&lt;br /&gt;.subsystem 0x0003       // WINDOWS_CUI&lt;br /&gt;.corflags 0x00000001    //  ILONLY&lt;br /&gt;// Image base: 0x00EB0000&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// =============== CLASS MEMBERS DECLARATION ===================&lt;br /&gt;&lt;br /&gt;.class public auto ansi beforefieldinit test_plugin.VSSPlugin&lt;br /&gt;       extends [mscorlib]System.Object&lt;br /&gt;{&lt;br /&gt;  .method public hidebysig static string &lt;br /&gt;          IdentifyPlugIn(int32 ID) cil managed&lt;br /&gt;  {&lt;br /&gt;    // Code size       8 (0x8)&lt;br /&gt;    .maxstack  1&lt;br /&gt;    .locals init ([0] string result)&lt;br /&gt;    IL_0000:  ldstr      "Hello from c#"&lt;br /&gt;    IL_0005:  stloc.0&lt;br /&gt;    IL_0006:  ldloc.0&lt;br /&gt;    IL_0007:  ret&lt;br /&gt;  } // end of method VSSPlugin::IdentifyPlugIn&lt;br /&gt;&lt;br /&gt;  .method public hidebysig specialname rtspecialname &lt;br /&gt;          instance void  .ctor() cil managed&lt;br /&gt;  {&lt;br /&gt;    // Code size       7 (0x7)&lt;br /&gt;    .maxstack  8&lt;br /&gt;    IL_0000:  ldarg.0&lt;br /&gt;    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()&lt;br /&gt;    IL_0006:  ret&lt;br /&gt;  } // end of method VSSPlugin::.ctor&lt;br /&gt;&lt;br /&gt;} // end of class test_plugin.VSSPlugin&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// =============================================================&lt;br /&gt;&lt;br /&gt;// *********** DISASSEMBLY COMPLETE ***********************&lt;br /&gt;// WARNING: Created Win32 resource file test_plugin.res&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now it’s time to make our changes. Bellow is the IL file, modified to support the export of our “IdentifyPlugIn” function. The changed and the added lines are bolded.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;//  Microsoft (R) .NET Framework IL Disassembler.  Version 2.0.50727.42&lt;br /&gt;//  Copyright (c) Microsoft Corporation.  All rights reserved.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Metadata version: v2.0.50727&lt;br /&gt;.assembly extern mscorlib&lt;br /&gt;{&lt;br /&gt;  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )&lt;br /&gt;  .ver 2:0:0:0&lt;br /&gt;}&lt;br /&gt;.assembly test_plugin&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;...bla bla bla...&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;.module test_plugin.dll&lt;br /&gt;// MVID: {CA976282-5C4E-46F5-A770-39DF57596ECE}&lt;br /&gt;.imagebase 0x00400000&lt;br /&gt;.file alignment 0x00001000&lt;br /&gt;.stackreserve 0x00100000&lt;br /&gt;.subsystem 0x0003       // WINDOWS_CUI&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p style="font-family=Courier"&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;.corflags 0x00000002&lt;br /&gt;.vtfixup [1] int32 fromunmanaged at VT_01&lt;br /&gt;.data VT_01 = int32(0)&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Image base: 0x00EB0000&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// =============== CLASS MEMBERS DECLARATION ===================&lt;br /&gt;&lt;br /&gt;.class public auto ansi beforefieldinit test_plugin.VSSPlugin&lt;br /&gt;       extends [mscorlib]System.Object&lt;br /&gt;{&lt;br /&gt;  .method public hidebysig static string &lt;br /&gt;          IdentifyPlugIn(int32 ID) cil managed&lt;br /&gt;  {&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p style="font-family: Courier"&gt;&lt;br /&gt;    &lt;b&gt;.vtentry 1 : 1&lt;br /&gt;    .export [1] as IdentifyPlugIn&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // Code size       8 (0x8)&lt;br /&gt;    .maxstack  1&lt;br /&gt;    .locals init ([0] string result)&lt;br /&gt;    IL_0000:  ldstr      "Hello from c#"&lt;br /&gt;    IL_0005:  stloc.0&lt;br /&gt;    IL_0006:  ldloc.0&lt;br /&gt;    IL_0007:  ret&lt;br /&gt;  } // end of method VSSPlugin::IdentifyPlugIn&lt;br /&gt;&lt;br /&gt;  .method public hidebysig specialname rtspecialname &lt;br /&gt;          instance void  .ctor() cil managed&lt;br /&gt;  {&lt;br /&gt;    // Code size       7 (0x7)&lt;br /&gt;    .maxstack  8&lt;br /&gt;    IL_0000:  ldarg.0&lt;br /&gt;    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()&lt;br /&gt;    IL_0006:  ret&lt;br /&gt;  } // end of method VSSPlugin::.ctor&lt;br /&gt;&lt;br /&gt;} // end of class test_plugin.VSSPlugin&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// =============================================================&lt;br /&gt;&lt;br /&gt;// *********** DISASSEMBLY COMPLETE ***********************&lt;br /&gt;// WARNING: Created Win32 resource file test_plugin.res&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It’s time to recompile the IL code into the target DLL file. You can use the following command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ilasm /OUT:test_plugin.dll test_plugin.il /DLL&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Copy the generated test_plugin.dll file under the PLSQL Developer “PlugIns” directory and start the IDE environment. Take a look into Tools/Configure Plugins! Bingo!!! You’ll see there “Hello from c#” which is the name of our first plugin written in csharp.&lt;br /&gt;&lt;br /&gt;This approach should be taken as proof of concept that, basically, you can write a PLSQL Developer plugin using csharp but I cannot tell you for sure what problems you might expect or if you will be allowed to use forms or other advanced csharp programming techniques.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116859370594238458?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116859370594238458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116859370594238458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116859370594238458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116859370594238458'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/writing-plsql-developer-plugins-in.html' title='Writing PLSQL Developer Plugins in CSHARP'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116853569618415279</id><published>2007-01-11T09:13:00.000-08:00</published><updated>2010-02-22T02:55:22.758-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>The Infamous Update on a Primary Key</title><content type='html'>Today I was put in front of a new challenging situation. We have a reporting application which is fed from another system using materialized views. In short, on the remote source system, for several “interesting” tables materialized view logs were defined with the “WITH PRIMARY KEY” option. These logs are used to support a fast refresh mechanism for the corresponding materialized views created on the reporting system. Each materialized view was created on a pre-built table. Of course, there’s a refresh job which takes place on regular intervals in order to keep in sync both systems. As soon as a new record arrives or an existing one is updated this is marked accordingly into a flag column within the pre-built table through a trigger. Likewise, the operation type (INSERT or UPDATE) is written as well into the pre-built table. Now, the big problem is the fact that some modules from the source system are updating (yes, very ugly!!!) values from columns which are part of the primary key. From the materialized view log perspective this is converted into a delete and an insert therefore as soon as the DBMS_MVIEW.REFRESH procedure is called on the reporting system the BEFORE/AFTER DELETE and BEFORE/AFTER INSERT triggers are executed instead of a BEFORE/AFTER UPDATE trigger. Now, one of the MV interface requirement was to convert this sequence of one DELETE and one INSERT so that on the reporting system that initial UPDATE on the primary key to look like a regular update. Even at the very beginning this might appear as a trivial task in fact is quite cumbersome. The solution we found so far relies on using ROWIDs for our pre-built tables. &lt;br /&gt;&lt;br /&gt;Okey, because the so called “too much sound but little sense” is not going to be the subject of this post, let’s delve into a concrete test scenario.&lt;br /&gt;&lt;br /&gt;First of all, create the source table:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create table muci (col1 integer, col2 integer, col3 integer);&lt;br /&gt;alter table muci add primary key (col1, col2);&lt;br /&gt;&lt;br /&gt;insert into muci values (1, 1, 1);&lt;br /&gt;insert into muci values (2, 2, 2);&lt;br /&gt;insert into muci values (3, 3, 3);&lt;br /&gt;&lt;br /&gt;commit;&lt;br /&gt;create materialized view log on muci with primary key;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, let’s create the pre-built table and the materialized view.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create table muci_mv as &lt;br /&gt;select t.rowid rid, t.*, '1' processed, 'INSERT' operation from muci t;&lt;br /&gt;&lt;br /&gt;create materialized view muci_mv &lt;br /&gt;on prebuilt table &lt;br /&gt;refresh fast on demand as &lt;br /&gt;select t.rowid rid, t.* from muci t;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is important to notice that we’ve created the pre-built table with additional columns: the “processed” and the “operation” fields. These fields are going to be filled in using a trigger on the MUCI_MV table. Also, pay attention to the “rid” field which is supposed to store ROWID addresses for all records refreshed from the MUCI table (not ROWIDs of MUCI_MV records!). I’ll show you right in a minute what the reason of this column is.&lt;br /&gt;&lt;br /&gt;Let’s go on creating a very simple package:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create or replace package MUCI_TOOLKIT &lt;br /&gt;is&lt;br /&gt;&lt;br /&gt;  g_old_rid rowid;&lt;br /&gt;&lt;br /&gt;end MUCI_TOOLKIT;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This package has a global variable which is intended to store the old value of the “rid” column of a record which is about to be deleted.&lt;br /&gt;&lt;br /&gt;Our test scenario is almost finished! The final step is to create a trigger onto the MUCI_MV table which actually takes care of updating the additional flags:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create or replace trigger trg_biudr_muci_mv&lt;br /&gt;  before insert or update or delete on muci_mv  &lt;br /&gt;  for each row&lt;br /&gt;declare&lt;br /&gt;begin&lt;br /&gt;  if inserting then&lt;br /&gt;    dbms_output.put_line('inserting...');&lt;br /&gt;    :new.processed := '0';&lt;br /&gt;    if muci_toolkit.g_old_rid is not null and :new.rid = muci_toolkit.g_old_rid then&lt;br /&gt;      :new.operation := 'UPDATE';&lt;br /&gt;      muci_toolkit.g_old_rid := null; -- cleanup&lt;br /&gt;    else&lt;br /&gt;      :new.operation := 'INSERT';&lt;br /&gt;    end if;&lt;br /&gt;  end if;&lt;br /&gt;  if updating then&lt;br /&gt;    dbms_output.put_line('updating...');&lt;br /&gt;    :new.processed := '0';&lt;br /&gt;    :new.operation := 'UPDATE';&lt;br /&gt;  end if;&lt;br /&gt;  if deleting then&lt;br /&gt;    dbms_output.put_line('deleting...');&lt;br /&gt;    muci_toolkit.g_old_rid := :old.rid;&lt;br /&gt;  end if;&lt;br /&gt;end trg_biudr_muci_mv;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, it’s time to effectively test!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;external_interface@pdmdb&gt; set serveroutput on&lt;br /&gt;external_interface@pdmdb&gt; select * from muci;&lt;br /&gt;&lt;br /&gt; COL1  COL2  COL3&lt;br /&gt;----- ----- -----&lt;br /&gt;    1     1     1&lt;br /&gt;    2     2     2&lt;br /&gt;    3     3     3&lt;br /&gt;&lt;br /&gt;external_interface@pdmdb&gt; select * from muci_mv;&lt;br /&gt;&lt;br /&gt;RID                 COL1  COL2  COL3 PROCESSED OPERATION&lt;br /&gt;------------------ ----- ----- ----- --------- ---------&lt;br /&gt;AACdH+AAFAADheGAAA     1     1     1 1         INSERT&lt;br /&gt;AACdH+AAFAADheGAAB     2     2     2 1         INSERT&lt;br /&gt;AACdH+AAFAADheGAAC     3     3     3 1         INSERT&lt;br /&gt;&lt;br /&gt;external_interface@pdmdb&gt; update muci set col1='123' where col1=1 and col2=1;&lt;br /&gt;&lt;br /&gt;1 row updated&lt;br /&gt;&lt;br /&gt;external_interface@pdmdb&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete&lt;br /&gt;&lt;br /&gt;external_interface@pdmdb&gt; exec dbms_mview.refresh('MUCI_MV', 'f');&lt;br /&gt;&lt;br /&gt;deleting...&lt;br /&gt;inserting...&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed&lt;br /&gt;&lt;br /&gt;external_interface@pdmdb&gt; select * from muci_mv;&lt;br /&gt;&lt;br /&gt;RID                 COL1  COL2  COL3 PROCESSED OPERATION&lt;br /&gt;------------------ ----- ----- ----- --------- ---------&lt;br /&gt;AACdH+AAFAADheGAAB     2     2     2 1         INSERT&lt;br /&gt;AACdH+AAFAADheGAAC     3     3     3 1         INSERT&lt;br /&gt;AACdH+AAFAADheGAAA   123     1     1 0         UPDATE&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see it works as expected… smooth! The whole trick consists in checking if the DELETE and INSERT sequence refers to the same source ROWID. If this is the case then we know that an update on the primary key was involved.&lt;br /&gt;&lt;br /&gt;However, there are some open points regarding this approach:&lt;br /&gt;1. additional storage is required for storing the added RID column;&lt;br /&gt;2. the DBMS_MVIEW.REFRESH mechanism must follow the sequence order of DML commands performed on the source system which, as far as the oracle documentation states, is not always guaranteed in all Oracle versions.&lt;br /&gt;3. in some MetaLink notes (see Note:67424.1) it is stated that triggers are not supported on read only materialized views.. Yet, you can find a HOWTO on the same MetaLink (176213.1) which advise you to create a trigger on a prebuilt table in order to fill in an additional column (as shown above) with the current SYSDATE value.&lt;br /&gt;4. because we rely on ROWID values of course we’ll end up in big problems if on the source site some source tables are moved to another tablespace or they are re-imported.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116853569618415279?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116853569618415279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116853569618415279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116853569618415279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116853569618415279'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/infamous-update-on-primary-key.html' title='The Infamous Update on a Primary Key'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116838094930081235</id><published>2007-01-09T14:08:00.000-08:00</published><updated>2010-02-22T02:55:56.695-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqlplus'/><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>To DESC or @DESC...</title><content type='html'>There is one SQLPLUS command which seems to be out of my control as far as its displaying layout is concerned. As you already guess from the post title it's about the well known DESC command. Seems that it has a “self-tuning” layout which takes into consideration the current LINESIZE settings.&lt;br /&gt;&lt;br /&gt;For example, using a high value for the LINESIZE setting we obtain:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scott@DDB&gt; set linesize 300&lt;br /&gt;scott@DDB&gt; desc emp&lt;br /&gt; Name                                                                          &lt;br /&gt;         Null?     Type&lt;br /&gt; ------------------------------------------------------------------------------&lt;br /&gt;-------------------------------------------------------------------------------&lt;br /&gt;---------------- -------- -----------------------------------------------------&lt;br /&gt;---------------------------------------------------------------&lt;br /&gt; EMPNO                                                                         &lt;br /&gt;         NOT NULL NUMBER(4)&lt;br /&gt; ENAME                                                                         &lt;br /&gt;  VARCHAR2(10)&lt;br /&gt; JOB                                                                           &lt;br /&gt;  VARCHAR2(9)&lt;br /&gt; MGR                                                                           &lt;br /&gt;  NUMBER(4)&lt;br /&gt; HIREDATE                                                                      &lt;br /&gt;  DATE&lt;br /&gt; SAL                                                                           &lt;br /&gt;  NUMBER(7,2)&lt;br /&gt; COMM                                                                          &lt;br /&gt;  NUMBER(7,2)&lt;br /&gt; DEPTNO                                                                        &lt;br /&gt;  NUMBER(2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But using a lower value for the LINESIZE setting the output looks fine:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scott@DDB&gt; set linesize 80&lt;br /&gt;scott@DDB&gt; desc emp&lt;br /&gt; Name                                      Null?    Type&lt;br /&gt; ----------------------------------------- -------- ----------------------------&lt;br /&gt; EMPNO                                     NOT NULL NUMBER(4)&lt;br /&gt; ENAME                                              VARCHAR2(10)&lt;br /&gt; JOB                                                VARCHAR2(9)&lt;br /&gt; MGR                                                NUMBER(4)&lt;br /&gt; HIREDATE                                           DATE&lt;br /&gt; SAL                                                NUMBER(7,2)&lt;br /&gt; COMM                                               NUMBER(7,2)&lt;br /&gt; DEPTNO                                             NUMBER(2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;From my point of view this behavior is quite ugly especially when I am working within a console with horizontal scrolling capabilities. Using a high value for LINESIZE allows me to execute various 'SELECT * FROM' without worrying about output wrapping  but when DESC command comes in place I will always end up scrolling to the right side till I reach the displaying of the columns type, which is really, really ugly! So, in the end I've decided to create a script which provides the expected nice output. The main idea is to decrease the LINESIZE setting, to execute DESC and then to restore the old LINESIZE setting. Not a big deal! Below is my script:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;store set crr_settings.cfg replace&lt;br /&gt;set linesize 80&lt;br /&gt;desc &amp;1&lt;br /&gt;@crr_settings.cfg&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, all I have to do is to take care to prefix with a @ the DESC command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scott@DDB&gt; set linesize 300&lt;br /&gt;scott@DDB&gt; @desc emp&lt;br /&gt;Wrote file crr_settings.cfg&lt;br /&gt; Name                                      Null?    Type&lt;br /&gt; ----------------------------------------- -------- ----------------------------&lt;br /&gt; EMPNO                                     NOT NULL NUMBER(4)&lt;br /&gt; ENAME                                              VARCHAR2(10)&lt;br /&gt; JOB                                                VARCHAR2(9)&lt;br /&gt; MGR                                                NUMBER(4)&lt;br /&gt; HIREDATE                                           DATE&lt;br /&gt; SAL                                                NUMBER(7,2)&lt;br /&gt; COMM                                               NUMBER(7,2)&lt;br /&gt; DEPTNO                                             NUMBER(2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Have fun! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116838094930081235?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116838094930081235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116838094930081235' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116838094930081235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116838094930081235'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/to-desc-or-desc.html' title='To DESC or @DESC...'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116818392228337969</id><published>2007-01-07T07:31:00.000-08:00</published><updated>2010-02-22T02:55:22.759-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Do Direct Load Inserts Generate Redo?</title><content type='html'>As to so many Oracle related questions the answer is: IT DEPENDS...&lt;br /&gt;&lt;br /&gt;If you are in the middle of such a tricky situation where, in the development environment your bulk direct load process performs well but into production the same direct load process behaves poorly because it generates a lot of redo, then you should start by checking the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;is your development database running in NOARCHIVELOG mode? In NOARCHIVELOG mode the direct load operations produce redo information at minimum which is not necessary the same into a database which runs in ARCHIVELOG mode. It's not unlikely to have the development environment in NOARCHIVELOG and the production in ARCHIVELOG mode therefore this is the first thing to check.&lt;/li&gt;&lt;li&gt;is the destination table from the production site configured with NOLOGGING attribute? Without this setting the direct load inserts against the table will continue to generate redo information as normal. So, check the LOGGING column from (USER/ALL/DBA)_TABLES view for the corresponding destination table.&lt;/li&gt;&lt;li&gt;has the production database the FORCE LOGGING option enabled? This may be required if there are some standby databases in place therefore all direct load operations will produce redo information  no matter what. To check this you can query the FORCE_LOGGING column from the V$DATABASE view.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116818392228337969?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116818392228337969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116818392228337969' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116818392228337969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116818392228337969'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/do-direct-load-inserts-generate-redo.html' title='Do Direct Load Inserts Generate Redo?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116795136808305161</id><published>2007-01-04T14:52:00.000-08:00</published><updated>2010-02-22T02:55:22.759-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Impersonating Of Any Oracle User?</title><content type='html'>Yes, it is possible! It's like sudo command in UNIX or “Run As” in Windows (but without prompting for password). Starting with 8i version, Oracle has a special undocumented package called DBMS_SYS_SQL which provides the functionality needed for impersonating users. It is internally used in databases replication or within the XDB platform. Of course, execute right against this package should be granted with extreme care, as it can be easily exploited by hackers. Furthermore, as an additional precaution it is advisable to check from time to time to whom execute privilege for this package was granted.&lt;br /&gt;&lt;br /&gt;So, lets try it!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; connect sys as sysdba&lt;br /&gt;Enter password:&lt;br /&gt;Connected.&lt;br /&gt;&lt;br /&gt;SQL&gt; grant execute on dbms_sys_sql to alek;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;br /&gt;&lt;br /&gt;SQL&gt; connect alek&lt;br /&gt;Enter password:&lt;br /&gt;Connected.&lt;br /&gt;SQL&gt; declare&lt;br /&gt;  2  l_uid number;&lt;br /&gt;  3  l_sqltext varchar2(100) := 'grant dba to super_user identified by xxx';&lt;br /&gt;  4  l_myint integer;&lt;br /&gt;  5&lt;br /&gt;  6  begin&lt;br /&gt;  7  select user_id into l_uid from all_users where username like 'SYS';&lt;br /&gt;  8&lt;br /&gt;  9  l_myint:=sys.dbms_sys_sql.open_cursor();&lt;br /&gt; 10  sys.dbms_sys_sql.parse_as_user(l_myint, l_sqltext, dbms_sql.native, l_uid);&lt;br /&gt;&lt;br /&gt; 11&lt;br /&gt; 12  sys.dbms_sys_sql.close_cursor(l_myint);&lt;br /&gt; 13  end ;&lt;br /&gt; 14  /&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;SQL&gt; connect super_user/xxx&lt;br /&gt;Connected.&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br /&gt;Brrr!!! Nice but scary!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116795136808305161?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116795136808305161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116795136808305161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116795136808305161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116795136808305161'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2007/01/impersonating-of-any-oracle-user.html' title='Impersonating Of Any Oracle User?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116686910387079552</id><published>2006-12-23T02:16:00.000-08:00</published><updated>2010-02-22T02:55:22.759-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Spelling Numbers</title><content type='html'>Wouldn't be nice to be able to display numbers in their spelling textual format? There are a lot of applications which require such a feature: billing, bookkeeping systems etc. Well, if we remember right there is a special suffix for specifying the mask to convert a date using the TO_CHAR function. That special suffix is SP. However, being designed to work with date types it's not very obvious how it can be used for plain numbers. Well, even it's not very often used we can convert a number into a date representation using the Julian format and then spell it using the SP prefix. For example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select to_char(to_date(34, 'j'), 'jspth') spell from dual;&lt;br /&gt;&lt;br /&gt;SPELL&lt;br /&gt;-------------&lt;br /&gt;thirty-fourth&lt;br /&gt;&lt;br /&gt;SQL&gt; select to_char(to_date(1023, 'j'), 'jspth') spell from dual;&lt;br /&gt;&lt;br /&gt;SPELL&lt;br /&gt;-------------------------&lt;br /&gt;one thousand twenty-third&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lovely! Nevertheless, there are some limitations here, and some of them are quite ugly therefore they should be carefully analyzed before deciding to use this approach into a production system. The following are some of the problems you might encounter:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;it's not suitable for multi-language applications. The SP prefix always speaks in English, despite of the current NLS settings.&lt;/li&gt;&lt;li&gt;It cannot be used to display large numbers. In fact, the maximum number which can be spelled using this approach is exactly 5373484. It's quite small for a bookkeeping system, right?&lt;/li&gt;&lt;li&gt;How about negative numbers or zero? Forget it! It will not work!&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116686910387079552?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116686910387079552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116686910387079552' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116686910387079552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116686910387079552'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/spelling-numbers.html' title='Spelling Numbers'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116686640072843782</id><published>2006-12-23T01:30:00.000-08:00</published><updated>2010-02-22T02:55:56.696-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqlplus'/><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>SQLPLUS and Custom Languages</title><content type='html'>Even I'm from Romania, I don't like how the translation of various messages sounds into my own language. However, sometimes it's useful to enable such a feature if, for example, the error messages which come from the Oracle server must be displayed into the client application but using the native language. So, at the very beginning you might think it's enough just to issue an “ALTER SESSION SET NLS_LANGUAGE=ROMANIAN;” but most of the time you'll find that nothing changes. This is because Oracle needs some additional translation files which, of course, must be installed. To install them you'll need the well known Oracle Universal Installer and you have to provide &lt;span style="font-family:courier new;"&gt;-addLangs&lt;/span&gt; as a parameter. You'll be led into a special wizard page like the one shown below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/4178/4059/1600/618459/snapshot3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger/4178/4059/320/23605/snapshot3.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;After choosing and installing the preferred language we can go on and test if now SQLPLUS speaks our lingo.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; ALTER SESSION SET NLS_LANGUAGE=romanian;&lt;br /&gt;&lt;br /&gt;Sesiune modificata.&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from no_table;&lt;br /&gt;select * from no_table&lt;br /&gt;           *&lt;br /&gt;EROARE la linia 1:&lt;br /&gt;ORA-00942: tabelul sau vizualizarea nu exist?&lt;br /&gt;&lt;br /&gt;SQL&gt; select eroare bre;&lt;br /&gt;select eroare bre&lt;br /&gt;             *&lt;br /&gt;EROARE la linia 1:&lt;br /&gt;ORA-00923: cuvantul cheie FROM nu este g?sit in locul a?teptat&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So far so good! Nevertheless, as I previously said the translated messages are quite funny. By the way, I already found three translation mistakes into the above output but I will let Romanian readers to find them. Aaaa, I almost forgot to say: those strange question marks are in place there because my database character set is not appropriate for displaying romanian characters therefore please don't count this as a translation error. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116686640072843782?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116686640072843782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116686640072843782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116686640072843782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116686640072843782'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/sqlplus-and-custom-languages.html' title='SQLPLUS and Custom Languages'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116678589996855342</id><published>2006-12-22T03:10:00.000-08:00</published><updated>2010-02-22T02:57:45.268-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>CANCEL if you want to work!</title><content type='html'>Ohoo, this is quite nice! Usually, you wouldn't expect to make something to work unless you specify CANCEL, right? One interesting case is when you want to recreate the control file with the RESETLOGS option. The scenario is simple, you have an old backup which contains all your datafiles and archivelogs and, in addition, you was smart enough to backup the control file to trace. Now supposing you lost all current datafiles and the current redolog files. You have to restore and recover from your backup. The first thing is to restore your datafiles to the known location, to start the instance in the nomount state and to issue the CREATE CONTROLFILE command from the trace file. After the command is successfully executed your instance will  be brought into the mount state using the fresh created control file. Now, the next step is to use the RECOVER DATABASE command. Bellow is a sample output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; startup nomount&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  264241152 bytes&lt;br /&gt;Fixed Size                  1218868 bytes&lt;br /&gt;Variable Size              75499212 bytes&lt;br /&gt;Database Buffers          184549376 bytes&lt;br /&gt;Redo Buffers                2973696 bytes&lt;br /&gt;CREATE CONTROLFILE REUSE DATABASE "DDB" RESETLOGS  ARCHIVELOG&lt;br /&gt;    MAXLOGFILES 16&lt;br /&gt;    MAXLOGMEMBERS 3&lt;br /&gt;    MAXDATAFILES 100&lt;br /&gt;    MAXINSTANCES 8&lt;br /&gt;    MAXLOGHISTORY 292&lt;br /&gt;LOGFILE&lt;br /&gt;  GROUP 1 (&lt;br /&gt;    '/opt/oracle/oradata/DDB/onlinelog/o1_mf_1_2pdco23c_.log',&lt;br /&gt;    '/opt/oracle/flash_recovery_area/DDB/onlinelog/o1_mf_1_2pdco49x_.log'&lt;br /&gt;  ) SIZE 50M,&lt;br /&gt;  GROUP 2 (&lt;br /&gt;    '/opt/oracle/oradata/DDB/onlinelog/o1_mf_2_2pdco6j0_.log',&lt;br /&gt;    '/opt/oracle/flash_recovery_area/DDB/onlinelog/o1_mf_2_2pdco8ns_.log'&lt;br /&gt;  ) SIZE 50M,&lt;br /&gt;  GROUP 3 (&lt;br /&gt;    '/opt/oracle/oradata/DDB/onlinelog/o1_mf_3_2pdcoby5_.log',&lt;br /&gt;    '/opt/oracle/flash_recovery_area/DDB/onlinelog/o1_mf_3_2pdcof0o_.log'&lt;br /&gt;  ) SIZE 50M&lt;br /&gt;-- STANDBY LOGFILE&lt;br /&gt;DATAFILE&lt;br /&gt;  '/opt/oracle/oradata/DDB/datafile/o1_mf_system_2rlg719d_.dbf',&lt;br /&gt;  '/opt/oracle/oradata/DDB/datafile/o1_mf_undotbs1_2rlg71l3_.dbf',&lt;br /&gt;  '/opt/oracle/oradata/DDB/datafile/o1_mf_sysaux_2rlg714v_.dbf',&lt;br /&gt;  '/opt/oracle/oradata/DDB/datafile/o1_mf_users_2rlg71kk_.dbf'&lt;br /&gt;CHARACTER SET WE8ISO8859P1&lt;br /&gt; ;&lt;br /&gt;&lt;br /&gt;SQL&gt; select open_mode from v$database;&lt;br /&gt;&lt;br /&gt;OPEN_MODE&lt;br /&gt;----------&lt;br /&gt;MOUNTED&lt;br /&gt;&lt;br /&gt;SQL&gt; recover database using backup controlfile;&lt;br /&gt;ORA-00279: change 793731 generated at 12/22/2006 12:00:32 needed for thread 1&lt;br /&gt;ORA-00289: suggestion :&lt;br /&gt;/opt/oracle/flash_recovery_area/DDB/archivelog/1_1_609804799.dbf&lt;br /&gt;ORA-00280: change 793731 for thread 1 is in sequence #1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Specify log: {&lt;RET&gt;=suggested | filename | AUTO | CANCEL}&lt;br /&gt;&lt;br /&gt;ORA-00279: change 794266 generated at 12/22/2006 12:09:00 needed for thread 1&lt;br /&gt;ORA-00289: suggestion :&lt;br /&gt;/opt/oracle/flash_recovery_area/DDB/archivelog/1_2_609804799.dbf&lt;br /&gt;ORA-00280: change 794266 for thread 1 is in sequence #2&lt;br /&gt;ORA-00278: log file&lt;br /&gt;'/opt/oracle/flash_recovery_area/DDB/archivelog/1_1_609804799.dbf' no longer&lt;br /&gt;needed for this recovery&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Specify log: {&lt;RET&gt;=suggested | filename | AUTO | CANCEL}&lt;br /&gt;&lt;br /&gt;ORA-00279: change 794268 generated at 12/22/2006 12:09:03 needed for thread 1&lt;br /&gt;ORA-00289: suggestion :&lt;br /&gt;/opt/oracle/flash_recovery_area/DDB/archivelog/1_3_609804799.dbf&lt;br /&gt;ORA-00280: change 794268 for thread 1 is in sequence #3&lt;br /&gt;ORA-00278: log file&lt;br /&gt;'/opt/oracle/flash_recovery_area/DDB/archivelog/1_2_609804799.dbf' no longer&lt;br /&gt;needed for this recovery&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Specify log: {&lt;RET&gt;=suggested | filename | AUTO | CANCEL}&lt;br /&gt;&lt;br /&gt;ORA-00279: change 794271 generated at 12/22/2006 12:09:07 needed for thread 1&lt;br /&gt;ORA-00289: suggestion :&lt;br /&gt;/opt/oracle/flash_recovery_area/DDB/archivelog/1_4_609804799.dbf&lt;br /&gt;ORA-00280: change 794271 for thread 1 is in sequence #4&lt;br /&gt;ORA-00278: log file&lt;br /&gt;'/opt/oracle/flash_recovery_area/DDB/archivelog/1_3_609804799.dbf' no longer&lt;br /&gt;needed for this recovery&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Specify log: {&lt;RET&gt;=suggested | filename | AUTO | CANCEL}&lt;br /&gt;&lt;br /&gt;ORA-00308: cannot open archived log&lt;br /&gt;'/opt/oracle/flash_recovery_area/DDB/archivelog/1_4_609804799.dbf'&lt;br /&gt;ORA-27037: unable to obtain file status&lt;br /&gt;Linux Error: 2: No such file or directory&lt;br /&gt;Additional information: 3&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SQL&gt; ALTER DATABASE OPEN RESETLOGS;&lt;br /&gt;ALTER DATABASE OPEN RESETLOGS&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-01113: file 1 needs media recovery&lt;br /&gt;ORA-01110: data file 1:&lt;br /&gt;'/opt/oracle/oradata/DDB/datafile/o1_mf_system_2rlg719d_.dbf'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Uppsy! File 1 needs media recovery? Why? &lt;br /&gt;Because, when I have been asked for the last log archive I didn't specify CANCEL. From the Oracle server point of view, the recover process was unsuccessful. So, the correct approach is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; recover database until cancel using backup controlfile;&lt;br /&gt;ORA-00279: change 794271 generated at 12/22/2006 12:09:07 needed for thread 1&lt;br /&gt;ORA-00289: suggestion :&lt;br /&gt;/opt/oracle/flash_recovery_area/DDB/archivelog/1_4_609804799.dbf&lt;br /&gt;ORA-00280: change 794271 for thread 1 is in sequence #4&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Specify log: {&lt;RET&gt;=suggested | filename | AUTO | CANCEL}&lt;br /&gt;CANCEL&lt;br /&gt;Media recovery cancelled.&lt;br /&gt;SQL&gt; ALTER DATABASE OPEN RESETLOGS;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, explicit CANCEL does matter in this case!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116678589996855342?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116678589996855342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116678589996855342' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116678589996855342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116678589996855342'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/cancel-if-you-want-to-work.html' title='CANCEL if you want to work!'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116671802509753783</id><published>2006-12-21T08:15:00.000-08:00</published><updated>2010-02-22T02:57:45.268-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>Should I Delete All Archives In One Shoot?</title><content type='html'>I was just wondering what is the best way to delete the backed up archives using RMAN. I have to choose between DELETE INPUT and DELETE ALL INPUT options. &lt;br /&gt;In my environment, all archives are written on two different locations. If I am going to use the DELETE ALL INPUT option then after the archives from one of the two locations are backed up, all the corresponding archive files are deleted from all available locations. If I am going to use DELETE INPUT option then only the backed up archives are deleted, just from one of the two locations. &lt;br /&gt;Now, I must admit that using the BACKUP ARCHIVELOG ALL command with DELETE ALL INPUT  sounds to me a little bit scary as after the successful completion of it I will end up with just one backup set with all backed up archives but no archives redundancy. This backup set becomes the single point of failure if a database recovery must take place and those archives are required.&lt;br /&gt;So, the other approach is to use the DELETE INPUT option only. The below figure shows what's happening in this case:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/4178/4059/1600/573656/snapshot1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger/4178/4059/320/217051/snapshot1.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;At T0 moment,  there are archives not backed up on both locations. The BACKUP command creates the “Bacup Set1” and deletes the corresponding archives from the LOCATION 1. So, now I have archives on LOCATION 2 and into the backup set as well (redundancy still 2). Suppose that after new archives are generated a new backup is taken. The following figure depicts what will happen in this case:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/4178/4059/1600/691788/snapshot2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger/4178/4059/320/988299/snapshot2.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;As it can be noticed, the next BACKUP command creates the “Backup Set2” which contains all archives from the LOCATION2 not deleted by the previous BACKUP command and, in addition, the new generated archive logs from the LOCATION1. These backed up archives are deleted but the redundancy level for them is still two. Much safer, right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116671802509753783?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116671802509753783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116671802509753783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116671802509753783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116671802509753783'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/should-i-delete-all-archives-in-one.html' title='Should I Delete All Archives In One Shoot?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116662224005016861</id><published>2006-12-20T05:42:00.000-08:00</published><updated>2010-02-22T02:57:45.269-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RMAN'/><title type='text'>Don't Forget to Restore Your Read-only Tablespaces</title><content type='html'>I know, this is a basic one! But, me personally, I don't restore/recover databases everyday therefore is quite easy to forget some basics. So, supposing that you have lost all datafiles and some of them were part of some read-only tablespaces then it is important to remember that, by default, RMAN will not restore any datafiles from those read-only tablespaces. Hopefully, RMAN will display a warning, something like this: “&lt;span style="font-family: courier new;"&gt;datafile X not processed because file is read-only&lt;/span&gt;”, but the restore operation will go on without problems. So, in order to restore all datafiles including the ones from the read-only tablespaces then the correct command is: “&lt;span style="font-family: courier new;"&gt;RESTORE DATABASE CHECK READONLY;&lt;/span&gt;”.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116662224005016861?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116662224005016861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116662224005016861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116662224005016861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116662224005016861'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/dont-forget-to-restore-your-read-only.html' title='Don&apos;t Forget to Restore Your Read-only Tablespaces'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116660897132160828</id><published>2006-12-20T02:00:00.000-08:00</published><updated>2010-02-22T02:55:22.760-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Does any Datablock Change Generates Flashback Logs?</title><content type='html'>In the “Database Backup and Recovery Basics” book from the 10g Release 2 (10.2) documentation, in the sub-chapter “5.3.7 Performance Tuning for Flashback Database” there is a remark which says:&lt;br /&gt;&lt;br /&gt;“Queries do not change data and thus do not contribute to logging activity for Flashback Database.”&lt;br /&gt;&lt;br /&gt;Hmm... indeed they do not change actual business data but they can change database blocks in the so called “block cleanout” process and, in such cases, they actually generate redolog information.&lt;br /&gt;&lt;br /&gt;My first assumption was that “Flashback database” engine detects on the very low level any change in data blocks, either as a consequence of a DML or as a consequence of an internal data block maintenance process such as the “block cleanout” operation.&lt;br /&gt;&lt;br /&gt;So, I've decided to test if the “block cleanout” process does or does not generate flashback logs. The scenario is simple: my test database has a datablock size of 8K so I will create a dummy table so that each of its rows to fit into one oracle datablock. Then I will insert enough records into this table so that, in the end, my transaction to simply give up cleaning out all modified blocks. In the end I will force a full table scan against the sample table in order to perform the cleanout process. During these operations I will closely look to some of my session statistics.&lt;br /&gt;&lt;br /&gt;Here we go:&lt;br /&gt;&lt;br /&gt;1.first of all, some checking and some rights are needed:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; connect / as sysdba&lt;br /&gt;Connected.&lt;br /&gt;SQL&gt; show parameter db_block_size&lt;br /&gt;&lt;br /&gt;NAME                                 TYPE        VALUE&lt;br /&gt;------------------------------------ ----------- ------------------------------&lt;br /&gt;db_block_size                        integer     8192&lt;br /&gt;SQL&gt; select flashback_on from v$database;&lt;br /&gt;&lt;br /&gt;FLASHBACK_ON&lt;br /&gt;------------------&lt;br /&gt;YES&lt;br /&gt;&lt;br /&gt;SQL&gt; grant select on v_$mystat to alek;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;br /&gt;&lt;br /&gt;SQL&gt; grant select on v_$statname to alek;&lt;br /&gt;&lt;br /&gt;Grant succeeded.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2.now, lets create our test environment:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;10:57:46 SQL&gt; connect alek&lt;br /&gt;Enter password:&lt;br /&gt;Connected.&lt;br /&gt;10:57:55 SQL&gt; create table muci (col1 char(2000), col2 char(2000), col3 char(2000));&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;10:58:12 SQL&gt; select name, value from v$mystat natural join v$statname&lt;br /&gt;where regexp_like(name, '(.*flash.*)|(redo size)');&lt;br /&gt;&lt;br /&gt;NAME                                                                  VALUE&lt;br /&gt;---------------------------------------------------------------- ----------&lt;br /&gt;physical reads for flashback new                                          6&lt;br /&gt;redo size                                                              9564&lt;br /&gt;flashback log writes                                                      0&lt;br /&gt;&lt;br /&gt;10:58:22 SQL&gt; insert into muci select 'a', 'b', 'c' from all_objects;&lt;br /&gt;&lt;br /&gt;40710 rows created.&lt;br /&gt;&lt;br /&gt;11:01:21 SQL&gt; commit;&lt;br /&gt;&lt;br /&gt;Commit complete.&lt;br /&gt;&lt;br /&gt;11:01:37 SQL&gt; select name, value from v$mystat natural join v$statname&lt;br /&gt;where regexp_like(name, '(.*flash.*)|(redo size)');&lt;br /&gt;&lt;br /&gt;NAME                                                                  VALUE&lt;br /&gt;---------------------------------------------------------------- ----------&lt;br /&gt;physical reads for flashback new                                      41526&lt;br /&gt;redo size                                                         263629980&lt;br /&gt;flashback log writes                                                      0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once again after a minute:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;11:01:45 SQL&gt; select name, value from v$mystat natural join v$statname&lt;br /&gt;where regexp_like(name, '(.*flash.*)|(redo size)');&lt;br /&gt;&lt;br /&gt;NAME                                                                  VALUE&lt;br /&gt;---------------------------------------------------------------- ----------&lt;br /&gt;physical reads for flashback new                                      41526&lt;br /&gt;redo size                                                         263629980&lt;br /&gt;flashback log writes                                                      0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There's no change! Go on with the clean out process:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;11:05:29 SQL&gt; select count(1) from muci;&lt;br /&gt;&lt;br /&gt; COUNT(1)&lt;br /&gt;----------&lt;br /&gt;    40710&lt;br /&gt;&lt;br /&gt;11:06:11 SQL&gt; select name, value from v$mystat natural join v$statname&lt;br /&gt;where regexp_like(name, '(.*flash.*)|(redo size)');&lt;br /&gt;&lt;br /&gt;NAME                                                                  VALUE&lt;br /&gt;---------------------------------------------------------------- ----------&lt;br /&gt;physical reads for flashback new                                      41526&lt;br /&gt;redo size                                                         266561132&lt;br /&gt;flashback log writes                                                      0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Trying once again after some minutes within the same session reveals no changes, therefore we can conclude that flashback logs were not generated even asynchronously after some time.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;11:06:21 SQL&gt; select name, value from v$mystat natural join v$statname&lt;br /&gt;where regexp_like(name, '(.*flash.*)|(redo size)');&lt;br /&gt;&lt;br /&gt;NAME                                                                  VALUE&lt;br /&gt;---------------------------------------------------------------- ----------&lt;br /&gt;physical reads for flashback new                                      41526&lt;br /&gt;redo size                                                         266561132&lt;br /&gt;flashback log writes                                                      0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Thats interesting! As it can be seen, the cleanup process has, indeed, generated redolog information which means that it changed some header information from the cleaned out datablocks but no flashback logs were produced.&lt;br /&gt;&lt;br /&gt;So, as far as these tests are concerned the above statement from the Oracle official documentation seems to be correct!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116660897132160828?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116660897132160828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116660897132160828' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116660897132160828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116660897132160828'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/does-any-datablock-change-generates.html' title='Does any Datablock Change Generates Flashback Logs?'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36335310.post-116655546694003621</id><published>2006-12-19T11:10:00.000-08:00</published><updated>2010-02-22T02:55:22.760-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RDBMS'/><title type='text'>Playing Around with “Flashback Database”</title><content type='html'>“Flashback Database” is a new feature available in 10g databases and it can be used to rewind the content of the database to a previous moment in time. The key elements of this feature are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;flashback logs&lt;/li&gt;&lt;li&gt;restore points&lt;/li&gt;&lt;/ul&gt;By default the database runs with the “flashback database” feature disabled. I can always find out if this feature is activated or not by querying the V$DATABASE view.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; SELECT FLASHBACK_ON FROM V$DATABASE;&lt;br /&gt;&lt;br /&gt;FLASHBACK_ON&lt;br /&gt;------------------&lt;br /&gt;NO&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;There are some important requirements which must be fulfilled in order to start using this feature:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a “Flash Recovery Area” must be setup;&lt;/li&gt;&lt;li&gt;the database must run in ARCHIVELOG mode;&lt;/li&gt;&lt;/ul&gt;To enable flashback database the following steps should be followed:&lt;br /&gt;&lt;br /&gt;1.clean shutdown of the database:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; shutdown immediate&lt;br /&gt;Database closed.&lt;br /&gt;Database dismounted.&lt;br /&gt;ORACLE instance shut down.&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;2.startup the database in mount state:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; startup mount&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  264241152 bytes&lt;br /&gt;Fixed Size      1218868 bytes&lt;br /&gt;Variable Size     79693516 bytes&lt;br /&gt;Database Buffers   180355072 bytes&lt;br /&gt;Redo Buffers      2973696 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;3. enable the flashback database feature:&lt;br /&gt;&lt;pre&gt;SQL&gt; alter database flashback on;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4.open the database:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter database open;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, that the “Flashback Database” is enabled I can monitor and estimate the size of flashback logs by using the V$FLASHBACK_DATABASE_LOG and V$FLASH_RECOVERY_AREA_USAGE views. I can perform some massive updates/inserts and to query those two views afterwards to see how the effective and estimate flashback log sizes are affected.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; select * from v$flashback_database_log;&lt;br /&gt;&lt;br /&gt;OLDEST_FLASHBACK_SCN OLDEST_FL RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE&lt;br /&gt;-------------------- --------- ---------------- -------------- ------------------------&lt;br /&gt;            624609 19-DEC-06             1440        8192000                283582464&lt;br /&gt;&lt;br /&gt;SQL&gt; select * from v$flash_recovery_area_usage;&lt;br /&gt;&lt;br /&gt;FILE_TYPE    PERCENT_SPACE_USED PERCENT_SPACE_RECLAIMABLE NUMBER_OF_FILES&lt;br /&gt;------------ ------------------ ------------------------- ---------------&lt;br /&gt;CONTROLFILE                 .33                         0               1&lt;br /&gt;ONLINELOG                  7.32                         0               3&lt;br /&gt;ARCHIVELOG                  .61                         0               1&lt;br /&gt;BACKUPPIECE               77.72                     25.84               8&lt;br /&gt;IMAGECOPY                     0                         0               0&lt;br /&gt;FLASHBACKLOG                .38                         0               1&lt;br /&gt;&lt;br /&gt;6 rows selected.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above listing reveals that currently I have a flashback log file of ~8M and the estimated flashback log size is ~270M.&lt;br /&gt;OK, lets see this feature in action. I am going to create a restore point, to perform some inserts and to flashback the database to the restore point.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; create restore point before_update;&lt;br /&gt;&lt;br /&gt;Restore point created.&lt;br /&gt;&lt;br /&gt;SQL&gt; create table alek.fback_test as select * from all_objects;&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(1) from alek.fback_test;&lt;br /&gt;&lt;br /&gt;COUNT(1)&lt;br /&gt;----------&lt;br /&gt;   49337&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, I want to rewind the database back to the restore point. This will imply a shutdown, a startup in mount state, the corresponding FLASHBACK command and the opening of the database with the RESETLOGS clause.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; shutdown immediate&lt;br /&gt;Database closed.&lt;br /&gt;Database dismounted.&lt;br /&gt;ORACLE instance shut down.&lt;br /&gt;SQL&gt; startup mount&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  264241152 bytes&lt;br /&gt;Fixed Size                  1218868 bytes&lt;br /&gt;Variable Size              88082124 bytes&lt;br /&gt;Database Buffers          171966464 bytes&lt;br /&gt;Redo Buffers                2973696 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;SQL&gt; flashback database to restore point before_update;&lt;br /&gt;&lt;br /&gt;Flashback complete.&lt;br /&gt;&lt;br /&gt;SQL&gt; alter database open resetlogs;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(1) from alek.fback_test;&lt;br /&gt;select count(1) from alek.fback_test&lt;br /&gt;                        *&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-00942: table or view does not exist&lt;br /&gt;&lt;/pre&gt;Everything went just perfect! The database was restored as it was when the restore point was defined. However, if my business requirements decide the need to restore the database to the defined restore point only and not between now and the time the restore point was defined then a better approach is to use guaranteed restore points with flashback database disabled. In this case the amount of generated flashback logs is smaller and the performance of an application which often modifies data is improved.&lt;br /&gt;So, if I am going to use the above approach the first thing to be done is to disable the flashback database feature. This can be done with the database open.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; alter database flashback off;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, switching back is not possible when the database is in the OPEN state:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SQL&gt; alter database flashback on;&lt;br /&gt;alter database flashback on&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-38759: Database must be mounted by only one instance and not open.&lt;br /&gt;&lt;/pre&gt;Another important thing to notice is that I cannot create the first guaranteed restore point with the database open. If trying to do so I'll get an error message as shown below:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; create restore point before_delivery guarantee flashback database;&lt;br /&gt;create restore point before_delivery guarantee flashback database&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-38784: Cannot create restore point 'BEFORE_DELIVERY'.&lt;br /&gt;ORA-38787: Creating the first guaranteed restore point requires mount mode &lt;br /&gt;when flashback database is off.&lt;br /&gt;&lt;/pre&gt;The error message is quite self explanatory therefore the next step would be to cleanly shutdown the database and to start it in the mount state.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; shutdown immediate&lt;br /&gt;Database closed.&lt;br /&gt;Database dismounted.&lt;br /&gt;ORACLE instance shut down.&lt;br /&gt;SQL&gt; startup mount&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  264241152 bytes&lt;br /&gt;Fixed Size                  1218868 bytes&lt;br /&gt;Variable Size              88082124 bytes&lt;br /&gt;Database Buffers          171966464 bytes&lt;br /&gt;Redo Buffers                2973696 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;SQL&gt; create restore point before_delivery guarantee flashback database;&lt;br /&gt;&lt;br /&gt;Restore point created.&lt;br /&gt;&lt;br /&gt;SQL&gt; alter database open;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;/pre&gt;Now, lets simulate the same scenario as we did with the flashback database feature enabled.&lt;br /&gt;&lt;pre&gt;SQL&gt; create table alek.fback_test as select * from all_objects;&lt;br /&gt;&lt;br /&gt;Table created.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(1) from alek.fback_test;&lt;br /&gt;&lt;br /&gt;COUNT(1)&lt;br /&gt;----------&lt;br /&gt;   49337&lt;br /&gt;&lt;br /&gt;SQL&gt; shutdown immediate&lt;br /&gt;Database closed.&lt;br /&gt;Database dismounted.&lt;br /&gt;ORACLE instance shut down.&lt;br /&gt;SQL&gt; startup mount&lt;br /&gt;ORACLE instance started.&lt;br /&gt;&lt;br /&gt;Total System Global Area  264241152 bytes&lt;br /&gt;Fixed Size                  1218868 bytes&lt;br /&gt;Variable Size              88082124 bytes&lt;br /&gt;Database Buffers          171966464 bytes&lt;br /&gt;Redo Buffers                2973696 bytes&lt;br /&gt;Database mounted.&lt;br /&gt;SQL&gt; flashback database to restore point before_delivery;&lt;br /&gt;&lt;br /&gt;Flashback complete.&lt;br /&gt;&lt;br /&gt;SQL&gt; alter database open resetlogs;&lt;br /&gt;&lt;br /&gt;Database altered.&lt;br /&gt;&lt;br /&gt;SQL&gt; select count(1) from alek.fback_test;&lt;br /&gt;select count(1) from alek.fback_test&lt;br /&gt;                        *&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-00942: table or view does not exist&lt;br /&gt;&lt;/pre&gt;Lovely, it works as expected! Now, I'm wondering what happen with my guaranteed restore point.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; select name, time, guarantee_flashback_database from v$restore_point;&lt;br /&gt;&lt;br /&gt;NAME                           TIME                                     GUA&lt;br /&gt;------------------------------ ---------------------------------------- ---&lt;br /&gt;BEFORE_DELIVERY                19-DEC-06 05.01.55.000000000 PM          YES&lt;br /&gt;BEFORE_UPDATE                  19-DEC-06 03.54.19.000000000 PM          NO&lt;br /&gt;&lt;/pre&gt;It is still there. The guaranteed restore points are never automatically age out therefore the only option I have in order to delete it is to use the DROP RESTORE POINT command.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SQL&gt; drop restore point before_delivery;&lt;br /&gt;&lt;br /&gt;Restore point dropped.&lt;br /&gt;&lt;br /&gt;SQL&gt; select name, time, guarantee_flashback_database from v$restore_point;&lt;br /&gt;&lt;br /&gt;NAME                           TIME                                     GUA&lt;br /&gt;------------------------------ ---------------------------------------- ---&lt;br /&gt;BEFORE_UPDATE                  19-DEC-06 03.54.19.000000000 PM          NO&lt;br /&gt;&lt;/pre&gt;Now, the ugly part of this is that I've end up with the previous situation when no guaranteed restore points were defined and the first one must be always created with the database started in the mount state.&lt;br /&gt;&lt;pre width="500"&gt;SQL&gt; create restore point before_delivery guarantee flashback database;&lt;br /&gt;create restore point before_delivery guarantee flashback database&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-38784: Cannot create restore point 'BEFORE_DELIVERY'.&lt;br /&gt;ORA-38787: Creating the first guaranteed restore point requires mount mode &lt;br /&gt;when flashback database is off.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The workaround would be to create a second guaranteed restore point and to delete the previous one so that at least one guaranteed restore point to be defined. However, the drawback of this is that I have to maintain this guaranteed restore point if my goal is to maximize the availability of the database.&lt;br /&gt;&lt;br /&gt;After the evaluation of this feature I can say what I like and what I don't like about it:&lt;br /&gt;&lt;br /&gt;I like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the straightforward way of configuring and using it;&lt;/li&gt;&lt;li&gt;the possibility to estimate the size of flashback logs through the V$FLASHBACK_DATABASE_LOG view;&lt;/li&gt;&lt;li&gt;much easier to use than the classical database incomplete recovery;&lt;/li&gt;&lt;/ul&gt;I don't like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the potential performance issues on a productive system which performs a lot of changes in the underlying data.&lt;/li&gt;&lt;li&gt;the fact that i cannot use it to rewind the content of just one or several tablespaces. If the database hosts more than one application then all of them will be affected therefore the remaining option will still remain the TPITR. The “Flashback Database” feature is closer to the “Database incomplete recovery” than the TPITR feature.&lt;/li&gt;&lt;li&gt;From my point of view this feature suits well into test and/or developing environments were the likelihood of making mistakes is greater in comparison with the production environment which is supposed to be used in a restrictive and controlled way. The main benefit of using it in production systems could be seen from the application deployment strategy perspective. Before running an update script as part of the application delivery process the DBA can define a guaranteed restore point and if something nasty happens within that script then he/she can easily rewind the database as it was at the time the restore point was defined. However, the fact that the database should be shutdown doesn't sound very well to me as precious cached data from the SGA will be lost.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36335310-116655546694003621?l=oracle-cookies.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-cookies.blogspot.com/feeds/116655546694003621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36335310&amp;postID=116655546694003621' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116655546694003621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36335310/posts/default/116655546694003621'/><link rel='alternate' type='text/html' href='http://oracle-cookies.blogspot.com/2006/12/playing-around-with-flashback-database.html' title='Playing Around with “Flashback Database”'/><author><name>Alexandru Tică</name><uri>http://www.blogger.com/profile/12127407011884904816</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://bp0.blogger.com/_gGEccZZIMqc/R1kWmNqVxAI/AAAAAAAAABA/DyA7msVPfWM/S220/me.png'/></author><thr:total>1</thr:total></entry></feed>
