Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  1/2010  Pfeil  Datenbanken
suche: 
Diese Reihe richtet sich an DB2-Administratoren, die die Möglichkeiten von Perl für ihre tägliche Arbeit kennenlernen möchten und an Perl-Entwickler, die erstmalig mit einer DB2-Datenbank arbeiten möchten.

Glossar

CPAN
UComprehensive Perl Archive Network: Online-Repository für Perl-Module, Anwendungen und Dokumentation.
DBD
Database Driver: Datenbankspezifischer Treiber für DBI.
DBI
Database Independent Interface: Die universelle Datenbankschnittstelle in Perl.


Neue Reihe: Perl und DB2 im Verbund (Teil I)

Perlen (nicht nur) für DB2-DBAs

Maskottchen sind beliebt. Bei Perl ist es seit langem das Kamel. IBM setzt seit DB2 Version 9.1 auf Schlangen (Viper, Cobra). Tiere, die sich eher aus dem Weg gehen, möchte man glauben. Das sie sich mit ein wenig gutem Zureden zumindest in der IT gut vertragen, soll dieser erste Artikel unserer neuen Reihe aufzeigen. Auch Perl-Entwickler, die mit anderen Datenbanken arbeiten, sind herzlich zum Lesen eingeladen.

Abb. 1: Architektur des Datenbankzugriffs.
Abb. 1: Architektur des Datenbankzugriffs.
source $DB2INSTANCE/sqllib/db2profile
export DB2_HOME=/opt/ibm/db2/v9.7/
gunzip DBD-DB2-1.78.tar.gz
tar –xvf DBD-DB2-1.78.tar
cd DBD-DB2-1.78
perl Makefile.PL
make
make install
Abb. 2: Beispielhafte Installation des DBD::DB2-Treibers.
#!/usr/bin/perl -w

use strict;      # zwingt uns u. a. zur Deklaration unserer Variablen
use DBI;
use DBD::DB2::Constants;
use DBD::DB2;

my $database_name = "dbi:DB2:ordix";
my $database_user = "testdb2";
my $password = "1234";
my $dbh;      # Diese Variable wird das Objekt mit dem Database-Handle enthalten

$dbh = DBI->connect(      # Verbindung aufnehmen
  $database_name,
  $database_user,
  $password,
  {
    db2_txn_isolation => SQL_TXN_READ_UNCOMMITTED,
      # aus DBD::DB2::Constants
    db2_info_programname => "perl-dbi-test"
  }
) or die "Datenbankverbindung gescheitert:", $dbh->errstr;

