Datenbankzugriff mal anders: TYPO3 4.0: DBAL
Ein Datenbank-Abstraktions-Layer für TYPO3 wurde in der Vergangenheit im Zusammenhang mit TYPO3 meist von großen
Firmen nachgefragt, die Zweifel an der Leistungsfähigkeit von MySQL
hegten und lieber ihre bestehenden Oracle- oder SQL-Server-Installationen nutzen wollten. Im Laufe der Zeit stieg jedoch
die Akzeptanz für MySQL auch in größeren Firmen, so dass sich trotz der
immer wieder aufkeimenden Diskussionen über eine Abstraktionsschicht niemand fand,
der diese auch implementiert hätte. Erst nach der TYPO3-Snowboard-Tour
2004 bot sich die Gelegenheit den DBAL zu realisieren.
Eine DBAL-Extension – das kann ja nicht so schwer sein
Aus Sicht von TYPO3 reicht Datenbank-Abstraktion im landläufigen
Sinne – als Vereinheitlichung der Funktionen zum Senden von
SQL-Anfragen – bei weitem nicht aus. Statt dieser
„Zugriffs-Vereinheitlichung“ ist hier eine Kombination aus
„SQL-Abstraktion“ und „Zugriffs-Vereinheitlichung“ notwendig. Dies ist
nötig, da TYPO3 selbst Datenbanktabellen anlegt und diese auch jederzeit
erweitern kann. Darüber hinaus ist Abwärtskompatibilität eine der
Leitlinien des TYPO3-Projekts, mit der Folge, dass die
Datenbankschemata
weiterhin aus MySQL-Dumps erzeugt werden müssen – auch für Oracle und
andere RDBMS. Dies alles führt natürlich zu völlig neuen Problemen, etwa bei der Behandlung unterschiedlicher Datentypen.
Im Laufe der Zeit hat Kasper Skårhøj alle Datenbankzugriffe im Kern von
TYPO3 in der Klasse „t3lib_db“ konsolidiert. Dies bot die Basis für die
Entwicklung der DBAL-Extension, die diese Klasse erweitert und
Kernmethoden überschreibt. Ohne diese Extension kann „t3lib_db“ eher als Wrapper um die klassischen
MySQL-Aufrufe gesehen werden. Da die Entwicklung der DBAL-Extension
schon aufwändig genug sein würde, wurde nach einer geeigneten
Abstraktions-Bibliothek gesucht. Als Kasper Skårhøj schließlich den Protoypen
der Extension schrieb, setzte er auf PEAR DB und ADOdb.
Dieser Prototyp wurde zur weiteren Entwicklung mit dem Ziel abgegeben,
TYPO3 auf PostgreSQL lauffähig zu machen, um anschließend Oracle ins Visier zu
nehmen.
Der Stand der Dinge
Im einfachsten Fall, wenn ausschließlich ein anderes Datenbank-System genutzt
werden soll, ist nach einigen Zeilen Konfiguration in der „localconf.php“
bereits alles erledigt: Das Listing zeigt eine Konfiguration zur
Nutzung von PostgreSQL. Über das Install Tool kann TYPO3 nun fast wie
gewohnt installiert und genutzt werden. Die Installation der
DBAL-Extension muss allerdings „zu Fuß“ geschehen, da der Extension
Manager zu diesem Zeitpunkt noch nicht zur Verfügung steht. Dies ist
jedoch ebenfalls recht einfach und in der Dokumentation der
DBAL-Extension [1] beschrieben.
$TYPO3_CONF_VARS['EXTCONF']['dbal']['handlerCfg'] = array ( '_DEFAULT' => array ( 'type' => 'adodb', 'config' => array( 'driver' => 'postgres7', ) ) );
Listing 1
Neben der kompletten Nutzung eines anderen Datenbank-Systems ist es auch
möglich, nur einzelne Tabellen oder Felder aus einem anderen System zu
lesen, dies ermöglicht das so genannte „Mapping“. Eine entsprechende
Konfiguration kann dazu genutzt werden, Extensions nahtlos zu
integrieren, obwohl die von ihnen benötigten Daten aus einem
Drittsystem stammen. Die Konfiguration hierfür ist komplexer,
die Dokumentation zur DBAL-Extension enthält jedoch auch hierfür gut
verständliche Beispiele.
Und das klappt?
Neben PostgreSQL und Oracle wurde die Extension mittlerweile auch mit
Firebird getestet, ohne dass dabei Probleme auftraten. In ersten größeren
Projekten traten dennoch Schwierigkeiten auf, die mittlerweile
gelöst sind und sich vor allem in Verbindung mit komplexeren
Möglichkeiten des Mapping zeigten.
Im Herbst 2004 wurde ein Geschwindigkeitstest [2] der Extension durchgeführt, bei dem sich zeigte, dass die Leistung bei
Nutzung von PostgreSQL etwa um die Hälfte gegenüber MySQL einbricht.
Durch den Einsatz eines PHP-Beschleunigers können jedoch wieder Werte
über den ursprünglichen erreicht werden. Ein System mit PosgtreSQL
und PHP-Beschleuniger ist also in etwa so schnell wie ein reines MySQL-System
ohne Beschleuniger. Daraus folgt, dass beim Einsatz der DBAL-Extension
der Einsatz eines solchen Beschleunigers absolut empfehlenswert ist.
Mittlerweile sind Optimierungen am Code erfolgt, ein erneuter Benchmark
zur Überprüfung der erreichten Leistungssteigerung ist jedoch bisher
nicht erfolgt.
Andere Datenbanken als die genannten warten noch auf ihre Feuertaufe im
Einsatz mit TYPO3. Grundsätzlich sollten Datenbanken, für die ein
ADOdb-Treiber zur Verfügung steht, auch mit TYPO3 lauffähig sein. Dies
hängt jedoch auch davon ab, ob der Treiber vollständig
implementiert ist und wie sich die Datenbank im Detail verhält –
Gewissheit bietet nur ein gründlicher Test.
Ein Problem, das Nutzer der DBAL-Extension wohl noch länger
beschäftigen wird, sind nicht DBAL-fähige Extensions. Da die
Project-Coding-Guidelines bereits seit TYPO3 Version 3.6.0 die Nutzung
der
DBAL-API beinhalten, sind die meisten jüngeren Extensions – was
diesen Punkt angeht – recht gut vorbereitet. Extensions die noch
direkte Aufrufe der MySQL-Funktionen tätigen, müssen umgeschrieben
werden. Ebenso macht die Nutzung von MySQL-spezifischem oder
komplexerem SQL Probleme, die nur durch Änderung der betroffenen
Extensions behoben werden können. Hier hoffen die DBAL-Entwickler auf Mitarbeit der
Community.
Zugeschaut und mitgebaut
Viele Entwickler, die eigene TYPO3-Extensions programmieren, kennen die Project-Coding-Guidelines [3] und nutzen bereits seit langem die DBAL-API des
TYPO3-Kerns. Für diejenigen, die erst einsteigen wollen, hier ein
kleines Beispiel, wie eine Extension fit für DBAL gemacht werden kann.
Als Beispiel soll die im Dokument „Creating a basic extension“ [4] beschriebene Extension dienen. Dort findet sich PHP-Code,
der unter anderem in der Methode „getItems()“ eine Datenbank-Abfrage
enthält.
$query = "SELECT * FROM tx_playerprofile_list WHERE pid IN (".$pid.") ORDER BY sorting"; $res = mysql(TYPO3_db,$query); $out=array(); while($row = mysql_fetch_assoc($res)) { $out[]=$row; }
Listing 2
Mit zwei kleinen Änderungen wird der Code DBAL-konform. Die erste
Änderung ersetzt den Aufruf der „mysql()“-Funktion gegen eine
entsprechende Methode aus der DBAL-API: „exec_SELECTquery()“. Hier wird
keine komplette SQL-Anfrage abgesetzt, sondern dem DBAL werden
Komponenten der Anfrage übergeben, die dieser für die Zieldatenbank
passend in eine konkrete Anfrage umsetzen kann. Das Ergebnis des
Aufrufs ist ein Ergebnis-Objekt, mit dem wieder fast wie bisher
verfahren werden kann: Aus „mysql_fetch_assoc()“ wird die Methode
„sql_fetch_assoc()“.
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tx_playerprofile_list', ' 1=1 AND pid IN ('.$pid.')', '', 'sorting') $out=array(); while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { $out[]=$row; }
Listing 3
Im Großen und Ganzen ist es leicht, den eigenen Extensions
DBAL-Fähigkeiten zu verschaffen. Falls es doch nicht auf Anhieb klappt,
ist das Backend-Modul der DBAL-Extension hilfreich, mit dem
Informationen über den Status der Extension abgerufen werden können. Im
Fehlerfall bietet es zudem die Möglichkeit, ein Log aller tatsächlich
durchgeführten Datenbank-Operationen und der dabei aufgetretenen
Fehlermeldungen zu erstellen. Interessant sind vor allem komplexe
Queries und Abfragen über mehrere Tabellen, die besonders in
Mapping-Szenarien problematisch sein können: Schnell konfiguriert man
zwei Tabellen aus einer solchen Anfrage in verschiedene Datenbanken,
mit verständlicherweise eher unerwünschten Ergebnissen.
Ein Blick in die Zukunft
Die erste offizielle Veröffentlichung der DBAL-Extension wird
vermehrt neue
Nutzer ansprechen und wohl auch restliche Unklarheiten ans Tageslicht
fördern. Neben der Beseitigung dieser „Bugs“ sind folgende neue
Funktionen geplant:
- Neue Handler für weitere Datenbanken werden hinzukommen. Bei
entsprechender Nachfrage auch solche, die eher nativen Charakter haben
und ohne die Nutzung von ADOdb auf die Zieldatenbank zugreifen. Dies
würde helfen, die bereits angesprochenen Probleme mit der
Geschwindigkeit zu entschärfen. - Handler sind nicht auf klassische Datenbanken beschränkt. So ist
es durchaus denkbar, den Zugriff auf JSR-170-Repositories über DBAL zu
ermöglichen, wenn hierfür eine PHP-Implementierung vorliegt. - Die Konfiguration in Form einer PHP-Datei ist zwar effizient,
allerdings nicht eben übersichtlich, wenn es um komplexe Szenarien
geht. Hier wäre ein Modul denkbar, mit dem die Konfiguration erfolgen
kann.
Diese Punkte sind jedoch mehr als lockere Ansammlung von Ideen zu
sehen. Die Arbeit nach dem Release dient in erster Linie dazu,
Erfahrungen aus dem Alltagsbetrieb in die
Programmierung einfließen zu lassen.