Tuesday, November 27, 2012

Enable Data Guard Broker in an Existing DG Envrionrment

There are several advantages to using the data guard broker to configure and manage your data guard environment.  Don't get me wrong, I believe in command line and the power of understanding what tools, and GUIs provide.  The broker provides a single integrated view of a data guard configuration.  Configuration changes, monitoring and switchover/failover are all available through the broker providing efficient management of a the environment.  When you are working with several environments that include logical standbys an efficient method of managing all aspects is not only a time saving but a necessities.  Performing these tasks through command line is more of luxury. 

So I already have a standby database (or multiple standbys in some cases) how do I set up the broker to make my life easier?

The broker requires a special static listener in order for the failover/switchover to work.  The broker will use this listener to connect as SYSDBA remotely and perform the startup.  The key here is the global name will be the db_unique_name appended with DGMGRL and the domain the database resides.  This must be done for both the primary and the standby.   No TNS entry is required because the broker knows this is the listener to utilize.

On the primary server:

SID_LIST_LISTENER =
   (SID_LIST =
      (SID_DESC =
         (GLOBAL_DBNAME = PRIMARY_DGMGRL)
         (ORACLE_HOME = /u01/app/oracle/product/11.2.0.3)
         (SID_NAME = PRIMARY)
    )
)

On the standby server:

SID_LIST_LISTENER =
   (SID_LIST =
      (SID_DESC =
         (GLOBAL_DBNAME = STANDBY_DGMGRL)
         (ORACLE_HOME = /u01/app/oracle/product/11.2.0.3)
         (SID_NAME = PRIMARY)
    )
)

Enable data guard broker by setting the DG_BROKER_START parameter to TRUE:

ALTER SYSTEM SET DG_BROKER_START=TRUE;

There are two configuration files for the broker the default values:

$ORACLE_HOME/dbs/dr1.dat
$ORACLE_HOME/dbs/dr2.dat

For RAC it is suggested that these are changed to a shared file system.

Start the data guard broker command line utility and connect as SYS.  It is assumed by the broker that sysdba is the privilege and therefore you don't need to specify it.

dgmgrl
DGMGRL> CONNECT SYS
Password:

Next we create the configuration by specifying the primary database name, and the configuration name.

DGMGRL> CREATE CONFIGURATION DG1' AS
PRIMARY DATABASE IS 'PRIMARY'
CONNECT IDENTIFIER IS 'PRIMARY' ;

Configuration "DG1" created with primary database "PRIMARY"

Add the standby databases to the configuration.

DGMGRL> ADD DATABASE 'STANDBY' AS
CONNECT IDENTIFIER IS   'STANDBY';

Database 'STANDBY' added

The data guard configuration must then be enabled.

DGMGRL> ENABLE CONFIGURATION;
Enabled


 







 

Wednesday, November 21, 2012

Data Pump Export Schema within Pl/SQL

I have one client where I don't have access to the database server, but still need to perform exports to move metadata.  This can easily be accomplished using the Data Pump APIs.  Here's an example of the script that I use, its the same script from The Data Pump API Utilities manual from Oracle.



DECLARE
  ind NUMBER;              
  h1 NUMBER;               
  percent_done NUMBER;     
  job_state VARCHAR2(30);  
  le ku$_LogEntry;         
  js ku$_JobStatus;        
  jd ku$_JobDesc;          
  sts ku$_Status;          
