Blog Aggregator - Amardeep Sidhu

  • Tags

  • Archives

  • Meta

  •  

    February 2008
    M T W T F S S
    « Jan   Mar »
     123
    45678910
    11121314151617
    18192021222324
    2526272829  

Archive for February 7th, 2008

07 Feb

Scoping with SQL Types

The scoping rules for function calls are quite clear. Given a package with a function which has the same name as a standalone function, another function in that package will call the packaged function not the standalone one:

SQL> create or replace function toto   2      return varchar2   3  as  4  begin  5      return ‘TOOTING’;  6  end toto;  7  /

Function created.

SQL> create or replace package a as  2      function toto return varchar2;  3      function tata return varchar2;  4  end a;  5  /

Package created.

SQL> create or replace package body a as  2      function toto return varchar2   3      as  4      begin  5          return ‘KANSAS’;  6      end toto;  7      function tata return varchar2   8      as  9      begin 10          return ‘We”re not in ‘||toto||’ anymore’; 11      end tata; 12  end a; 13  /

Package body created.

SQL> select a.tata from dual  2  /TATA———————————–We’re not in KANSAS anymore

SQL> 

The rules apply the same way if we’re working with an object rather than a package ….

SQL> drop package a  2  /

Package dropped.

SQL> create or replace type a as object (  2      attr1 varchar2(20)  3      , member function toto return varchar2  4      , member function tata return varchar2  5  ) NOT FINAL;  6  /    

Type created.

SQL> create or replace type body a as   2      member function toto return varchar2   3      as  4      begin  5          return attr1;  6      end toto;  7      member function tata return varchar2   8      as  9      begin 10          return ‘We”re not in ‘||toto||’ anymore’; 11      end tata; 12  end; 13  /

Type body created.

SQL> set serveroutput onSQL> declare   2      my_a a := new a(’KANSAS’);  3  begin  4      dbms_output.put_line(my_a.tata);  5  end;  6  /We’re not in KANSAS anymore

PL/SQL procedure successfully completed.

SQL> 

However, there is a gotcha: the scoping rules do not work that way when our type inherits from a super-type….

 SQL> create or replace type b under a (  2      overriding member function tata return varchar2  3  );  4  /    

Type created.

SQL> create or replace type body b as   2      overriding member function tata return varchar2   3      as  4      begin  5          return ‘We”re not in ‘||toto||’ anymore!!!’;  6      end tata;  7  end;  8  /

Type body created.

SQL> declare   2      my_b b := new b(’KANSAS’);  3  begin  4      dbms_output.put_line(my_b.tata);  5  end;  6  /We’re not in TOOTING anymore!!!

PL/SQL procedure successfully completed.

SQL> 

The solution is quite straightforward: use the SELF keyword to make the scope explicit.

SQL> create or replace type body b as   2      overriding member function tata return varchar2   3      as  4      begin  5          return ‘We”re not in ‘||SELF.toto||’ anymore!!!’;  6      end tata;  7  end;  8  /

Type body created.

SQL> SQL> declare   2      my_b b := new b(’KANSAS’);  3  begin  4      dbms_output.put_line(my_b.tata);  5  end;  6  /We’re not in KANSAS anymore!!!

PL/SQL procedure successfully completed.

SQL> 

I admit I am not clear about the rules for using SELF. Sometimes it is compulsory, sometimes it is optional. So it’s just easier to always include it whenever we reference anything inside a type body.

NB: I ran these tests on 9.2.0.6, if that makes any difference.

07 Feb

Cary Millsap is blogging

If you work with Oracle databases and are interested in system performance, then you probably want to know what Cary Millsap has to say. So, make sure you bookmark his blog: http://carymillsap.blogspot.com/

07 Feb

SQL*Net message to client wait isn’t really what it’s thought to be

In a recent Oracle Forum thread a question came up how to use SQL*Net message to client wait events for measuring network latency between server and client. The answer is that you can’t use it for network latency measurements at all, due how TCP stack works and how Oracle uses it.
I’ll paste my answer here […]

07 Feb

Why the command line rocks…

because when you own it, you own the world.  You can literally do anything you want (given you have that privilege of course)…

Check this out.  Neat eh.

Control the command line and nothing will ever control you.  You have to understand something before you can do that stuff.

Besides, ASCII art is universal… (ctl-f for "A standard confirm")

 

ops$tkyte%ORA10GR2> CREATE TABLE hash_example  2  ( hash_key_column   date,  3    data              varchar2(20)  4  )  5  PARTITION BY HASH (hash_key_column)  6  ( partition part_1 ,  7    partition part_2 ,  8    partition part_3 ,  9    partition part_4 10  ) 11  /

Table created.

ops$tkyte%ORA10GR2> insert into hash_example  2  select sysdate+rownum, ‘x’  3    from all_objects  4   where rownum <= 10000;

10000 rows created.

ops$tkyte%ORA10GR2>ops$tkyte%ORA10GR2> select pname, cnt,  2         substr( rpad(’*',30*round( cnt/max(cnt)over(),2),’*'),1,30) hg  3    from  4  (  5  select uo.subobject_name pname, count(*) cnt  6    from user_objects uo, hash_example he  7   where uo.data_object_id = dbms_rowid.rowid_object(he.rowid)  8   group by uo.subobject_name  9  ) 10  order by pname 11  /

PNAME                                 CNT HG—————————— ———- ——————————PART_1                               2398 ***************************PART_2                               2466 ****************************PART_3                               2563 ******************************PART_4                               2573 ******************************
07 Feb

Are Virtual IPs required for Data Guard?