$dbh->do(
"CREATE TABLE ORDIX_TEST (id bigint not null, seminar varchar(
200), dozent varchar(30))"
);      # DDL-Operationen mit “do”
my $insertstring = "INSERT INTO ORDIX_TEST VALUES(?,?,?)";
my $sth = $dbh->prepare($insertstring);
$sth->execute( 1, 'Perl Programmierung Grundlagen', 'Norbert
Munkel' );
$sth->execute(
  3,
  'IBM DB2 für Linux/Unix/Windows Administration',
  'Michael Spoden'
);

my $selectstring = "SELECT seminar, dozent from ordix_test
WHERE dozent LIKE ?";
$sth = $dbh->prepare($selectstring);
$sth->execute("%Munkel%");

while ( my @row = $sth->fetchrow_array ) {
  print join( ';', @row );
  print "\n";
}
$sth->finish;
$dbh->disconnect;
Abb. 3: Ein einfaches DBI/DBD-Skript.

Warum Perl?

„Folgende 12 Abfragen hätte ich gerne jeden Tag auf dem Linux-Server ausgeführt und als Excel-Arbeitsmappe auf dem FTP-Server des Kunden abgelegt“. So oder ähnlich lauten Aufträge unserer Kunden. Nun, den ersten Teil der Aufgabe könnte man auch mit einem Shell-Skript erledigen. Aber wie geht es weiter, wenn die Anforderungen an den Output ständig variieren?

Nach mittlerweile gut 20 Jahren Entwicklungszeit hat sich Perl in vielen Bereichen etabliert und vor allem im Unix-Umfeld bei einer wachsenden Anzahl von Administratoren die Shell-Programmierung abgelöst. Die große Anzahl frei verfügbarer Bibliotheken deckt viele Spezialfälle ab, die mit einem Shell-Skript entweder gar nicht oder nur sehr mühsam abzubilden wären. Zudem kann man sich bei aktuellen Unix-Derivaten (bei Linux sowieso) i. d. R. darauf verlassen, dass zumindest eine Perl-Installation mit den Standard- Bibliotheken vorhanden ist. Da sich viele Aufgaben innerhalb der Programmierung ständig wiederholen, ist die Möglichkeit der Wiederverwendbarkeit von Code sicher für viele praktisch. Wenn man ein wenig Acht gibt, bleibt der Code auch ohne allzu ausschweifende Kommentierungen wartbar.

Die Qual der Wahl

Die Suche nach „DB2“ im CPAN liefert eine Vielzahl von entsprechenden Perl-Modulen [1]. Der Entwicklungsstand dieser Module ist jedoch recht unterschiedlich. So wurden z. B. die DBIx-Module bereits seit 2006 nicht mehr aktualisiert. Die verbreiteteste Technologie dürfte die Verwendung der DBI/DBD-Schnittstelle sein, auf die wir im Folgenden eingehen.

DBI und DBD

Zuständig für die Anbindung beliebiger Datenbanken unter Perl ist das Database Independent Interface (DBI). Für die Anbindung an DB2 ist weiterhin ein spezifischer Datenbanktreiber (DBD) notwendig (siehe Abbildung 1). Beide sind nicht Bestandteil der Perl-Standardbibliothek und müssen somit nachinstalliert werden.

Diese Kombination liefert uns eine SQLSchnittstelle. Da mit jeder Version von DB2 mehr Konfigurationsparameter über die SYSIBMADM-Views zugreifbar werden, ist dies ein guter Einstiegspunkt. Das DB2::Admin-Modul verspricht dagegen Zugriff auf Nicht-SQL-Aktionen (Event-Snapshots, Katalog-Verwaltung usw.), leidet aber an mehreren Einschränkungen. Die Installation ist an viele Vorbedingungen geknüpft und die vollständige Funktionsweise wurde bisher lediglich für RedHat-basierte Systeme bestätigt. Zudem ist eine ständig größer werdende Anzahl von administrativen Aufgaben mit den SYSIBMADM-Views und einfachem SQL übersichtlich handhabbar.

Wir werden uns in dieser Reihe vornehmlich mit dem „klassischen“ Zugriff per DBI/DBD beschäftigen. Da der Großteil der verwendeten Methoden direkt aus dem DBI-Modul stammt, wird erfahrenen Perl-Entwicklern einiges bekannt vorkommen. Bitte beachten Sie in diesem Fall die spezifischen Connect-Parameter. Ihr DBA wird es Ihnen danken!

Beschaffung und Installation

Bei den meisten Linux-Distributionen ist zumindest DBI als Paket installierbar. Dieser Weg wird auch empfohlen, da benötigte Abhängigkeiten automatisch aufgelöst werden. Spätestens beim DB2-Treiber ist aber Handarbeit angesagt. Zwingende Vorbedingung hierfür ist das Vorhandensein eines C-Compilers (z. B. gcc) sowie mindestens eine DB2-Client-Installation. Für die Verbindung zur Datenbank benötigen Sie weiterhin zwingend einen lokalen Katalogeintrag.

Die Installation erfolgt sinnvollerweise als User root. Weitere Vorbedingung ist das Setzen des Umgebungsparameters DB2_HOME auf das IBM-Installationsverzeichnis. Abbildung 2 zeigt eine beispielhafte Installation des DBD::DB2-Treibers.

Der erste Kontakt

Der User, unter dem das Skript laufen soll, sollte die db2profile-Datei der entsprechenden Instanz laden, damit die Umgebung passt. Kurz: Der User sollte den db2-Client auf dem Rechner verwenden können. Für die administrativen Aufgaben sollte der User auf der Datenbankseite mindestens SYSMONoder SYSCTL-Berechtigung erhalten. In der Regel wird man ohnehin den Instanzen-User verwenden, der diese Berechtigung aufweist. Der Verbindungsaufbau ist in Abbildung 3 dargestellt.

Für den Einstieg gehen wir davon aus, dass die Datenbank lokal katalogisiert ist. Eine Verbindung zu einer nicht-katalogisierten Datenbank ist unter Angabe des Host-Namens und der Port-Nummer ebenfalls möglich, aber für unsere Reihe an dieser Stelle eher unnötig kompliziert.

Attribute für Datenbank-Connections

Jeder Connect-String kann einen zusätzlichen Parameter enthalten. Hier kann eine (anonyme) Referenz auf einen Attribut-Hash hinterlegt werden.

Mögliche Attribute sind in der DBI als auch der DBD::DB2-Dokumentation aufgeführt. An dieser Stelle gehen wir auf zwei wesentliche Attribute beispielhaft ein.

Mit db2_txn_isolation kann der Isolation Level des Skripts geändert werden. Gerade für Admin-Skripte bietet sich hier der Wert SQL_TXN_READ_UNCOMMITED an, da z. B. Systemtabellen oft gesperrt sind.

Mit db2_info_programname kann wiederum ein Applikationsname vergeben werden. Leider stellen sich Perl-Programme in der Ausgabe von list applications ansonsten lediglich mit dem Schlüsselwort perl dar, was bei mehreren parallel laufenden Skripten ein wenig unübersichtlich sein kann.

Mit Datenbank-Connections arbeiten

Um den „Hello World“-Charakter dieses ersten Teils nicht zu sprengen, werden wir uns auf ein paar grundlegende Operationen beschränken. Wir werden eine Tabelle erzeugen, einige Werte eingeben und diese dann auslesen. Somit haben wir sowohl DDLals auch DML-Operationen. Für die DDLOperationen verwenden wir die Methode do. Für INSERT, UPDATE und SELECT verwenden wir ein mehrstufiges Verfahren. Die Vorgehensweise ist - unabhängig von den verschiedenen speziellen Methoden - im Wesentlichen wie folgt:

  1. connect
  2. prepare (Statement wird kompiliert)
  3. execute (Statement wird ausgeführt, Parameter-Marker werden mit Werten belegt)
  4. fetch (hier gibt es verschiedene Methoden, die in der DBI-Dokumentation beschrieben sind. Wir verwenden im Beispiel die Methode fetchrow_array, welche jede Zeile des Abfrageergebnisses in ein Array schreibt.
  5. disconnect

Parameter-Marker

Parameter-Marker werden durch ein Fragezeichen dargestellt. Man könnte die VALUES und WHERE-Klauseln auch direkt mit Werten belegen. Hierdurch erzeugt man allerdings einen unnötigen Overhead. Bei Verwendung der Parameter-Marker wird das Statement nur ein einziges Mal kompiliert.

Für Abfragen, bei denen man sicher davon ausgehen kann, dass nur eine Zeile zurückgeliefert wird, gibt es z. B. die Methode selectall_array. Hier werden die Phasen prepare/execute/fetch in einem Statement zusammengefasst und die erste Zeile des Ergebnisses einem Array zugewiesen. Ein komplettes, funktionstüchtiges Skript zeigt Abbildung 3.

Fazit

Der erste Schritt ist getan. Im nächsten Teil der Reihe zeigen wir, wie man mit SQL::Library Ordnung in seine Abfragen bringt und entwickeln eine aussagefähigere Alternative zu LIST APPLICATIONS.

 

Norbert Munkel (info@ordix.de).