DB2 ist ein Produkt der
IBM Corporation. Bitte Copyright- und Trademark-Hinweise beachten!
#!/usr/local/bin/perl -w
################################################################################
# xmpTBSCReStmt.pl - Generate Tablespace/Containter SQL Statements
# Called by - Command Level oder DBA Scripts
# Calls - xmpPerl.pm - xmp DBA Perl Package
# Getopt - Argument Verwaltung
# Env - Zugriff auf Umgebungsvariablen
# English - Aliase für Perl Variablen
# Optionen - xmpTBSCReStmt.pl -d databaseDatenbank-Name
# -u user -p psw User und Password
# -f file File für Statement Generierung
# -t CREATE|RESTORE
# -s CURRENT|HWM Size: Current Alloc or High Water Mark
# -g nn Plus nn % growth
#-------------------------------------------------------------------------------
# Autor - GR /28.03.01 - V1.0 erste Version, kopiert aus xmpTBSCList.pl
# Changes - GR /16.05.01 - V1.1 Zugriff auf Catalog für BPool und Korrekturen,
# z.B. für Berechnung HWM Page Sizes
# GR /16.05.01 - V1.2 HWM Page Size zuzügl. Minimum Requirements
# GR /06.07.01 - V1.3 neuer Parm -g nn für Wachstum
# GR /02.11.01 - V1.4 Mehr Hinweise in erzeugtes Script schreiben
#-------------------------------------------------------------------------------
# Comments - PERL5LIB Environment Variable muss auf Perl Module Pfad zeigen!
################################################################################
################################################################################
# Modules
################################################################################
use strict;
use Getopt::Std;
use vars qw($opt_d $opt_u $opt_p $opt_f $opt_t $opt_s $opt_g);
use xmpPerl;
use Env;
use English;
use DBI;
use DBD::DB2::Constants;
use DBD::DB2;
################################################################################
# Declare/Init
################################################################################
my $VER = "1.4";
my $work = "";# for TS List
my @work;# for TS List
my $work2 = "";# for Container List
my @work2;# for Container List
my ($dbh, $sth);# DB2 Access Handles
my $stmt= "";
my $var;
my $val;
my $id;
my $ts= 0;# no. of Tablespaces
my %ts_id= (); my $f1;# Tablespace Structure
my %ts_name= (); my $f2;
my %ts_type = (); my $f3;
my %ts_content = (); my $f4;
my %ts_state = (); my $f5;
my %ts_pgtotal = (); my $f6;
my %ts_pguseable= (); my $f7;
my %ts_pgused = (); my $f8;
my %ts_pgfree = (); my $f9;
my %ts_pghwm = (); my $fe;# High Water Mark
my %ts_pgsize = (); my $fa;
my %ts_extsize = (); my $fb;
my %ts_pfsize = (); my $fc;
my %ts_container= (); my $fd;
my $tsc= 0;# no. of Containers
my %tsc_tsid= (); #$f1# Tablespace ID
my %tsc_id = ();#$f2# Container ID
my %tsc_name = ();#$f3# Container Name
my %tsc_type = ();#$f4
my %tsc_pgtotal = ();#$f5
my %tsc_pguseable=();#$f6
my %tsc_pgaccess=();#$f7
my %tsc_tsname = ();#$f8# Tablespace Name
my $ts_total_total = 0;# Current Total Allocation
my $ts_total_hwm = 0;# HWM Allocation
my $ts_total_new= 0;# new to allocate
my $hFile;# File Handle
my $pagemin = 0;# Min. no. of pages
my $bpool = "";# Bufferpool Name
my ($rest1,$rest2) = ""; # Add. Attributes
################################################################################
# Argumente/Options prüfen
################################################################################
getopts("d:u:p:f:t:s:g:");
if (! defined $opt_d )# Datenbank Check
{print "$0 - Datenbank nicht angegeben\n";
SaySyntax();
}
if (! defined $opt_u )# User Check
{$opt_u = xmpPerl::getDBAUser();
if ($opt_u eq "")
{print "$0 - User nicht angegeben und keine lP_LUS Variable definiert\n";
SaySyntax(); }
}
if (! defined $opt_p )# User Password Check
{$opt_p = xmpPerl::getDBAPsw();
if ($opt_p eq "")
{print "$0 - User's Password fehlt und keine lP_LPW Variable definiert\n";
SaySyntax(); }
}
if (! defined $opt_f )# File für Statement Generierung
{print "$0 - File für Generierung des Statements fehlt\n";
SaySyntax();
}
if (! defined $opt_t )# Type
{$opt_t = "RESTORE";
}
if (! defined $opt_s )# Size = Current Allocation Size
{$opt_s = "CURRENT";
}
$opt_d = uc $opt_d;
$opt_s = uc $opt_s;
$opt_t = uc $opt_t;
if (($opt_t ne "RESTORE")& ($opt_t ne "CREATE") ) {
print "$0 - Type invalid, please choose either CREATE or RESTORE!\n";
SaySyntax();
}
if (($opt_s ne "CURRENT")& ($opt_s ne "HWM") ) {
print "$0 - Options -s invalid value, use CURRENT or HWM only!\n";
SaySyntax();
}
if (! defined $opt_g )# Growth Percentage
{$opt_g = 0;
}
if (($opt_g < 0) | ($opt_g > 1000) ) {
print "$0 - Option -g invalid value, use 0 - 1000 only!\n";
SaySyntax();
}
################################################################################
# Check DB2 Existenz und Informationsblock ausgeben
################################################################################
xmpPerl::chkDB2();
xmpPerl::prtHeaderDB2("$0 - Generierung Tablespace Statements - V$VER");
print "Database / DB2 User ID ......: $opt_d / $opt_u";
################################################################################
# DB2 Connect zur Datenbank
################################################################################
$work = xmpPerl::doCmdOut("db2 connect to $opt_d user $opt_u using $opt_p ");
if ($work =~ "Connection Information")
{print " (Connect erfolgreich)\n";}
else
{die ">>>Kann keine Verbindung zur Datenbank $opt_d mit User $opt_u herstellen\n".
">>>Meldung: $work\n".
">>>ABEND";}
print "File for generated statement : $opt_f\n";
print "Type of generation ..........: $opt_t\n";
print "Object Size to consider .....: $opt_s\n";
print "Percentage Object Growth ....: $opt_g (0=not expanding)\n";
################################################################################
# DB2 List Commands ausführen
################################################################################
$work = xmpPerl::doCmdOut("db2 list tablespaces show detail");
undef $/;
@work = split("\n",$work);
#print "$#work lines returned from DB2 List Tablespace Command.\n";
foreach $work (@work) {
($var,$val) = split("=",$work);
if (! defined $var) {$var = "";}
if (! defined $val) {$val = "";}
$var = uc xmpPerl::trim($var);
$val = uc xmpPerl::trim($val);
########################################################################
# Korrektur erforderlich, wenn Utility Pending (z.B. Load vorher abgebr.)
########################################################################
if ($var =~ "CHANGE"){
$var = "";
$val = "";
}
#if ($var ne "" || $val ne "") {
#print "$var\t$val\n";
#}
########################################################################
# Beginn eines neuen Tablespace-Blocks
########################################################################
if ($var =~ "TABLESPACE ID"){
################################################################
# Tablespace Nummer erfassen
################################################################
##$ts++;
$ts = $val;
$ts_id{$ts} = $val;# neue TSpace ID
#print "Neuer TS $var $val\n";
}
#######################################################################
# andere Suchbegriffe
#######################################################################
if ($var =~ "NAME") {
$ts_name{$ts} = $val;
################################################################
# Container Infos anfordern
################################################################
$f1 = $ts_id{$ts};
$f2 = "db2 list tablespace containers for $f1 show detail";
#print "TS-ID=$f1\n";
$work2= xmpPerl::doCmdOut($f2);
#print "$work2\n";
@work2 = split("\n",$work2);
#print "$#work2 lines returned from DB2 List Container Command.\n";
foreach $work2 (@work2) {
($var,$val) = split("=",$work2);
if (! defined $var) {$var = "";}
if (! defined $val) {$val = "";}
$var = uc xmpPerl::trim($var);
$val = xmpPerl::trim($val);
#$val = uc xmpPerl::trim($val);
if ($var =~ "CONTAINER ID") {
$tsc++;
$tsc_tsid{$tsc} = $f1;# Tablespace ID
$tsc_id{$tsc} = $val;# neue Container ID
$tsc_tsname{$tsc} = $ts_name{$ts} # TS Name
}
if ($var =~ "NAME"){$tsc_name{$tsc} = $val}
if ($var =~ "TYPE") {$tsc_type{$tsc} = uc $val};
if ($var =~ "TOTAL"){$tsc_pgtotal{$tsc}= $val}
if ($var =~ "USEABLE"){$tsc_pguseable{$tsc}= $val}
if ($var =~ "ACCESS"){$tsc_pgaccess{$tsc}= uc $val}
}
}
#######################################################################
# Und der Rest der anderen Suchbegriffe
#######################################################################
if ($var =~ "TYPE") {
if ($val =~ "SYSTEM") {$ts_type{$ts} = "SMS"};
if ($val =~ "DATA") {$ts_type{$ts} = "DMS"};
}
if ($var =~ "CONTENTS") {
$ts_content{$ts} = uc $val;
if ($val =~ "ANY") {$ts_content{$ts} = "REGULAR"}
if ($val =~ "TEMP") {$ts_content{$ts} = "TEMPORARY"}
if ($val =~ "LONG") {$ts_content{$ts} = "LONG"}
}
if ($var =~ "STATE"){$ts_state{$ts} = $val}
if ($var =~ "TOTAL") {$ts_pgtotal{$ts} = $val}
if ($var =~ "USEABLE") {$ts_pguseable{$ts} = $val}
if ($var =~ "USED") {$ts_pgused{$ts} = $val}
if ($var =~ "FREE") {
if ($val =~ "NOT APPLIC") {
$ts_pgfree{$ts} = "N/A"}
else {$ts_pgfree{$ts}= $val}
}
if ($var =~ "HIGH WATER"){
if ($val =~ "NOT APPLIC") {
$ts_pghwm{$ts} = $ts_pgtotal{$ts} }
else {$ts_pghwm{$ts} = $val }
}
if ($var =~ "PAGE SIZE") {$ts_pgsize{$ts} = $val/1024}
if ($var =~ "EXTENT") {$ts_extsize{$ts} = $val}
if ($var =~ "PREFETCH") {$ts_pfsize{$ts} = $val}
if ($var =~ "CONTAINERS"){$ts_container{$ts} = $val}
}
################################################################################
# DB2 Connection abbauen
################################################################################
$work = xmpPerl::doCmdOut("db2 connect reset");
################################################################################
# File für Statements öffnen, falls vorhanden
################################################################################
if (! open(hFile, "> $opt_f") )
{ die "$0 kann nicht in $opt_f schreiben. \n".
"abends";
}
################################################################################
# Create Header for Redirected RESTORE DATABASE Statement
################################################################################
if ($opt_t eq "RESTORE" ) {
print hFile "UPDATE COMMAND OPTIONS USING S ON Z ON $opt_f.out V ON;\n";
print hFile "SET CLIENT ATTACH_NODE 0;\n";
print hFile "SET CLIENT CONNECT_NODE 0;\n";
$work = xmpPerl::getTimestamp();
print hFile "ECHO \@---------------------------------------------------------\@;\n";
print hFile "ECHO \@Script created ........: $work \@;\n";
print hFile "ECHO \@Script File ...........: $opt_f \@;\n";
print hFile "ECHO \@Database to be restored: $opt_d (Redirected Restore) \@;\n";
print hFile "ECHO \@Database Object Sizing : $opt_s plus $opt_g\% growth \@;\n";
print hFile "ECHO \@Disclaimer: Check/edit this script to avoid loss of data! \@;\n";
print hFile "----------------------------------------------------------------\n";
print hFile "RESTORE DB $opt_d \n".
" FROM /back-up-path\n".
" TAKEN AT yyyymmddhhmmss\n".
" TO /new-db-path\n".
" INTO new-db\n".
" NEWLOGPATH /new-logpath\n".
" WITH 2 BUFFERS BUFFER 2048\n".
" REDIRECT;\n";
print hFile "----------------------------------------------------------------\n";
print hFile "-- Comments: DO NOT CHANGE THE NAME IN 'RESTORE DB $opt_d'!\n".
"-- DO NOT CHANGE THE NAME IN 'RESTORE DB $opt_d CONTINUE'!\n".
"-- /back-up-path = path or location of back-up file \n".
"-- yyymmddhhmmss = back-up start timestamp, part of backup-file name\n".
"-- /new-db-path = database path, see CONTAINER statement below\n".
"-- new-db = original database name or new target db name\n".
"-- /new-logpath = path to log files, you may alter it afterwards\n".
"-- with UPDATE DB CFG FOR ... USING NEWLOGPATH ...\n";
print hFile "----------------------------------------------------------------\n";
print hFile "-- RESTORE DB $opt_d ABORT;\n";
}
################################################################################
# Create Header for CREATE TABLESPACE Statement
################################################################################
if ($opt_t eq "CREATE" ) {
$work = xmpPerl::getTimestamp();
print hFile "----------------------------------------------------------------\n";
print hFile "-- DDL created ........: $work\n";
print hFile "-- DDL File ...........: $opt_f\n";
print hFile "-- Database ...........: $opt_d\n";
print hFile "-- Object Sizing ......: $opt_s\n";
print hFile "-- Disclaimer: Check/edit this DDL script to avoid loss of data!\n";
print hFile "----------------------------------------------------------------\n";
################################################################################
# DBI Switches
################################################################################
my $switch = DBI->internal;
$switch->debug(0); # 1=normal debug, 2=detailed handle trace
#print "DBI Version and Attributes ..: $switch->{'Attribution'}, $switch->{'Version'}\n";
#print "DBI Drivers .................: ",join(", ",DBI->available_drivers()),"\n";
################################################################################
# Connect to Database
################################################################################
$dbh = DBI->connect("dbi:DB2:$opt_d",
$opt_u,
$opt_p,
{ PrintError => 0, # don't print error by default
RaiseError => 0, # don't print error and die by default
AutoCommit => 0, # don't commit after each statement
ChopBlanks => 0, # don't remove trailing blanks on CHAR-Types
} )
|| die ">>>$0 Problem mit Connect to $opt_d\n>>>".$DBI::errstr;
}
################################################################################
# Anweisungen für jeden Tablespace Container oder Pfad
################################################################################
$work = $tsc;
$work2 = "";
for ($tsc = 1; $tsc <= $work; $tsc++) {
$f1 = $tsc_tsid{$tsc};
$f2 = $tsc_id{$tsc};
$f3 = $tsc_name{$tsc};
$f4 = $tsc_type{$tsc};
$f5 = $tsc_pgtotal{$tsc};
$f6 = $tsc_pguseable{$tsc};
$f7 = $tsc_pgaccess{$tsc};
$f8 = $tsc_tsname{$tsc};
#print ">>>".$ts_name{$f1}."\n";
$ts_total_total = $ts_total_total + ( $f5 * $ts_pgsize{$f1} );
########################################################################
# Consider percentage of growth from net space V1.3
########################################################################
if ($opt_g > 0) {
$f5 = $f5 * ((100+$opt_g)/100); # V1.3
$f5 = int($f5 + 0.5); # V1.3
}
########################################################################
# Calculate minumum number of pages per Tablespace
########################################################################
$pagemin = $ts_container{$f1} + ( (3+2+2 +1)* $ts_extsize{$f1} );
$pagemin = $pagemin + $ts_pghwm{$f1};# Overhead V1.2
########################################################################
# Calculate HWM per file dividing HWM pages by number of containers
########################################################################
#print "TS HWM: ".$ts_pghwm{$f1}." / ".$ts_container{$f1}."\n";
$fe = int(( $pagemin / $ts_container{$f1} )+ 0.5);# round
$fe = int(( ($fe + 9 )/ 10 ) ) * 10;
$ts_total_hwm = $ts_total_hwm + ( $fe * $ts_pgsize{$f1} );
if ($opt_g > 0) {
$fe = $fe * ((100+$opt_g)/100); # V1.3
$fe = int($fe + 0.5); # V1.3
}
########################################################################
# Assign calculated new space, summarize Page Counts and KBytes
########################################################################
if ($opt_s eq "HWM") { $f5 = $fe };
$ts_total_new = $ts_total_new + ( $f5 * $ts_pgsize{$f1} );
########################################################################
# Create Redirected RESTORE DATABASE Statement, Tablespace Sections
########################################################################
if ($opt_t eq "RESTORE" ) {
################################################################
# Create Container
################################################################
if ($f1 ne $work2){# TS-ID changed?
if ($tsc gt 1) {print hFile " );\n"};
print hFile "----------------------------------------------------***\n";
print hFile "-- TS ID $f1 / $f2 / $f8 \n";
print hFile "-- Space Allocated in Pages: ".$ts_pgtotal{$f1}."\n";
if ( $ts_type{$f1} eq "DMS" ) {
print hFile "-- High Water Mark in Pages: ".$ts_pghwm{$f1}."\n";
}
print hFile "-------------------------------------------------------\n";
print hFile "SET TABLESPACE CONTAINERS FOR $f1 USING (\n";
if ($f4 eq "FILE") {print hFile " $f4 $f3 $f5 \n";}
if ($f4 eq "PATH") {print hFile " $f4 $f3 \n";}
if ($f4 eq "DISK") {print hFile " DEVICE $f3 $f5 \n";}
}
else{
if ($f4 eq "FILE") {print hFile " ,$f4 $f3 $f5 \n";}
if ($f4 eq "PATH") {print hFile " ,$f4 $f3 \n";}
if ($f4 eq "DISK") {print hFile " ,DEVICE $f3 $f5 \n";}
}
}
########################################################################
# Create CREATE TABLESPACE Statement
########################################################################
if ($opt_t eq "CREATE" ) {
################################################################
# Next Tablespace? Add additional attributes at end of current cmd
################################################################
if (($work2 ne "") & ($work2 ne $f1)) {
print hFile $rest1;
print hFile $rest2;
}
########################################################################
# Access to DB2 Catalog to get Bufferpool
########################################################################
#$stmt = "select a.tbspace, a.tbspaceid, a.bufferpoolid,b.bpname".
$stmt ="select b.bpname ".
"from sysibm.systablespaces a, ".
" sysibm.sysbufferpools b ".
"where a.bufferpoolid = b.bufferpoolid ".
"and a.tbspace = '$f8' ".
"and a.tbspaceid = $f1 ";
$sth = $dbh->prepare($stmt);
$sth->execute() || die $dbh->errstr;
if ( $dbh->err ) {
die "$0 abended with $dbh->errstr";
}
$bpool = $sth->fetchrow();
if ( $dbh->err ) {
$bpool = "BPCannotCreate $dbh->errstr";
}
################################################################
# Additional attributes for the end of current cmd
################################################################
$rest1 = " ) EXTENTSIZE ".$ts_extsize{$f1}." PREFETCHSIZE ".$ts_pfsize{$f1}."\n";
$rest2 = " BUFFERPOOL $bpool;\n";
################################################################
# Create Tablespace
################################################################
if ($f1 ne $work2){# TS-ID changed?
print hFile "----------------------------------------------------***\n";
print hFile "-- TS $f1 $f8: ".$ts_pgtotal{$f1}." total pages, HWM ".$ts_pghwm{$f1}." pages\n";
print hFile "-- DROP TABLESPACE $f8;\n";
print hFile " CREATE ".$ts_content{$f1}." TABLESPACE $f8\n";
print hFile " PAGESIZE ".$ts_pgsize{$f1}."K \n";
if ($ts_type{$f1} eq "DMS") {
print hFile " MANAGED BY DATABASE\n";}
else {print hFile " MANAGED BY SYSTEM\n";}
if ($f4 eq "FILE") {print hFile " USING (FILE '$f3' $f5 \n";}
if ($f4 eq "PATH") {print hFile " USING ('$f3' \n";}
if ($f4 eq "DISK") {print hFile " USING (DEVICE '$f3' $f5\n";}
}
else{
if ($f4 eq "FILE") {print hFile " ,FILE '$f3' $f5\n";}
if ($f4 eq "PATH") {print hFile " ,'$f3' \n";}
if ($f4 eq "DISK") {print hFile " ,DEVICE '$f3' $f5\n";}
}
}
$work2 = $f1;
}
$tsc--;
################################################################################
# Create Footer for Redirected RESTORE DATABASE Statement
################################################################################
if ($opt_t eq "RESTORE" ) {
print hFile " );\n";
print hFile "----------------------------------------------------***\n";
print hFile "ECHO \@Restored Database Size : $ts_total_new KBytes \@;\n";
print hFile "----------------------------------------------------***\n";
print hFile "RESTORE DB $opt_d CONTINUE;\n";
print hFile "-- ROLLFORWARD DATABASE $opt_d TO END OF LOGS;\n";
print hFile "-- ROLLFORWARD DATABASE $opt_d STOP;\n";
print hFile "----------------------------------------------------------------\n";
print hFile "-- Comments: Use ROLLFORWARD TO END OF LOGS, if log files will\n".
"-- contain important information which will bring the\n".
"-- database to latest consistent state. Use STOP to\n".
"-- ignore log files at all. Do not use CANCEL keyword!\n";
print hFile "----------------------------------------------------------------\n";
}
else {
print hFile $rest1;print hFile $rest2;
print hFile "-- \n";
print hFile "-- Database Total Size : $ts_total_new KBytes\n";
print hFile "-- ***END***\n";
################################################################################
# Close Statement, Disconnect from Database
################################################################################
$sth->finish() || die $dbh->errstr;
$dbh->commit || die $dbh->errstr;
$dbh->disconnect || die $dbh->errstr;
}
########################################################################
# Close File and set File Access Mode
########################################################################
close(hFile);
chmod 0775,$opt_f;
print "Current Total allocated .....: $ts_total_total kBytes\n";
print "High Water Mark used ........: $ts_total_hwm kBytes\n";
print "New space to be allocated ...: $ts_total_new kBytes\n";
print "Tablespaces $opt_t File successfully created for $opt_d!\n";
print "***Ende***\n";
exit 0;
#################################################################################
########################################################## Sub Routines #########
# SaySyntax #####################################################################
sub SaySyntax {
die "Usage: [perl] $0 -d db [-u parm -p parm] -f file [-t {RESTORE|CREATE} -s {CURRENT|HWM}] [-g nn]\n".
"-d database \n".
"-u User (opt)\n".
"-p Password (opt)\n".
"-f file for statement generation\n".
"-t type of statement to generate\n".
"-s current allocation or HWM High Water Mark)\n".
"-g percentage growth (CURRENT/HWM plus n%)\n".
"abends";
}
© Gernot Ruban