Until 10.2.0.3, the Data Guard (and broker) technology suffered from several weaknesses. One of the "highlights" was that no Virtual IP management was provided by Oracle. This has quite important consequences for the clients as soon as the primary server is down (no IP responding to the TCP requests e.g. of a connection build up). In this case, the failover from the first to the second address (in the address list of the TNS entry used by the client) could take a long time, depending on network/TCP timeouts. The RAC/Clusterware architecture solved this issue by introducing the Virtual IPs (VIP) which where always available (maybe moved to a surviving node).

 

Of course several solutions are available to overcome that problem, for instance managing your own VIP with self-made scripts (and all the subsequent risks, you try to fake a failover cluster!), combine Data Guard with  Failover Cluster technology (e.g. Heartbeat under Linux, Veritas Cluster Services), and so on …

 

All that solutions have as almost as many  drawbacks as advantages, the most important are:

 

- How can we garantee that the VIP is always started on the Primary database side?

- How is it possible to prevent two Virtual IP running in parallel in the cluster?

 

However, one of the mentioned solutions is almost "mandatory" for Oracle clients before 10.2.0.3.

 

Starting with 10.2.0.3 on client and server side, Oracle proposes the OUTBOUNT_CONNECT_TIMEOUT parameter (not very well documented though). This option must be set in the sqlnet.ora file and defines the maximum number of seconds to be waited before trying to access the second, third etc. address in the ADDRESS_LIST, independent of TCP/IP timeouts. Examples:

 

In sqlnet.ora:

OUTBOUND_CONNECT_TIMEOUT=5

 

In tnsnames.ora on the client side or in the LDAP server:

PCMDB =

  (DESCRIPTION =

   (ADDRESS_LIST=

    (ADDRESS = (PROTOCOL = TCP)(HOST = server1 )(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST = server2 )(PORT = 1521))

   )

    (CONNECT_DATA =

      (SERVICE_NAME = PCMDB_RW )

    )

  )

 

PCMDB_RW is a service created beforehand and activated through a "startup database" trigger (see end of the post). This makes sure, that the client can only connect to the primary side. If after 5 seconds (in our case), server1 is still unreachable, the client will try to connect to server2 (ignoring existing TCP/IP parameters).

 

Unfortunately, during our tests we observed that this parameter requires the remote_listener parameter to be set on the server side, at least for Linux/Sun(/… ?) clients. This for the non-error situation that a client first tries the standby database (and therefore should failover to the primary). For windows clients, patch 6038241 (10.2.0.3.7P) can be installed (only available for 32 Bit), see metalink note 342443.1. With this patch, the remote_listener parameter does not have to be.

 

So the Windows clients have a valid/stable solution using the patch.

 

The Linux clients however suffer from the side effects of the remote_listener parameter: The remote_listener parameter is used to register to other (remote) listeners in order to inform them about the current instance load. This means that in case of crash of the primary server and activation of the standby database, the service PCMDB_RW is known by the listener of the standby side as being offered by the new primary (ok) and the old primary (not ok)!

 

This situation may result in "ORA-12560: TNS:protocol adapter error" errors.

 

The solution is quite simple: the listener should be "reloaded" on the new primary side (old standby) when the standby database becomes the primary. This could be easily automated with a script and a DB_CHANGE_ROLE trigger. See the code below :

 

Script to reload the listener:

#!/bin/ksh

# Set the ORACLE environment variables (ORACLE_HOME, PATH, aso …)

lsnrctl reload LISTENER_PCMDB

 

Below the trigger to reload the listener:

CREATE OR REPLACE TRIGGER RELOAD_LISTENER AFTER DB_ROLE_CHANGE ON DATABASE

BEGIN

dbms_scheduler.create_job(job_name=>'reload_lsn',job_type=>'executable',job_action=>'/u00/app/oracle/local/custom/bin/reload_lsn_PCMDB.ksh',enabled=>TRUE);

END;

/

 

With this solution, both Linux and Windows clients do not require any VIP or Failover Cluster anymore to fully benefit from a Data Guard architecture. The only 'restriction' is to use 10.2.0.3 Oracle client releases. Even 10.2.0.2 does not work properly. Of course, wait for 10.2.0.4 and hope that the "problem" is fixed could be another solution :-)

 

Appendix : startup trigger for "_RW" service :

create or replace trigger service_trigger after

startup on database

declare

db_name       varchar(512);

db_domain     varchar(512);

database_role varchar(16);

service_names varchar(512);

instance_name varchar2(16);

begin

  select value into service_names from v$parameter where name = 'service_names';

  select value into instance_name from v$parameter where name = 'instance_name';

  select value into db_name from v$parameter where name = 'db_name';

  select value into db_domain from v$parameter where name = 'db_domain';

  select database_role into database_role from v$database;

  if database_role = 'PRIMARY' then

    service_names := rtrim(service_names || ', ' || db_name || '_RW.' || db_domain, '.');

  else

  service_names := rtrim(service_names || ', ' || db_name || '_RO.' || db_domain, '.');

  end if;

  execute immediate 'alter system set service_names = ''' || service_names || ''' scope=memory sid=''' || instance_name || '''';

end;

/

 

07 Feb

Building a Stretch Real Application Clusters Configuration? Get The CRS Voting Disk Setup Right!

The topic of “stretch clusters” has been interesting to a lot of folks for quite some time. A stretch cluster is one where one or more cluster nodes, one of more portions of the SAN or both are geographically remote. Geographically remote could be within eye-sight (1-2km) or a long distance away. YottaYotta (Robin […]

© 2008 Blog Aggregator - Amardeep Sidhu | Entries (RSS) and Comments (RSS)

Powered by Wordpress, design by Web4 Sudoku, based on Pinkline by GPS Gazette