BEGIN

 h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'MYJOB','LATEST');
 
 DBMS_DATAPUMP.ADD_FILE(h1,'myexport.dmp','EXPORT_DIR');
 
 DBMS_DATAPUMP.ADD_FILE(handle=>h1,filename=>'myexport.log',directory=>'EXPORT_DIR',
    filetype=>DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE); 
 
 DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''MY'')');

  DBMS_DATAPUMP.START_JOB(h1);

  percent_done := 0;
  job_state := 'UNDEFINED';
  while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
    dbms_datapump.get_status(h1,
           dbms_datapump.ku$_status_job_error +
           dbms_datapump.ku$_status_job_status +
           dbms_datapump.ku$_status_wip,-1,job_state,sts);
    js := sts.job_status;

    if js.percent_done != percent_done
    then
      dbms_output.put_line('*** Job percent done = ' ||
                           to_char(js.percent_done));
      percent_done := js.percent_done;
    end if;

   if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
    then
      le := sts.wip;
    else
      if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
      then
        le := sts.error;
      else
        le := null;
      end if;
    end if;
    if le is not null
    then
      ind := le.FIRST;
      while ind is not null loop
        dbms_output.put_line(le(ind).LogText);
        ind := le.NEXT(ind);
      end loop;
    end if;
  end loop;

  dbms_output.put_line('Job has completed');
  dbms_output.put_line('Final job state = ' || job_state);
  dbms_datapump.detach(h1);
END;
/

For a table level export simply replace the lines as follows:


