Tilgang til Oracle via Perl (Del 2)

Tilgang til Oracle via Perl (Del 1)

I del 1 så vi på konfigurasjon av Perl, og kjørte en liten Perl snutt. Nå skal vi se videre på hvordan vi kan koble til en Oracle instans. Vi skal også se på hvordan vi enkelt kan opprette to koblinger mot samme database, eller to koblinger mot to ulike databaser. Begge disse tilkoblingsmuligheten åpner for en del fine ting.

La oss først se på hvordan vi kan opprette en enkel kobling mot en Oracle instans, og kjøre en enkel spørring:

#Script simple_connect.pl
use DBI;            # Load the DBI module
use strict;

my ($dbh, $sth, @row); # Define variables 

### Perform the connection using the Oracle driver
$dbh = DBI->connect( "dbi:Oracle:ORCL.EDB.COM", "lj", "lj" )
    or die "Can't connect to Oracle database: $DBI::errstr\n";

### Prepare a SQL statement for execution
$sth = $dbh->prepare( "SELECT user FROM dual" );

### Execute the statement in the database
$sth->execute(  );
### Fetch row
@row = $sth->fetchrow_array(); 
### Print username connected
printf ("Connected as: %s\n",$row[0]);

$sth->finish;
$dbh->disconnect;
exit;
####### Output #########
oracle@ubuntu:$ perl simple_connect.pl
Connected as: LJ

Først laster vi databasebase modulen med “use DBI;”. “use strict;” tvinger oss til å definere våre variabler med “my”-kommandoen. Derfor deklarer vi de variablene som vi trenger – “my ($dbh, $sth, @row);”. Perl kaller de to første variablene for skalar variabler ($dbh, $sth). Så deklarer vi en array av referanser (@row).
Så setter vi opp en forbindelse (connection) mot databasen:

$dbh = DBI->connect( "dbi:Oracle:ORCL.EDB.COM", "lj", "lj" )
    or die "Can't connect to Oracle database: $DBI::errstr\n";

Hvis forbindelsen feiler vil programmet avsluttet. Dette defineres med “die” kommandoen.
Hvis vi nå kobler til som DBA og sjekker v$session vil vi se forbindelsen mot databasen

-- her kommer mer -- (beklager ... rekker ikke dette før i kveld).

Så klargjør vi et prepared statement.

$sth = $dbh->prepare( "SELECT user FROM dual" );

Dette kan vi også se som SYSDB i v$sql:

-- her kommer mer -- (beklager ... rekker ikke dette før i kveld).

Så kjører vi spørringen vår mot databasen:

$sth->execute(  );

Dette betyr at vi åpner en cursor i databasen, og står klare for å hente ut aktuelle rader. Dette gjør vi med en “fetch”:

@row = $sth->fetchrow_array(); 

Som jeg nevte over kan vi også reletivt lett koble opp flere sesjoner mot enten samme eller ulike databaser.
Under oppretter jeg tre koblinger mot samme database, men prinsippet er et samme om du kobler til ulike database instanser:

# Script: twice_same_db.pl
# Description:      Connects to two Oracle databases simultaneously.
#                   We see two sessions in the instance.

use DBI;            # Load the DBI module
use strict;         # Must then declare with "my"

my ($SID, $USER, $PASS, $SUSER, $SPASS)=("ORCL","lj","lj","system","man");

### Perform two connections using the Oracle driver
my $dbh1 = DBI->connect( "dbi:Oracle:${SID}", "${USER}", "${PASS}" )
    or die "Can't make 1st database connect: $DBI::errstr\n";
my $dbh2 = DBI->connect( "dbi:Oracle:${SID}", "${SUSER}", "${SPASS}" )
    or die "Can't make 2nd database connect: $DBI::errstr\n";

### Prepare a SQL statement for execution
my $sth = $dbh2->prepare(q{
SELECT sid, serial#, username, program FROM v\$session WHERE lower(program) like '%perl%'" );
});

$sth->execute(); # EXECUTE

### Retrieve the returned rows of data
while ( my @row = $sth->fetchrow_array(  ) ) {
  print "Row: @row\n";
}
  warn "Data fetching terminated early by error: $DBI::errstr\n"
      if $DBI::err;
exit;
####### Output #########
oracle@ubuntu:$ perl twice_same_db.pl 
Row: 36 5463 LJ perl@ubuntu (TNS V1-V3)
Row: 128 17523 SYSTEM perl@ubuntu (TNS V1-V3)

