Home » Tutorials » Datenbanken » ZEOS Library – Einsatz mit Delphi und Firebird

ZEOS Library – Einsatz mit Delphi und Firebird

TZConnection

Die Komponente TZConnection ist die Kombination aus einer BDE-TDatabase ähnlichen Komponente und einer Komponente, die eine Transaktion steuert. Diese Kombination macht Sinn, denn Zugriffe auf Firebird Datenbanken werden immer im sog. Kontext einer laufenden Transaktion durchgeführt. In der ZEOS Library wird eine solche Transaktion beim Öffnen einer Verbindung (Methode Connect von TZConnection) zu einer Datenbank gestartet. Das bewirkt, dass jeder Datenbankzugriff automatisch im Kontext eben dieser Transaktion stattfindet. Dabei ist der sog. AutoCommit-Modus standardmäßig angeschaltet (True), was auch das Standardverhalten der BDE-Komponenten ist. Bei aktiviertem AutoCommit wird jedes einzelne SQL-Statement nach erfolgreicher Ausführung durch COMMIT bestätigt und die Änderungen in der Datenbank festgeschrieben. Soll dieses Verhalten ausgeschaltet werden und somit eine explizite Transaktion gestartet werden, in der man mehrere Datenbankzugriffe nacheinander durchführt, um diese als „Gruppe“ durch COMMIT zu bestätigen, so muss die Methode StartTransaction aufgerufen werden. AutoCommit ist während einer expliziten Transaktion ausgeschaltet. Mit dem Aufruf der Methode Commit werden die Änderungen, die durch die Zugriffe in dieser Transaktion durchgeführt wurden, bestätigt. Der Aufruf der Methode Rollback macht diese Änderungen rückgängig. In beiden Fällen ist AutoCommit nach Methodenaufruf wieder eingeschaltet. Die explizite Transaktion ist beendet.

Retaining

Nach dem Bestätigen einer Transaktion durch COMMIT oder Zurücknehmen durch ROLLBACK, wird diese im SQL Standard beendet und die evtl. vorhandene Ergebnismenge einer Abfrage oder Stored Procedure wird verworfen. Man redet hier von „harten“ Commits bzw. Rollbacks. Bei ZEOS ist das anders. Hier wird die Ergebnismenge am Leben erhalten, da die Transaktionen in einem TZConnection-Objekt durch „weiche“ Commits bzw. Rollbacks abgeschlossen werden. Man bezeichnet diese Methode als Retaining. Die Befehle COMMIT bzw. ROLLBACK werden mit dem Zusatz RETAINING ausgeführt. Dieses Retaining bewirkt, dass sofort nach dem Beenden der Transaktion eine neue Transaktion gestartet wird, die alle Daten und Ressourcen (im besonderen die Ergebnismenge) der Alten übernimmt.
Problematisch ist das Retaining bei größeren Tabellen. Es behindert nämlich den internen Aufräum-Mechanismus von Firebird (die Garbage Collection). Das führt (bedingt durch das Versioning bzw. Multigenerationen-Prinzip von Firebird) dazu, dass sehr viele alte Datensatzversionen erhalten bleiben, die eigentlich nicht mehr benötigt werden. Das beeinträchtigt die Performance negativ. Ein sog. Sweep würde diese alten Versionen beseitigen und somit die Performance wieder verbessern. Dieser Sweep wird aber nur nach einem „harten“ COMMIT oder ROLLBACK durchgeführt. Bei ZEOS werden diese (erst) beim Beenden der Datenbankverbindung durchgeführt. Während die Datenbankverbindung aktiv ist, ist dies nicht möglich. Man müsste die Datenbankverbindung also gelegentlich trennen und wieder neu aufbauen, um dem Performance-Verlust entgegen zu wirken.

Transaction Isolation Levels von TZConnection

Die TZConnection-Komponente hat vier brauchbare, vordefinierte Transaction Isolation Levels (TIL) zur Auswahl:

tiRepeatableRead

Er entspricht dem TIL „SNAPSHOT“, der als Standard beim Firebird Server Verwendung findet. Abgebildet wird er durch die Trasaction-Parameter „concurrency“ und „nowait“. Es wird ein Schnappschuss des aktuellen Datenbstandes angefertigt. Andere Benutzer werden in der Regel nur dann behindert, wenn zwei Transaktionen einen Datensatz gleichzeitig bearbeiten wollen. Bei Zugriffskonflikten wird eine Fehlermeldung zurückgeliefert. Änderungen anderer Transaktionen werden nicht „wahrgenommen“. Dieser TIL deckt die Anforderungen des SQL-Standards (SERIALIZABLE) zum größten Teilen ab.