h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'MYJOB','LATEST');
 
   h1 := DBMS_DATAPUMP.OPEN('EXPORT','TABLE',NULL,'MYJOB',LATEST'); 
    
 
DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''MY'')');
 
    DBMS_DATAPUMP.METADATA_FILTER(h1,'NAME_EXPR',IN (''TABLE1'',''TABLE2''...)'); 

   

 
 

   

Wednesday, October 24, 2012

Commands I Always Forget

This post is aimed at one location for maintaining commands I can't seem to keep straight and end up googling.  PSOUG and Morgan's library our great resources, but some times I just want a quick place to stop by and retrieve what I need.  As I run into these commands I'll update this page.

Dropping a database 11.2 Single Instance

 SQLPLUS:

 SQL> shutdown immediate
 SQL> startup restricted mount
 SQL> drop database;

RMAN:

> RMAN
RMAN>  CONNECT TARGET SYS@orcl

target database Password: password
connected to target database:  orcl (DBID=4920931111)

 RMAN > STARTUP FORCE MOUNT
 RMAN > SQL 'ALTER SYSTEM ENABLE RESTRICTED SESSION';
 RMAN> DROP DATABASE INCLUDING BACKUPS NOPROMPT;

Stop and Start Physical Standby 

SQLPLUS

Start 
 SQL> ALTER DATABASE RECOVER MANAGED STANDBY DISCONNECT FROM SESSION;

Stop

SQL> ALTER DATABASE RECOVER MANAGED STANDBY CANCEL; 

CRSCTL

crsctl start crs 
   start cluster 11.2 must be root or have sudo rights

crsctl stop crs
    stop cluster 11.2 must be root or have sudo rights

crsctl stat res -t
   displays the shorten form of the status (10.2 crs_stat)  

crsctl enable crs
     enable clusterware daemons to auto start

crsctl disable crs
      disables automatic start of clusterware daemons  

crsctl add css votedisk path
     add a vote disk

crsctl delete css votedisk path
     remove voting disk
crsctl check crs
    status of the crs  

 crsctl check cssd

crsctl check crsd

crsctl check evmd

crsctl check cluster

crsctl query crs softwareversion

crsctl query crs activeversion


Check Inventory

./opatch lsinventory
    ** view inventory using Opatch

cat /etc/oraInst.loc|grep inventory_loc 
     ** to find the location of the inventory

cat /opt/app/oraInventory/ContentsXML/inventory.xml
     ** View inventory without using Opatch












Skipping Users In Logical Standby

Logical standby's have their place for reporting requirements. They do require their own special attention. Logical standby's are generally used to fulfill a reporting requirement which would only cause performance issues in the production instance. However, not everything needs to be replicated to the logical standby. Individual users who have access to production environments and can create objects are one type of events that can be skipped. If they are creating objects and data with a requirement to replicate, that's a whole other issue. When we create a user in a production environment it will be replicated to the logical standby, however, we do not want their objects or the data to be replicated from production to the logical standby. So we issue the following with each user create:  
ALTER database stop logical standby apply; 
EXECUTE DBMS_LOGSTDBY.SKIP(stmt =>'DML',schema_name => 'NewUser',object_name => '%'); 
EXECUTE DBMS_LOGSTDBY.SKIP(stmt =>'SCHEMA_DDL',schema_name => 'NewUser',object_name => '%');
 alter database start logical standby apply immediate;
 **Note Substitute the actual user for NewUser.

The key is to remember to do this when each user is created. Or have an automated process that will trigger these command on the logical standby.

RMAN register several archivelogs

From time to time physical standbys get out of sync. The apply process stops working, and the gap fetch doesn't seem to fetch the missing archive logs from the primary. So a manual move of the archives to the primary has to occur -- unless the gap is too large then it would be easier to just perform an incremental backup, but that's another post. Once the archives have been moved to the appropriate directory on the standby, they have to be registered.

 >ALTER DATABASE REGISTER LOGFILE '/home/oracle/archives/orcl/1_19526_676899244.arc';

This will be displayed in the alert log and Media Recovery will apply the log. The messages will look like:
 alter database register logfile '/home/oracle/archives/orcl/1_19526_676899244.arc' 

There are 1 logfiles specified. 

ALTER DATABASE REGISTER [PHYSICAL] LOGFILE Completed: 
alter database register logfile '/home/oracle/archives/orcl/1_19526_676899244.arc'

The process works great when dealing with only a handful of archive logs. There is a better way to register an entire directory of logs with RMAN.
1. rman target / nocatalog -- log in to rman which would be appropriate to your environment.
2. CATALOG START WITH '/home/oracle/archives/orcl -- provide the directory that contains the archive logs to register. ** Be Careful if you have an archive log from a different incarnation this could be problematic as it will be registered and applied.
3. RMAN will then review the directory and any files not registered will be listed to register and you will be prompted:  

Do you really want to catalog the above files (enter YES or NO)? 4. YES -- If the listing looks appropriate.

Oracle will then register the archive logs and report any that could not be registered. Any files that are not archive logs will not be registered and will be listed as corrupted. Once finished the Media Recovery will begin picking up the archive logs and applying.

Determine Queries Temporary Space Requirement

If you are ever in the situation where someone doesn't want to add disk space to the temporary tablespace without having the specifics as to exactly how much space is required. There are two events that can be set that will provide this information.

The key is that you will actually need to run the query in question in order to get all the sort information required.

alter session set events '10032 trace name context forever';
alter session set events '10033 trace name context forever';

10032 will provide all the sort information to include the total amount of records input and output as well as the total amount of space required.:


10033 will provide the details of the sort run to include the block address and the number of blocks. At the end it will total the blocks used for all the sorts. This total number will be the amount of disk space required for this query with this data set.

Both of these traces express the disk space required in blocks, so make sure you multiple that number by the block size of the database.

Saturday, July 3, 2010

Key To Troubleshooting Global Cache Waits

I returned from vacation a few weeks ago to a serious performance issue that had hampered processing by at least 75% overall. Some processing wasn't impacted.

I read through all the email threads theorizing that the problem was the redo switching.

I pulled up the gv$session looking keying on the minimum information to see what Oracle was telling us through the wait interface. I was floored the Global Cache Waits were significantly high, processes weren't moving through the GC. I confirmed by running some AWR reports over different time periods since the issue was first reported.

I sent an email explaining my findings using the wait interface, and then discounted the redo switching since we were not seeing any waits for Archiver, Log Writer or any other background process on log waits. There were background processes that waited on GC waits.

I explained to the team that Oracle will tell you what is slowing processing down if you just listen to the wait interface. It won't give you the root cause but it will tell you where to start looking. And even though we were switching frequently, we weren't waiting on the switch to occur and therefore that was not the area to concentrate efforts.

Another theory was sent out that the Interconnect was probably suffering because some of reference tables were cached on one of the old nodes that was no longer being used by the application (we are actually preparing to remove it from the cluster). The theory was that the blocks were remaining on the instance and all the other instances had to always go to that instance to retrieve the blocks. A perfect example of how global cache does not work. I explained how the buffer cache worked and that the blocks would actually be pulled over to the requesting instance and the touch count incremented.

I also explained that it didn't appear we were saturating the Interconnect by the amount of traffic that was trying to be pushed across, but we were experiencing block lost, according to the wait interface.

I took the additional step in disproving the theory by caching data on one of the other instances, and then pulling the data over to one of the other instances. Checking the waits -- Global Cache Waits.

Another theory was raised that because we did a lot of full table scans (FTS) and our multi-block read count was high (16K), that this was why we were experiencing the waits. Because on Metalink there was a note that OS settings may need to be adjust under these circumstance. In particular the UDP buffers, but ours were already at 256K. We have always had a 16K MBR count. So what changed? Did the workload actually start soaring? Were we saturating the bandwidth of the Interconnect?

The network and linux administrator were instructed to start checking the OS and hardware. As well as, I requested all of the changes that went into the database, OS or hardware prior to the waits issue.

In the meantime, the theory of the instance buffer cache kept surfacing from individuals that really didn't have an understanding of how buffer cache or global cache fusion worked. So I decided the easiest way to demonstrate was to shutdown the node. Which I did... and the results were not exactly what I wanted.

The entire cluster started having issues as nodes were evicted.

Things proceeded to get worse. As we tried to bring up the individual nodes they experienced reconfiguration issues and would keep rebooting. After about an hour of the new DBA on the block struggling I realized the issue..... THE SWITCH WAS BAD! Then I started with admonishing myself for not realizing it from the onset of the issue.

I immediately began explaining my ah ha moment. The nodes were having problem reconfiguring and staying in the cluster because they were having trouble communicating across the Interconnect. The Interconnect being nothing more than 8 Cat 5 wires plugged into a 48 port Netgear switch (yes I know not exactly a stellar setup but you learn to make due with what you have at the moment). The chances of all 8 wires going bad was slim, but the switch a definite could happen. Everyone thought I was insane and said switches don't go bad. I differed with them based on my husband managing a team of network engineers who dealt with switches going bad all the time. They are after all nothing more than electronics and they too can over heat, have cards go bad just like any other electronics.

We decided to bring up one node at time and let it come all the way up with the database, before we started the next node. And my boss wanted us to make sure that we didn't bring up the old nodes at all. We obliged, after all by this point I was fairly certain what the outcome would demonstrate. After node one was up we brought up Grid so that we could have an instant picture for assessment. The second node came up and there were the cluster waits. The only activity that was occurring was the opening of the database and then just the background processes. The cluster waits were noticeably high, to those of us who had a mental baseline of what they should be at this time under normal circumstances. We introduced the third node and the waits shot up more. We then started getting Inbound Connection Timeouts on the third node. We made a collective decision to bring down the node.

Not having a spare switch on hand (long story), we decided to grab a little 6 port 100mb switch. Made the swap with the two active node, and the Global Cache Waits pretty much disappeared. Since only half the bandwidth was being used, we decided to experiment and see what would happen if we brought up the third node.

Unfortunately, since we only had 100mb switch and the traffic pushed to just over 90mb with the third node we were saturating the bandwidth. We needed to back off of using the third node until we could be procure a Gig switch. Which we did the next day.

With the new switch in place the Global Cache Waits returned to normal. Block lost were a thing of the past.

The one thing that I came out of this fire fighting activity is to not make troubleshooting more difficult. Think through what comprises the waits in question and remember to include the hardware in the assessment. For Global Cache Waits if you have been cruising right along without any issues and then all of sudden the waits soar chances are that the issue isn't with the database or RAC, but with the Interconnect.