Av og til når vi skal test ut eller analysere hvordan Oracle fungerer, har vi behov for å kjøre SQL-er mot data dictionary, samtidig som et test skript kjører. Dette kan være vanskelig å få til manuelt. I stedet kan vi lage et perl skript som kjører i en evig løkke, og kaller vår spørring f.eks. hvert sekund.
Her er et lite eksempel:

# Scipt: monitor_forever.pl
use DBI;
use strict;

my ($SID, $USER, $PASS)=("ORCL","system","man");

my $dbh = DBI->connect("dbi:Oracle:${SID}","${USER}","${PASS}",{ RaiseError=>1,AutoCommit =>0 })
   || die "Database connection not made: $DBI::errstr\n";

my $sth = $dbh->prepare(q{
SELECT sid, to_char(sysdate,'mi:ss') time, round(work_area_size/1048576, 1) work_area_size_mb, 
           round(max_mem_used/1048576, 1) max_mem_used_mb, number_passes, 
           nvl(tempseg_size/1048576, 0) tempseg_size_mb
FROM v$sql_workarea_active 
ORDER BY sid
});
my $format="%5s %5s %14s %12s %6s %12s\n";
printf($format, "SID", "TIME", "WORK_AREA_SIZE", "MAX_MEM_USED", "PASSES", "TEMPSEG_SIZE");
for (;1!=2;) {
        $sth->execute;
        while ( my @row = $sth->fetchrow_array ) {
                printf($format, $row[0], $row[1], $row[2], $row[3], $row[4], $row[5]);
        }
        sleep 1;
}
$dbh->disconnect;
exit;
####### Output #########
oracle@ubuntu:$ perl monitor_forever.pl 
  SID  TIME WORK_AREA_SIZE MAX_MEM_USED PASSES TEMPSEG_SIZE

Spørringen mot v$sql_workarea_active vil bli kjørt hvert sekund. Så lenge spørringen ikke finner data, vil heller ikke noe bli skrevet ut. Hvis vi kjører en litt større spørring, vil vi se at det begynner å skje noe:

SQL> select object_id, object_name from all_objects where rownum<=15000 order by created;
...
15000 rader valgt.

Da ser vi at monitorerings programmet vårt starter å fange opp data:

oracle@ubuntu:/data/books/Secrets_of_the_Oracle_db/my_source$ perl monitor_forever.pl 
  SID  TIME WORK_AREA_SIZE MAX_MEM_USED PASSES TEMPSEG_SIZE
  156 30:11             ,8           ,8      0            0
  156 30:11              4          1,5      0            0
  156 30:11              3          1,2      0            0

Monitorerings programmet vårt går i en evig løkke, og vil ikke stoppe før vi terminerer det.
Følgende ble kjørt i et annet konsoll:

root@ubuntu:~$ ps -ef | grep perl
oracle    3112     1  0 Mar28 ?        00:00:14 /u01/app/oracle/product/11.2.0/dbhome_1/perl/bin/perl /u01/app/oracle/product/11.2.0/dbhome_1/bin/emwd.pl dbconsole /u01/app/oracle/product/11.2.0/dbhome_1/localhost_ORCL/sysman/log/emdb.nohup
ek2046    6143  6120  0 23:09 pts/8    00:00:00 grep --color=auto perl
oracle   25748 16631  0 19:51 pts/7    00:00:02 perl monitor_forever.pl
root@ubuntu:~# kill -9 25748
root@ubuntu:~#

Den første kommandoen (ps -ef | grep perl) ser vi returnerer tre linjer. Denne ene "grep --color=auto perl" er vår egen grep kommando. Den andre (perl monitor_forever.pl) er den prosessen vi ønsker å terminere. I tillegg ser vi en annen perl prosess som kjører under $ORACLE_HOME. Dette er DBConsole-et, dvs Enterprise Manager, som benytter diverse perl skript. Hvorfor tror du Oracle selv har valgt å bruke Perl i sine produkter?

Hvis vi nå vender tilbake til konsolet der vi kjørte vårt perl program (monitor_forever.pl), ser vi at prosessen er blitt terminert:

oracle@ubuntu:~$ perl monitor_forever.pl 
  SID  TIME WORK_AREA_SIZE MAX_MEM_USED PASSES TEMPSEG_SIZE
  156 30:11             ,8           ,8      0            0
  156 30:11              4          1,5      0            0
  156 30:11              3          1,2      0            0
Killed
oracle@ubuntu:~$ 

Post a Comment

Your email is never published nor shared. Required fields are marked *