tiReadCommitted

Er entspricht dem gleichnamigen TIL „READ COMMITTED“ und wird über folgende Transaction-Parameter realisiert: „read_committed“, „rec_version“, „nowait“. Dieser TIL nimmt die durch COMMIT bestätigten Änderungen anderer Transaktionen wahr. Der Parameter „rec_version“ sorgt dafür, dass immer die aktuellsten (von anderen Benutzern) bestätigten Werte berücksichtigt („wahrgenommen“) werden. Der Parameter „nowait“ sorgt dafür, dass nicht auf die Freigabe von gesperrten Datensätzen gewartet wird. Der Server ist aufgrund der notwendigen Aktualisierungen von Werten mehr beansprucht als bei tiRepeatableRead.

tiSerializable

Er entspricht in etwa dem TIL „SNAPSHOT TABLE STABILITY“ und dient dem exklusiven Zugriff auf eine Ergebnismenge. Durch den Transaction-Parameter „consistency“ realisiert, verhindert er, dass „fremde“ Transaktionen auf geschriebene Daten zugreifen können. Nur die Transaktion, die die Daten geschrieben hat, kann auch wieder auf diese zugreifen. Somit wird ein Mehrbenutzer-Zugriff auf die geschriebenen Daten verhindert. Dieser TIL sollte aufgrund der Restriktivität beim Zugriff auf geschriebene Daten mit Vorsicht und Bedacht eingesetzt werden.

tiNone

Es wird kein TIL für die Transaktion verwendet.
Der TIL tiReadUncommitted wird vom Firebird-Server nicht unterstützt. Bei seiner Angabe wird eine Fehlermeldung ausgegeben und in dessen Folge die Transaktion nicht mit einem TIL versehen (so wie tiNone).

Empfehlung

Empfehlenswert ist auf jeden Fall die Abschottung der Transaktionen im Transaction Isolation Level tiRepeatableRead, dem Firebird-Standard. Dieser kommt, wie schon oben erwähnt, den SQL-Anforderungen am nächsten, denn er verhindert alle Konsistenzprobleme, die durch die Verwendung von Transaktionen entstehen können. Je nach Einsatzgebiet und Notwendigkeit fällt die zweite Wahl auf tiReadCommitted, wenn das Abfrageergebnis immer aktuell sein soll.

Eigene TILs konfigurieren

Will man sich seinen eigenen TIL konfigurieren oder einen vorgegebenen TIL erweitern, dann kann man das über die Parameter von TZConnection erledigen. Wichtig ist, dass der TIL, auf dem aufgebaut werden soll, in der Property Isolation von TZConnection gesetzt ist. Anschließend werden die entsprechenden TIL-Parameter (siehe IB/FB-API-Referenz) im Quellcode hinzugefügt. Hier zum Beispiel die Festlegung eines eigenen TIL mit der Voreinstellung tiNone:

ZConnection.TransactIsolationLevel := tiNone;
ZConnection.Properties.Add('isc_tpb_concurrency');
ZConnection.Properties.Add('isc_tpb_wait');
ZConnection.Connect;

Protocol

Die wohl wichtigste Einstellung in einem TZConnection-Objekt überhaupt, wird in der Property Protocol gemacht. Hier wird (wie der Name schon sagt) festgelegt, welches Zugriffsprotokoll benutzt werden soll und somit bestimmt, auf welchen SQL-Server zugegriffen wird. Diese Methode macht ZEOS weitgehend flexibel, denn es müssen nicht für jeden Datenbank Server die spezifischen Komponenten installiert werden, wie noch bis Version 5.x. Die Komponenten werden einmal installiert und das reicht aus. Es sind Protokolle (Schnittstellen) für alle am Anfang genannten Server vorhanden. Für Firebird 1.5 aber muss hier das Protokoll firebird-1.5 eingestellt werden.

Read-Only-Connection

Die vom TZConnection-Objekt verwaltete Datenbankverbindung ist per Default mit der Property ReadOnly = True konfiguriert. Das bedeutet, dass keine schreibenden Zugriffe auf die Datenbank zugelassen werden. Um Schreibend auf die Datenbank zugreifen zu können, muss diese Property auf False gesetzt werden.

Codepages

Codepages werden in TZConnection im Parameter „lc_ctype“ oder „Codepage“ angegeben. Dieser Parameter wird der Property Properties hinzugefügt. Z. B.:

 ZConection.Properties.Add ('lc_ctype=ISO8859_1');

oder

 ZConnection.Properties.Add ('Codepage=ISO8859_1');

Info: Die Codepage-Unterstützung des Firebird Server (auch die embedded Version) reagiert in Version 1.5 mit den ZEOS Komponenten ein wenig fehlerhaft. Dieses Fehlverhalten wurde mit der Version 1.5.1 von Firebird beseitigt.

Besonderheiten beim Firebird embedded Server

In der Property HostName steht bei einem „normalen“ Firebird Server die IP-Adresse oder der Name des Servers, auf dem Firebird läuft. Beim embedded Firebird fällt diese Angabe weg. In der Property Database steht wie beim normalen Server der Pfad zur Datenbank und ihr Name mit Extension.
Eine weitere Besonderheit des embedded Server ist, dass zum Aufbau einer Verbindung zur Datenbank, ein beliebiger Loginnamen mit einem beliebigen Passwort benutzt werden kann. Man sollte sich aber angewöhnen, in diesem Fall den Benutzer „SYSDBA“ (Passwort ist egal!) zu benutzen.
Eine kleine Fallgrube schaufelt derjenige sich, der ein TZConnection-Objekt in der IDE auf Connected = True stellt, um z. B. Daten während der Entwicklung sehen zu können. Spätestens dann, wenn die Applikation kompiliert und über die IDE oder über den direkten Aufruf ausgeführt wird, wird gemeldet, dass die Datenbank nicht geöffnet werden kann, weil sie schon in Benutzung ist. Man sollte also die Datenbankverbindung auf jeden Fall erst beim Applikationsstart (z. B. im OnCreate des Hauptformulars) herstellen und die benötigten Queries und Tabellen öffnen. Dektiviert wird die Verbindung zur Datenbank dann beim Schließen der Applikation (z. B. im OnDestroy des Hauptformulars). Es ist nicht unbedingt notwendig, die Queries bzw. Tabellen wieder explizit zu schließen. Das übernimmt das TZConnection-Objekt. Wenn mit einem Datenmodell-Formular gearbeitet wird, dann muss dafür Sorge getragen werden, dass das Datenmodell-Formular noch vor dem Hauptformular erstellt wird (Einstellung in der IDE über die Projekt-Optionen).

Nützliche TZConnection-Parameter

Weitere Parameter für die Steuerung des Verbindungsaufbaus zu einer Firebird Datenbank sind die Folgenden:

CreateNewDataBase:

Eine neue Datenbank wird anhand des angegebenen CREATE-DATABASE-Statements erstellt und anschließend sofort die Verbindung zu ihr hergestellt. Das alles geschieht beim Aufruf der Connect-Methode.

 ZConnection1.Database := 'd:db1.fdb';
 ZConnection1.Protocol := 'firebird-1.5';
 ZConnection1.Properties.Add ('CreateNewDatabase=CREATE DATABASE ' + 
   QuotedStr ('d:db1.fdb') + ' USER ' +
   QuotedStr ('sysdba') + ' PASSWORD ' + QuotedStr ('masterkey') +
   ' PAGE_SIZE 4096 DEFAULT CHARACTER SET ISO8859_1');
 ZConnection1.Connect;

Es müssen aber zuvor mindestens die Properties Database und Protocol gesetzt werden (auch über den Objektinspektor möglich).

Dialect:

Dieser Parameter setzt den Firebird SQL Dialekt. Um den Dialekt „1“ zu setzen, sollte folgende Zeile verwendet werden:

 ZConnection.Properties.Add('Dialect=1');

Per Default ist der SQL Dialekt bei Firebird 1.5 „3“.

Rolename:

Dieser Parameter bewirkt, dass ein Rollenname (RoleName) gesetzt wird. Mit den Rechten dieser Rolle kann dann ein Benutzer an einer Datenbank arbeiten. Dazu muss ihm aber zuvor diese Rolle zugewiesen worden sein. Das alles gilt nicht für den Firebird embedded Server.

Ein Gedanke zu „ZEOS Library – Einsatz mit Delphi und Firebird“

  1. Lieben Dank für dieses tolle Tutorial. Es ist sehr klar und übersichtlich, und eine tolle Hilfe für den Einstieg.

     

Kommentare sind geschlossen.