D ISSERTATION ZUR E RLANGUNG DES D OKTORGRADES FAKULTÄT FÜR A NGEWANDTE W ISSENSCHAFTEN DER A LBERT-L UDWIGS -U NIVERSITÄT F REIBURG IM B REISGAU DER TransForm: Transaktionen für Web-Formulare von Matthias Ihle Dekan: Prof. Dr. Bernhard Nebel Referenten: Prof. Dr. Georg Lausen Prof. Dr. Peter Thiemann Datum der Promotion: 21. Februar 2008 Zusammenfassung Das World Wide Web mit seinen universellen, plattformunabhängigen Browsern und deren eingebauten Formularen scheint eine ideale Plattform für OLTP-Anwendungen zu bilden. Allerdings bereitet gerade die Verarbeitung von Web-Formularen in Transaktionen Schwierigkeiten, wenn die Abhängigkeit der zu schreibenden Daten von den Ausgangswerten erfasst werden soll. Üblicherweise wird deshalb die Serverinfrastruktur an die Bedürfnisse der Formularverarbeitung angepasst und auf modifizierte Webserver oder zusätzliche Transaktionsserver zurückgegriffen. TransForm verfolgt einen entgegengesetzten Ansatz und passt den Mechanismus der Formularverarbeitung und die Schnittstelle für den Datenzugriff an die Gegebenheiten des WWW an. Dabei fungiert ein Web-Service als Wrapper für die eigentliche Datenbank, der über eine HTTP-basierte Schnittstelle einzelne Transaktionsschritte entgegennimmt und zu ACID-Transaktionen zusammenfasst. Spezielle Formulare bilden das clientseitige Gegenstück im Browser, die wie gewöhnliche HTML-Formulare im Seitenquelltext definiert werden. Die Tagdefinitionen enthalten alle benötigten Informationen, damit ein Javascriptprogramm Benutzerinteraktionen automatisch in Aufrufe des Web-Service übersetzen kann. Abstract As result of the ubiquity and platform independence of web browsers with their built-in web forms the World Wide Web seems to be an ideal platform for OLTP applications. On the other side, comprising the dependency of written data and initial values, the processing of web forms raises difficulties when transactions come into play. For this purpose the server infrastructure is usually tailored to the form processing needs, either by modifying the web server or introducing an additional transaction server. In this thesis, we propose with TransForm a solution following an opposite approach by adjusting the form processing mechanism and the data access interface to the realities of the WWW. Therefore, a web service acts as a wrapper for the underlying database subsuming individual transaction steps that are received via an HTTP-based interface into ACID transactions. Special forms are the client-side counterpart in the browser, defined in the web page source code like ordinary HTML forms. The tag definitions contain all the information that a JavaScript program needs to automatically translate user interactions into web service calls. Inhaltsverzeichnis 1 Einleitung 1.1 Motivation . . . . . . . . . . . . . 1.1.1 Problemstellung . . . . . 1.1.2 Ziele . . . . . . . . . . . . 1.2 Der TransForm-Lösungsansatz . . 1.2.1 Ein einführendes Beispiel 1.2.2 Systembedingte Nachteile 1.3 Gliederung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 3 4 6 7 8 2 Hintergrund 2.1 Das World Wide Web . . . . . . . . . . . . . 2.1.1 Grundlagen & Technologien . . . . . 2.1.2 Das WWW als Anwendungsplattform 2.1.3 Das WWW als Forschungsgebiet . . . 2.2 Transaktionsverarbeitung . . . . . . . . . . 2.2.1 Benutzerschnittstellen . . . . . . . . 2.2.2 Das Transaktionskonzept . . . . . . . 2.2.3 TP-Monitore . . . . . . . . . . . . . . 2.3 Transaktionsverarbeitung im WWW . . . . . 2.3.1 Datenbankverbindungen . . . . . . . 2.3.2 Relevante Forschungsarbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 12 15 18 19 20 21 22 23 25 3 TransForm 3.1 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Architektur als TP-System . . . . . . . . . . . . . . . . . . 3.1.2 TransForm als Architekturstil . . . . . . . . . . . . . . . . 3.1.3 Schichten-Modell . . . . . . . . . . . . . . . . . . . . . . . 3.1.4 Vergleich zu Datenbank-Servern . . . . . . . . . . . . . . . 3.2 Modelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 Datenmodell . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Transaktionenmodell . . . . . . . . . . . . . . . . . . . . . 3.2.3 Formularmodell . . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Authentifikation . . . . . . . . . . . . . . . . . . . . . . . 3.3 ACID-Garantien . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Atomizität und Dauerhaftigkeit von Transaktionsschritten 3.3.2 TransForm-Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 28 29 30 31 32 33 33 36 39 42 44 45 46 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v Inhaltsverzeichnis 3.3.3 Recovery-Strategien im Web-Service . . . 3.3.4 Wiederherstellung nach Browserabstürzen 3.3.5 Anforderungen an Scheduler . . . . . . . 3.4 Komponenten und Schnittstellen . . . . . . . . . 3.4.1 Komponenten im Webservice . . . . . . . 3.4.2 Die Web-Service-Schnittstelle . . . . . . . 3.4.3 Formulare als Browser-Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 48 49 50 50 53 55 4 Backends 4.1 Charakterisierung verschiedener Backends . . . . . . . . . . . 4.1.1 Datenbank-Typen . . . . . . . . . . . . . . . . . . . . . 4.1.2 Zugriff auf relationale Datenbanken . . . . . . . . . . 4.2 Generischer Zugriff auf Relationale Datenbanken . . . . . . . 4.2.1 Die XML-Sicht der Datenbank . . . . . . . . . . . . . . 4.2.2 Datenzugriff über XPath . . . . . . . . . . . . . . . . . 4.2.3 Konflikterkennung . . . . . . . . . . . . . . . . . . . . 4.2.4 Erweiterte Sicht und Verbundanfragen . . . . . . . . . 4.3 Anwendungsspezifischer Zugriff auf relationale Datenbanken 4.3.1 Tabellen der Platzreservierungs-Datenbank . . . . . . 4.3.2 XML-Sicht des Backends . . . . . . . . . . . . . . . . . 4.3.3 XPath-Anfragen . . . . . . . . . . . . . . . . . . . . . . 4.4 Dateisysteme als Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 56 57 57 58 59 60 64 65 70 70 71 72 74 5 Scheduler 5.1 Vorbetrachtungen . . . . . . . . . . . . . . . . 5.1.1 Klassen von Schedules . . . . . . . . . 5.1.2 Scheduling-Verfahren . . . . . . . . . 5.1.3 Ein Rahmen für TransForm-Scheduler . 5.2 Optimistische Scheduling-Verfahren . . . . . . 5.2.1 Rückwärtsgerichtete Varianten . . . . 5.2.2 Die vorwärtsgerichtete Variante FOCC 5.2.3 Der optimistische TransForm-Scheduler 5.3 Sperrbasierte Scheduling-Verfahren . . . . . . 5.3.1 Umsetzung von Sperren . . . . . . . . 5.3.2 2-Phasen-Sperrprotokolle . . . . . . . 5.3.3 Der sperrbasierte TransForm-Scheduler 5.3.4 Diskussion weiterer Sperrverfahren . . 5.4 Ein hybrider TransForm-Scheduler . . . . . . . 5.5 Verteilte Transaktionen . . . . . . . . . . . . . 5.5.1 Das 2-Phasen-Commit-Protokoll . . . . 5.5.2 Verteilte Transaktionen in TransForm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 76 77 79 81 83 84 85 87 87 88 89 90 93 95 97 97 98 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Formulare 101 6.1 Der Formular-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 vi Inhaltsverzeichnis 6.1.1 Formulare . . . . . . . . . . . . . . . . . . 6.1.2 Eingabeelemente . . . . . . . . . . . . . . 6.1.3 Formular-Definition . . . . . . . . . . . . 6.1.4 Implementierung . . . . . . . . . . . . . . 6.2 Von Formularen zu Webanwendungen . . . . . . 6.2.1 Erweiterter Formularbegriff . . . . . . . . 6.2.2 Kinoreservierung als Anwendungsbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 103 105 108 109 109 111 7 Evaluierung 7.1 Performance . . . . . . . . . . . . . . . . 7.1.1 Test Setup . . . . . . . . . . . . . 7.1.2 Testreihen . . . . . . . . . . . . . 7.1.3 Ergebnisse der Latenzmessungen 7.1.4 Ergebnisse der Lastmessungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 115 117 119 120 123 8 Fazit 8.1 Zusammenfassung . . . . . . . . . 8.2 Vergleich mit verwandten Arbeiten 8.3 Beitrag . . . . . . . . . . . . . . . . 8.4 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 126 127 128 129 . . . . . . . . . . . . Abbildungsverzeichnis 130 Literaturverzeichnis 132 vii viii Kapitel 1 Einleitung 1.1 Motivation Transaktionsverarbeitungs-Systeme (TP-Systeme) bieten einer Vielzahl von Anwendern die Möglichkeit, Daten einer gemeinsamen Datenbank gleichzeitig zu bearbeiten. Wenn das in Echtzeit geschieht, spricht man auch von online-Transaktionsverarbeitung bzw. OLTPSystemen. Klassische Anwendungsfelder sind Warenhaltungssysteme oder Flugbuchungssysteme, die schon in den 60er-Jahren mit dem SABRE-System [CMM95] die erste erfolgreiche kommerzielle Anwendung hervorgebracht haben. Üblicherweise werden OLTPAnwendungen in Plattformen mit ausgefeiltem Transaktionsmanagement wie beispielsweise dem TP-Monitor CICS [IBM] implementiert. Aber auch das WWW, ursprünglich als Hypertext-System entworfen, hat sich als mittlerweile vielleicht größte Anwendungsplattform zu einer auf den ersten Blick attraktiven Grundlage für OLTP-Anwendungen entwickelt. Eine zentrale Installation und Wartung der Anwendungslogik wird ergänzt durch Web-Browser, die als universelle und plattformunabhängige Clients auf nahezu jedem System verfügbar sind und mit HTML-Formularen die nötigen Bordmittel für die Datenbearbeitung schon mitbringen. Näher betrachtet, bereitet aber gerade der aus seiner Hypertext-Vergangenheit resultierende grundlegende Anfrage-Antwort-Zyklus Probleme, insbesondere bei der Verarbeitung von Formulardaten in Transaktionen, wenn diese die Abhängigkeit der geschriebenen Daten von den Ausgangswerten erfassen sollen. 1.1.1 Problemstellung Abbildung 1.1 verdeutlicht diese Problematik. Hier erzeugt ein erster Webserver-Prozess eine Webseite, die ein Formular mit in diesem Fall zwei Formularfeldern enthält. Die Ausgangswerte dieser Formularfelder liest er dazu aus der Datenbank, dargestellt durch den Pfeil zwischen der ersten server action und dem Datenbank-Zylinder. Wenn der Benutzer die Bearbeitung des Formulars abgeschlossen hat, übermittelt der Browser die Inhalte aller Formularfelder zurück an den Webserver. In einem zweiten Prozess schreibt der Webserver nun abhängig von den übermittelten 1 Kapitel 1 Einleitung Abbildung 1.1: Die Verarbeitung von Formularen in unterschiedlichen Prozessen des Webservers. Formularinhalten einen neuen Zustand in die Datenbank und liefert eine neue Webseite mit dem Verarbeitungsergebnis aus. Da das Lesen und Schreiben in unterschiedlichen Webserver-Prozessen geschieht, kann es nicht in eine einzige Transaktion der Datenbank eingeschlossen werden. Die dazu nötige Verbindung zur Datenbank muss nämlich in jedem Prozess neu aufgebaut werden und kann nicht einfach wiederverwendet werden. Bei Verbindungsende werden alle Transaktionen automatisch beendet. Um trotzdem beide Verarbeitungsschritte in eine gemeinsame Transaktion zu kapseln, stehen prinzipiell zwei Möglichkeiten zur Verfügung: 1. Verarbeitung beider Webseiten in einem Prozess: Dieser Ansatz wurde zum ersten Mal von Mawl [ABBC99] vorgeschlagen. Ein modifizierter Webserver fasst beide Schritte in einer Session zusammen. Da jede Session in einen Prozess verarbeitet wird, muss die Datenbankverbindung nicht geschlossen werden. 2. Aufrechterhaltung der Datenbankverbindung: Eine andere Möglichkeit wäre es, die Datenbank-Verbindungen von einer externen Komponente aufrechterhalten zu lassen und sie dem Webserver zur Verfügung zu stellen. Als typisches Beispiel sei hier JPernLite [YK99] genannt, das mit Hilfe solcher externer Komponenten weitreichende Unterstützung für Transaktionen im Webumfeld bietet. Beide Möglichkeiten erfordern eine Anpassung der normalen Web-Architektur, entweder durch eine Modifikation des Webservers oder die Hinzunahme weiterer, externer Komponenten. Die übliche Web-Infrastruktur wird also durch eine an die speziellen Bedürfnisse angepasste Infrastruktur ersetzt. Hohe Anforderungen an die Infrastruktur verhindern aber eine größere Verbreitung solcher Systeme und insbesondere ein Vordringen in Massenangebote kommerzieller Webhosting-Provider. Diese bilden immer noch Grundlage der meisten Webanwendungen und 2 1.1 Motivation setzen auf verbreitete und leicht wartbare Standardkomponenten. Skriptsprachen wie PHP oder ASP.NET implementieren die Anwendungslogik und bieten Zugriff auf Datenbanken. In solchen Web-Anwendungen kommt üblicherweise keine oder nur eine rudimentäre Nebenläufigkeitskontrolle zum Einsatz, für die der Programmierer auf Ebene der Anwendungslogik sorgen muss. Die Komplexität dieser transaktionsunterstützenden Systeme resultiert auch aus dem Wunsch, SQL in vollem Umfang zu unterstützen, und somit die Schnittstelle für den Datenzugriff unverändert zu lassen. Gerade OLTP-Anwendungen kommen aber oft mit einer relativ kleinen Untermenge von SQL aus, da für die Formularverarbeitung im Wesentlichen einzelne Datenbankfelder gelesen und geschrieben werden müssen. 1.1.2 Ziele Wir wollen in dieser Arbeit einen entgegengesetzten Ansatz verfolgen, indem wir den Verarbeitungsmechanismus von Formularen sowie die Schnittstelle für den Datenzugriff an die Gegebenheiten des WWW anpassen. Dazu haben wir ein Framework entwickelt, dessen Name TransForm für die transaktionale Formular-Verarbeitung steht. Bei der Konzeption unseres Systems haben wir uns folgende Ziele gesetzt: 1. ACID-Garantien: Unser System soll für die Verarbeitung von Daten in Formularen die ACID-Eigenschaften gewährleisten. 2. Standardinfrastruktur: Wir wollen keine neue Infrastruktur mit externen Komponenten wie Transaktions-Servern definieren, sondern Komponenten und Modelle entwickeln, die sich nur mit Standardtechnologien umsetzen lassen und lediglich einen Webserver mit Unterstützung für eine der üblichen Skriptsprachen voraussetzen. 3. Integration: Unser System soll dabei kompatibel zu bewährten Programmiersprachen und Entwicklungs-Frameworks für Webanwendungen bleiben. Wir wollen die Schnittstellen von TransForm so gestalten, dass sich der Datenzugriff überall integrieren lässt, entweder durch fertige Komponenten oder durch maßgeschneiderte Lösungen. 4. Formulare: Als zentraler Aspekt soll der Formularbegriff unseres Systems über den von HTML hinausgehen. Web-Anwendungen sollen sich einerseits aus solchen Formularen zusammensetzen lassen und andererseits über Formulare leicht in andere Webseiten integrieren lassen, was dem integrativen Gedanken des Web 2.0 entspricht. 5. Unterstützung verschiedener Datenbanksysteme: Unser System soll nicht auf eine bestimmte Datenbank festgelegt sein. Das Hauptaugenmerk liegt deshalb nicht auf einer möglichst guten Unterstützung von relationalen Datenbanken und SQL, sondern auf der Integration von unterschiedlichen Datenquellen auf einheitliche Art und Weise. 3 Kapitel 1 Einleitung 1.2 Der TransForm-Lösungsansatz TransForm definiert eine Datenbankschnittstelle, die auf die Verarbeitung von Formulardaten in Transaktionen zugeschnitten ist. Neben einem Web-Service sieht TransForm eine spezielle Art von Formularen als Grundlage dieser Schnittstelle vor, die für die Ausführung einzelner Transaktionsschritte auf den Web-Service zurückgreifen und die Grenzen von Transaktionen definieren. Der Webservice schlüpft dabei in die Rolle eines Transaktionsservers, der über eine HTTPbasierte Schnittstelle ein an das WWW angepasstes Transaktionsmodell implementiert. Als Wrapper für Datenquellen wie relationale Datenbanken oder Dateisysteme bietet er neben einfachen Lese- und Schreibzugriffen auf die Daten auch Operationen für die TransaktionsSteuerung an. Der Dienst ist dabei in gewisser Weise ein leichtgewichtiger Transaktionsserver, da er den Transaktionsmechanismus der Datenbank dazu ausnutzt, um die ACIDEigenschaften seines Transaktionsmodells zu gewährleisten. Die Formularverarbeitung in TransForm ist in Abbildung 1.2 schematisch dargestellt. Die Abbildung zeigt eine Webseite mit einem TransForm-Formular, dessen komplette Verarbeitung mittels unterschiedlicher HTTP-Anfragen an den Web-Service erfolgt. Das Formular wird also zur Verarbeitung nicht mehr komplett an den Webserver übertragen. Die Verarbeitung erfolgt in mehreren kleinen Schritten, deren Ergebnisse jeweils direkt in der aktuellen Seite dargestellt werden, ohne diese durch eine neue Seite ersetzen zu müssen. Jedes Formularelement ist direkt mit einem Datenobjekt verknüpft und leitet einzelne Verarbeitungsschritte wie das Schreiben von geänderten Werten in direkter Reaktion auf Benutzer-Events an den Webservice. Da dieser mit jedem Schritt auch Informationen über den Transaktionszustand zurückgeben kann, können Benutzer schon während der Formularverarbeitung auf eventuelle Konflikte hingewiesen und zum Scheitern verurteilte Transaktionen frühzeitig abgebrochen werden. Erst mit dem letzten Schritt, dem Commit, werden die Effekte der Transaktion in der Datenbank sichtbar. Damit der Web-Service die ACID-Eigenschaften garantieren kann, ist es natürlich entscheidend, dass alle Datenzugriffe über ihn erfolgen und keine Daten ohne sein Wissen verändert werden. Der Zugriff auf den Webservice muss aber nicht ausschließlich über Formulare aus dem Browser heraus erfolgen. Beispielsweise könnte auch ein Verwaltungsprogramm für die Datenbank in Java geschrieben sein solange es die Web-Service-Schnittstelle für den Datenzugriff verwendet. In der Abbildung 1.2 ist die linke server action ausgegraut dargestellt, da sie als Webserverprozess, der die TransForm-Seite ausliefert, nicht auf den Web-Service zugreift und die Seitengenerierung somit unabhängig vom Zustand der Datenbank erfolgt. Deshalb muss das Formular zunächst die Transaktion starten und anschließend die Initialwerte aller Formularelemente auslesen. Prinzipiell können Transaktionsstart sowie das Auslesen der Initialwerte schon von dieser server action übernommen werden, solange dazu der Web-Service verwendet wird und der Transaktions-Zustand in die Formulardefinition einfließt. 4 1.2 Der TransForm-Lösungsansatz Abbildung 1.2: Der Formularverarbeitungsmechanismus von TransForm. Transparenz Es kann dabei für Benutzer verborgen bleiben, dass nicht der übliche Formularverarbeitungsmechanismus zum Einsatz kommt. Dazu müssen alle Kontrolloperationen transparent bleiben, was auch problemlos möglich ist, solange keine Konflikte auftreten. Transaktionsstart sowie das Auslesen der Initialwerte können automatisch erfolgen und der Commit kann hinter dem üblichen Absendemechanismus versteckt bleiben. Eventuelle Konflikte und damit verbundene Transaktionsabbrüche müssen aber dem Benutzer entsprechend erklärt werden. Datenmodell Die Grundlage des TransForm-Konzepts ist ein abstrahiertes Datenmodell, das die Datenbank in logische Datenobjekte aufteilt und in XML modelliert. Als Anfragesprache kommen dabei spezielle XPath-Ausdrücke zum Einsatz, über die Datenobjekte spezifiziert werden, die entweder gelesen oder geschrieben werden können. Bei relationalen Datenbanken werden diese Ausdrücke in eine select-project-join-Anfragesprache als Untermenge von SQL übersetzt. Damit wird natürlich nicht die Mächtigkeit von SQL erreicht. Für die Formularbearbeitung entstehen aber zwei entscheidende Vorteile. Einerseits können die Lese- bzw. Schreibzugriffe automatisch erzeugt werden, wenn jedes Formularelement mit einem solchen Objekt des Datenmodells verknüpft ist. Andererseits können Konflikte effizienter erkannt werden, da keine SQL-Anfragen oder andere native Anfragesprachen analysiert werden müssen. Das XML-Modell und die Struktur der XPath-Ausrücke können so entworfen werden, dass betroffene Datenobjekte relativ leicht ermittelt werden können. Formulare Der Umgang mit dieser ungewohnten Datenbankschnittstelle wird über spezielle TransForm-Formulare wesentlich erleichtert, da diese die Präsentation und Bearbeitung der Da- 5 Kapitel 1 Einleitung <html> <head> <script type="text/javascript " src="tf. js "/> </head> <body onload="transform();"> <h1>Daten Freiburg</h1> <tf:form service="http://tf .net/pfad/zu/service" protocol="opt"> <tf:begin type="hidden" autostart="true" /> Name: <tf:input xpath="/mondial/city[id=’FR’]/@name" /> Einwohnerzahl: <tf:input xpath="/mondial/city[id=’FR’]/@population" /> <tf:commit type="button" label="sichern" /> <tf:messages></tf:messages> </tf:form> </body> </html> Abbildung 1.3: Ein erstes Beispiel einer Webseite mit TransForm-Formularen. ten im Browser weitestgehend automatisieren. Ähnlich wie normale HTML-Formulare werden sie über Tags direkt im Markup der Seite definiert. Da der Browser diese speziellen Tags nicht verstehen kann, übersetzt ein Javascript-basierter Controller diese in Eingabefelder oder andere im Browser darstellbare HTML-Elemente und kommuniziert mit dem Web-Service gemäß den Regeln unseres Systems. Dabei nehmen Formularelemente von gewöhnlichen Eingabeelementen über JavaScript-basierte Schieberegler bis hin zu Elementen, die Seitenbereiche dynamisch nachladen, eine große Bandbreite ein. Diese Tags bilden die Programmier-Schnittstelle für den Anwendungsprogrammierer. Sie enthalten deshalb alle für die Umsetzung nötigen Informationen, wie die URL des WebServices oder Objekte des Datenmodells, mit denen die Formularelemente verknüpft sind. Als kleinster gemeinsamer Nenner der Webanwendungsentwicklung sind Tags die ideale Grundlage für die Integration in andere Systeme. 1.2.1 Ein einführendes Beispiel Abbildung 1.3 zeigt ein einfaches Beispiel einer TransForm-Webseite. Im Header wird die TransForm-Bibliothek eingebunden, in der der Controller definiert ist. Im Body-Tag ist im onload-Attribut eine Funktion hinterlegt, die aufgerufen wird, sobald die Seite geladen ist. Diese Funktion startet den Controller, der zuerst den Quelltext der Seite nach TransFormTags durchsucht und diese zum Leben erweckt. Unser Beispiel enthält ein solches Formular, das auf einen Web-Service an der im service- 6 1.2 Der TransForm-Lösungsansatz (a) Formular während der Bearbeitung (b) Resultat der Formularverarbeitung Abbildung 1.4: Die Darstellung der TransForm-Beispielseite im Browser. Attribut angegebenen Adresse zugreift und der in diesem Fall ein optimistisches Scheduling-Protokoll verwenden soll. Das Formular enthält zwei Eingabefelder, die als einziges Attribut das Datenobjekt enthalten, auf das sie zugreifen sollen. Es handelt sich dabei um die Attribute name sowie population der Tupel der city-Relation der mondial-Datenbank, die in ihrer id-Spalte den Wert ’FR’ enthalten. Das <tf:begin>-Tag enthält Optionen für den Transaktionsstart. Da sein Typ als hidden definiert ist, wird es als verstecktes Formularfeld auf der Seite nicht visuell repräsentiert. Es sorgt allerdings über das Attribut autostart dafür, dass der Controller automatisch eine Transaktion startet und die Eingabefelder ihre Startwerte einlesen. Wie der Transaktionsabschluss gehandhabt werden soll, ist im <tf:commit>-Tag spezifiziert. Wie es das typeAttribut festlegt, erzeugt der Controller einen Button, den er gemäß des label-Attributs mit ’sichern’ beschriftet. Der Benutzer kann nun das Commit der Transaktion anfordern, indem er diesen Knopf anklickt. Das letzte Tag, das der Controller berücksichtigen muss, ist <tf:messages>, über das der Benutzer über den aktuellen Transaktionszustand informiert wird. Wie diese Situation sich im Browser nach dieser Initialisierung durch den Controller darstellt, ist in Abbildung 1.4(a) dargestellt. Abbildung 1.4(b) zeigt die Seite nach Abschluss der Transaktion, in der die Einwohnerzahl auf 217.547 geändert wurde. Wie aus dem Nachrichtenfeld ersichtlich ist, konnte die Transaktion erfolgreich abgeschlossen werden. 1.2.2 Systembedingte Nachteile Um in TransForm ACID-Transaktionen ohne zusätzliche, externe Komponenten verwirklichen zu können, mussten natürlich einige Kompromisse eingegangen werden. Diese gehen insbesondere zu Lasten der Mächtigkeit der Anfragesprache sowie der Performance. 7 Kapitel 1 Einleitung Als Anfragesprache dienen einfache Lese- und Schreiboperationen auf Datenobjekte. Die so definierte Anfragesprache ist im Vergleich zu Anfragesprachen wie SQL eingeschränkt und erzielt nicht die gleiche Mächtigkeit. Neben dem erhöhten Aufwand für den Datenzugriff, bei dem wir als zusätzlichen Schritt unsere Ausdrücke in die native Anfragesprache übersetzen müssen, wirkt sich auch die Transaktionsverwaltung und Konflikterkennung, die über dem Transaktionsmechanismus des Datenbanksystems implementiert sind, negativ auf die Performance aus. Da in jedem Transaktionsschritt Kontakt zum Webservice aufgenommen wird, entsteht natürlich auch eine größere Belastung für den Webserver als beim herkömmlichen Formularverarbeitungsmechanismus aus Abbildung 1.1. 1.3 Gliederung Kapitel 2 soll zunächst Hintergrundinformationen zu den beiden Schwerpunktgebieten dieser Arbeit liefern, dem WWW sowie der Transaktionsverarbeitung. Dabei werden insbesondere die Schwierigkeiten näher erläutert, welche die grundlegende Architektur des Web der Anwendungsentwicklung sowie der Transaktionsverarbeitung auferlegt. Im Kapitel 3 wird das TransForm-Framework im Ganzen beschrieben. Dazu werden Architektur, grundlegende Modelle sowie einzelne Komponenten und deren Schnittstellen vorgestellt und gezeigt, wie diese im Zusammenspiel die ACID-Eigenschaften garantieren. Eine Datenbank, in der ein TransForm-Dienst die persistenten Daten speichert, wird in unserer Terminologie als Backend bezeichnet. In Kapitel 4 diskutieren wir die Eignung unterschiedlicher Datenbanksysteme als TransForm-Backends und stellen neben zwei unterschiedlichen Möglichkeiten für relationale Datenbankbackends ein Dateisystem-basiertes Backend vor. In Kapitel 5 entwickeln wir verschiedene Scheduler. Dazu rekapitulieren wir zunächst einige Konzepte aus der Serialisierbarkeitstheorie und entwickeln ausgehend von bewährten Strategien geeignete Scheduling-Protokolle für TransForm-Systeme. Zum Abschluss werden noch die Möglichkeiten verteilter Transaktionen innerhalb eines TransForm-Systems diskutiert. Kapitel 6 behandelt die tagbasierte Definition von Formularen sowie deren Umsetzung in Browsern und vermittelt die grundlegende Idee, wie sich ganze Webanwendungen mit Hilfe von TransForm-Formularen entwickeln lassen. Im Kapitel 7 führen wir eine prinzipielle Auswertung der Performance von TransFormSystemen durch und ziehen Vergleiche zu Webanwendungen, die Formulare auf die herkömmliche Art verarbeiten. Kapitel 8 fasst schließlich die Arbeit zusammen. Dabei wird ein Vergleich zu verwandten Arbeiten gezogen und noch einmal der Beitrag von TransForm herausgestellt. 8 Kapitel 2 Hintergrund Da diese Arbeit in der Schnittmenge des WWW und der Transaktionsverarbeitung liegt, wollen wir zunächst einen Überblick über beide Gebiete liefern und relevante Technologien, Systeme, Konzepte und Forschungsarbeiten vorstellen. 2.1 Das World Wide Web Seit seiner Einführung als Hypertextsystem mit statisch in Dateien abgelegten Inhalten und Hyperlinks als einziger Interaktionsmöglichkeit hat das World Wide Web [BL96] eine große Wandlung durchlaufen und bildet mittlerweile die vielleicht größte Anwendungsplattform. Die Gründe für diese Entwicklung liegen dabei weniger in den technologischen Vorzügen des Web als Plattform, sondern vielmehr in der Allgegenwart von Webbrowsern, die sich zu einem universellen und plattformunabhängigen Anwendungsfrontend entwickelt haben. 2.1.1 Grundlagen & Technologien Das World Wide Web wurde im Wesentlichen von Tim Berners-Lee als Weiterentwicklung des Hypertext-Systems Enquire am Genfer Forschungszentrum für Teilchenphysik CERN entwickelt [BLCGP92], wo es um 1990 seinen endgültigen Namen erhielt und die ersten Versionen seiner drei Säulen entstanden: 1. HTTP, das Protokoll für die Kommunikation zwischen Web-Clients und Web-Servern (Hypertext Transfer Protocol [FGM+ 99]). 2. Ein einheitliches Adressierungsschema für beliebige Datenquellen - das Schema der sogenannten URIs (URI: Universal Resource Identifier [BL94]). 3. HTML als Auszeichnungssprache für Web-Dokumente (HTML = Hypertext Markup Language). Berners-Lee schrieb auch die erste Web-Server-Software und stellte Ende des Jahres 1990 unter dem Namen info.cern.ch die ersten, in HTML geschriebenen Web-Seiten der Welt zur 9 Kapitel 2 Hintergrund Verfügung. Zunächst fand das Projekt vor allem unter wissenschaftlichen Institutionen Verbreitung. Erst mit der Veröffentlichung des Mosaic-Browser 1993 wurde das WWW auch für Privatanwender verfügbar. Zunächst schufen Netscape mit ihrem 1994 veröffentlichten Navigator sowie später Microsoft mit dem Internet Explorer De-Facto-Standards für das WWW, indem nach Belieben neue und nicht standardisierte Features in die Browser integriert wurden. Mittlerweile existiert mit dem W3-Konsortium eine akzeptierte Institution, die sich um die technischen Grundlagen und Standards im Web kümmert. Interaktion mit Formularen Berners-Lees ursprüngliche Idee des Web wich durchaus von dessen tatsächlicher Entwicklung ab, die von nur zum Lesen gedachten Web-Browsern geprägt wurde. Eigentlich sollten Web-Seiten online editierbar sein, sofern entsprechende öffentliche Schreibrechte vergeben waren. Diese Ideen mündeten später in WebDAV [EJWG99], einer Erweiterung von HTTP. Zunächst setzten sich jedoch andere Konzepte durch. Mit der Einführung der CGI-Schnittstelle [NCS] durch den NCSA Server 1993 in Kombination mit HTML-Formularen wurde die heute noch gültige Grundlage für interaktive Webanwendungen geschaffen. CGI definiert eine Schnittstelle für den Aufruf externer Programme, die im Wesentlichen aus Variablen sowie Ein- und Ausgabekanälen besteht. Der Browser fungiert dabei als Gateway für den Aufruf dieser CGI-Programme über eine URL. So lassen sich Webseiten dynamisch erzeugen. Variablen sind zeichenkettenbasierte NameWert-Paare, die üblicherweise aus den Namen und Inhalten von Formularelementen erzeugt werden. Obwohl CGI-Programme prinzipiell in jeder allgemeinen Programmiersprache geschrieben werden können, wird oft Perl in einem Atemzug mit CGI genannt, da umfangreiche Bibliotheken die Programmierung erleichtern. Mittlerweile wurde der Formularbegriff durch den W3C-Standard XForms [W3C00] wesentlich erweitert. XForms folgt dem Model-View-Controller-Muster und sieht eine Trennung von Daten-Modellierung, Darstellung und Steuerung vor. Als Bestandteil des noch in der Entwicklung befindlichen XHTML-2.0-Standards findet XForms allerdings aktuell lediglich über Plugins Unterstützung in Browsern. Das „Web 2.0“ Mit dem Platzen der Internetblase um die Jahrtausendwende entstanden bzw. verbreiteten sich Technologien wie XML, SOAP oder Ajax, die später den Begriff des „Web 2.0“ prägten. Neben dem Gedanken des sozialen „Mitmach“-Web, bei dem Inhalte nicht mehr zentral über große Anbieter sondern vernetzt und dezentral, beispielsweise über Weblogs, verbreitet werden, steht das Schlagwort auch für eine neue Generation von Webanwendungen. Merkmale dieser neuen Webanwendungen sind eine Benutzerschnittstelle, die der von Desktopanwendungen nachempfunden ist, und die Integration in andere Seiten als 10 2.1 Das World Wide Web sogenannte Mashups. Google Maps oder YouTube bilden klassische Anwendungsbeispiele. Aus technischer Sicht steht „Web 2.0“ für eine Kombination aus unterschiedlichen Technologien wie Web-Service-APIs, Ajax oder Abonnement-Dienste wie RSS, die im Gegensatz zu älteren Technologien für reichhaltige Webanwendungen wie Java-Applets oder ActiveX in allen modernen Browsern direkt zur Verfügung stehen. Der Begriff Ajax (Asynchronous JavaScript and XML) wurde in [Gar05] geprägt und steht für ein ganzes Paket von Technologien für die asynchrone, XML-basierte Datenübertragung zwischen Browser und Webserver. Während eine Webseite im Browser dargestellt wird, tauscht ein JavaScript-Programm im Hintergrund asynchron mit einem Webserver Daten aus. Dabei handelt es sich in der Regel um XML, das mittels JavaScript geparst und in den DOM-Baum der Webseite integriert wird. Mit der JavaScript Object Notation hat sich mittlerweile eine leichtgewichtigere Alternative zu XML etabliert. Da HTTP-Anfragen durchgeführt werden, ohne dabei eine Seite komplett neu laden zu müssen, entsteht der Eindruck einer besseren Performance. Es werden lediglich einzelne Seitenbereiche bei Bedarf neu dargestellt. Da HTTP-Anfragen asynchron durchgeführt werden ohne den Browsern zu blockieren, werden Wartezeiten von Benutzern oft nicht wahrgenommen. Die clientseitige Skriptsprache JavaScript wurde ursprünglich für den Netscape Navigator entwickelt. Sie ist heute aber als ECMAScript [ECM99] standardisiert und wird von den meisten Browsern weitgehend unterstützt. Die Namensähnlichkeit zu Java ist allerdings irreführend. Obwohl die Syntax durchaus Ähnlichkeiten zu der von Java aufweist, gibt es grundlegende Unterschiede wie beispielsweise eine prototypbasierte anstelle einer klassenbasierten Objektorientierung. Eine andere Möglichkeit, Code im Browser zur Laufzeit auszuführen, ist die Skriptsprache des verbreiteten Flash-Plugins. Obwohl Flash in erster Linie für Animationen in Webseiten gedacht ist, lassen sich damit die gleichen Dinge bewerkstelligen wie mit JavaScript. Web-Services Das serverseitige Gegenstück zu Ajax bilden im neuen Web die Web-Services oder WebDienste. Ein Web-Service ist für die maschinelle Verarbeitung durch Rechner und nicht für menschliche Benutzer gedacht und sieht deshalb eine automatisierte Nutzung von Funktionen auf entfernten Rechnern vor. Es haben sich zwei grundsätzliche Arten von Web-Services etabliert. SOA-Web-Services Die service-orientierte Architektur [He] ist ein Architekturstil, der eine Menge voneinander unabhängiger, lose gekoppelter Dienste vorsieht. Ein Dienst wird dabei von einem Dienstanbieter für einen Konsumenten erbracht. Wesentliches Merkmal der SOA ist eine plattformunabhängige Kapselung von persistenten Daten durch Dienste. Dabei haben sich drei XML-basierte Standards als sogenanntes Web-Service-Dreieck eta- 11 Kapitel 2 Hintergrund bliert. Sie bilden dabei die wichtigsten Teile der Zusammenarbeit zwischen Anbieter und Konsument ab: Das Zusammenfinden, das Binden sowie den Datenaustausch. Der Verzeichnisdienst UDDI dient der Registrierung von Web Services und ermöglicht das dynamische Finden des Web-Services durch den Konsumenten. WSDL erklärt die Benutzung eines Dienstes und standardisiert die Beschreibung der unterstützten Methoden und deren Parametern. SOAP ist schließlich das Kommunikationsprotokoll, über das der eigentliche Dienst-Aufruf abgewickelt wird. REST-basierte Web-Services Eine andere Art von Web-Services ist aus dem Begriff des REpresentational State Transfer oder kurz REST entstanden, den Roy Fielding in seiner Dissertation [Fie00] als Architekturstil für Web-Anwendungen einführt. Dabei steht REST weder für ein Produkt noch für einen Standard, sondern beschreibt, wie bestehende Standards in einer dem Web gerechten Weise eingesetzt werden können. Die grundlegende Idee REST-basierter Web-Services sind Ressourcen, die über eine URI identifiziert werden und beliebig viele Repräsentierungen besitzen. REST-Web-Services sind einfach gehalten und setzten auf verbreitete Standard-Technologien wie HTTP für die Schnittstellen und XML als Nachrichtenformat. Dabei wird die HTTP-Methode GET nur für das Auslesen der Repräsentation einer Ressource verwendet. Andere Methoden werden für das Ändern (POST), das Erzeugen (PUT) oder das Löschen (DELETE) von Repräsentationen benutzt. Das World Wide Web stellt selbst eine REST-Anwendung dar. Viele Suchmaschinen, Shops oder Buchungssysteme sind ohne Absicht bereits als REST-basierter Web Services verfügbar. 2.1.2 Das WWW als Anwendungsplattform Der Begriff Webanwendung kann einerseits für ein Internet-basiertes Geschäftsmodell stehen, sich andererseits aber auch auf die Lauffähigkeit von Anwendungen in einem WebBrowser beziehen. Die Abgrenzung von Webanwendungen zu klassischen Websites oder Web-InformationsSystemen ist dabei schwierig. In [IBV98] wird eine Klassifizierung nach Verwendung in organisatorischen Einheiten vorgenommen: Intranets für organisationsinterne Arbeiten, Web-Präsenzen bzw. Webauftritte für die Erreichung von Kunden, Electronic-Commerce für die Interaktion mit Kunden und Extranets für die B2B-Kommunikation. Architektur Die grundlegende Architektur ist dabei allerdings für alle Arten von Webanwendungen die gleiche, egal ob es sich um Ajax-Anwendungen, um eine klassische, formularverarbeitende Webanwendung oder um dynamisch erzeugte Webseiten handelt. Alle sind Client/ServerAnwendungen, bei denen ein Webbrowser die Rolle des Clients einnimmt, der mit einem 12 2.1 Das World Wide Web HTMLSeite HTMLSeite HTTPAnfrage HTTPAntwort Web-Server Prozess an URI CGIProgramm Datenbank Abbildung 2.1: Der grundlegende HTTP-Anfrage-Antwort-Zyklus. Webserver über HTTP kommuniziert. Dieser implementiert nun entweder direkt oder in Verbindung mit weiteren Komponenten die Anwendungslogik. Die konkrete Architektur kann dabei eine große Bandbreite von statischen Web-Sites als reine Client/Server-Systeme bis hin zu komplexen n-tier-Systemen einnehmen. Den wichtigsten Spezialfall bildet dabei ein geschichtetes System mit den drei Ebenen Browser, Webserver und Datenbankserver. Die drei im letzten Abschnitt vorgestellten Pfeiler des WWW bilden dabei natürlich auch die Basistechnologien jeder Webanwendung. Anfrage-Antwort-Zyklus als grundlegendes Modell Das Grundprinzip ist der in Abbildung 2.1 dargestellte Anfrage-Antwort-Zyklus, bei dem der Browser, ausgelöst durch eine Benutzerinteraktion, eine Webseite vom Webserver anfordert und diese dem Benutzer anzeigt. Der Webserver sendet dazu entweder ein statisches Dokument zurück oder ruft dazu über die CGI-Schnittstelle ein Programm auf, das die Antwort dynamisch erzeugt. Eine Webanwendung besteht nun prinzipiell aus vielen solchen aufeinanderfolgenden Zyklen, die im Allgemeinen über Hyperlinks oder Formulare miteinander verbunden sind. Konzeptuell besteht eine Webanwendung allerdings aus lediglich einem Programm wie es auch in Abbildung 2.2 dargestellt ist. Daraus ergeben sich zwei prinzipielle Probleme: 1. Gewährleistung der globalen Kohärenz: Die vielen separaten Programme müssen ein kohärentes konzeptuelles Programm bilden. Das Gesamtverhalten einer Webanwendung ist über eine Anzahl eigenständiger Programme verteilt und hängt von der Interaktion dieser untereinander ab. Das erschwert die Analyse, Erstellung und Wartung des konzeptuellen Programms. 2. Anwendungszustand: Da HTTP ein zustandsloses Protokoll ist, muss der Anwendungszustand auf andere Art und Weise zwischen den einzelnen Anfrage-AntwortZyklen bewahrt werden. Üblicherweise werden dazu über Cookies, versteckte Formularfelder oder URL-Codierungen die für den Zugriff auf die eigentlichen Daten in der Datenbank benötigten Informationen übertragen. 13 Kapitel 2 Hintergrund HTMLSeite HTMLSeite WebserverProgramm HTMLSeite HTMLSeite WebserverProgramm HTMLSeite Anwendung WebserverProgramm und Anwendung HTMLSeite Abbildung 2.2: Der skript- und seitenbasierte Ansatz (links) sowie der sessionbasierte Ansatz (rechts). Für die Implementierung von Webanwendungen gibt es viele unterschiedliche Sprachen und Frameworks, die sich auf unterschiedlichen Abstraktionsebenen einordnen lassen. Dabei kann man drei prinzipielle Ansätze unterscheiden, je nachdem welche Konzepte im Zentrum der Anwendungsentwicklung stehen: 1. Skripte, 2. Webseiten oder 3. Sessions. Auf unterster Ebene stehen dabei die aus dem letzten Abschnitt bekannten CGI-Programme. Der skriptbasierte Ansatz Zentrales Konzept dieses Ansatzes ist ein Skript, das sozusagen als Seiteneffekt seines Ablaufs als Ausgabe eine Webseite erzeugt. Als Schnittstelle kommt erwähntes Common Gateway Interface [NCS] zum Einsatz, über das der Webserver die Anfrage dem Skript vermittelt. Ein großer Nachteil von CGI-Programmen ist ihre relativ schlechte Performanz, weil der Webserver jeden CGI-Aufruf in einem eigenen Prozess ausführt. FastCGI umgeht diese Probleme, indem in jedem Prozess mehrere Aufrufe bearbeitet werden. Es konnte allerdings trotz deutlicher Vorteile gegenüber CGI nie annähernd dessen Bedeutung erlangen, da sich gleichzeitig einfacher zu handhabende Lösungen des seitenbasierten Ansatzes etablieren konnten. Der seitenbasierte Ansatz Der seitenbasierte Ansatz unterscheidet sich nicht grundsätzlich vom skriptbasierten. Allerdings stehen hier Webseiten im Vordergrund, in die ausführbarer Code eingebettet ist. Hier entsteht die Webseite also nicht als Seiteneffekt. Der Code ist in spezielle Bereiche einer Webseite integriert und wird bei der Auslieferung der Seite vom Webserver interpretiert. Es gibt eine ganze Reihe sehr populärer Sprachen, die diesen Ansatz verfolgen, in erster Linie die Open-Source-Sprache PHP sowie Active Server Pages (ASP) und Servlets (JSP). Der Webserver muss speziell konfiguriert werden, damit er gewöhnliche HTML-Dateien von solchen mit eingebettetem Code unterscheiden kann. 14 2.1 Das World Wide Web Die Performance kann im Vergleich zu CGI-Programmen deutlich gesteigert werden, da der Interpreter der Skriptsprache als Bibliothek eingebunden und Skripte in Threads des Webservers ausgeführt werden können. Der sessionbasierte Ansatz Ein naheliegender Ansatz, das Problem der globalen Kohärenz zu lösen, ist der sessionbasierte Ansatz, bei dem in einem Prozess nicht mehr nur ein Anfrage-Antwort-Zyklus verarbeitet wird, sondern alle Zyklen, die zu einem Programm bzw. einer Session gehören. Dieser Ansatz ist in Abbildung 2.2 auf der rechten Seite abgebildet, wo ein Prozess mehrere Seiten ausliefert. Dieser Ansatz wurde zuerst im Mawl-Projekt [ABBC99] verwendet, bei dem eine Webanwendung als Ansammlung von Sessions betrachtet wird, die jeweils in einem einzigen Programm implementiert sind. Dieser Ansatz hat zu der Entwicklung von verschiedenen domänenspezifischen Sprachen geführt, die den höchsten Abstraktionsgrad für die Entwicklung von Webanwendungen bilden. Einige Vertreter dieser Sprachen stellen wir im nächsten Abschnitt vor. Dieser Ansatz erfordert allerdings nicht nur die Anpassung der Webserver-Konfiguration, sondern benötigt spezielle Webserver, wie beispielsweise Web-Container bzw. EJB-Container innerhalb der im kommerziellen Bereich wichtigen Java-Plattform J2EE. Das MVC-Entwurfsmuster Ein häufig im Zusammenhang mit Webanwendungen erwähntes Entwurfsmuster ist das „Model-View-Controller”-Muster, bei dem die Sicht das Modell (Daten) repräsentiert. Ein Controller sorgt dafür, dass Änderungen an der Sicht dem Modell bzw. an dem Modell der Sicht mitgeteilt werden. Die klassische Anwendung sind GUIs. Im Kontext von Webanwendungen entspricht dabei das Browserfenster der Sicht und die Datenbank dem Modell. Leider ist die Anwendung dieses Entwurfsmusters nicht ganz zutreffend, da die Sicht immer den aktuellen Zustand des Modells widerspiegelt und deshalb über Änderungen durch den Controller informiert werden sollte. Gerade das ist allerdings bei Webanwendungen nicht möglich, da die Aktivität, also die Initiierung der Kommunikation, immer vom Browser ausgehen muss. Der Webserver nimmt eine rein passive Rolle ein, in der er auf Anfragen von Clients wartet. Bestenfalls kann ein Browser ermitteln, ob seine dargestellte Sicht noch dem Modell entspricht. 2.1.3 Das WWW als Forschungsgebiet Die Diskrepanz zwischen dem Interesse am WWW als Anwendungs-Plattform und seinen technologischen Defiziten hat ein riesiges Forschungsgebiet entstehen lassen. Aus Sicht der Datenbankgemeinschaft sind dabei zwei Gesichtspunkte interessant. Wenn man das WWW 15 Kapitel 2 Hintergrund selbst als Datenbank betrachtet, müssen die bekannten Konzepte für die Modellierung, Anfragen und Ähnliches angepasst werden. Auch muss die Integration des neuen, semistrukturierten Datenmodells von XML mit dem bewährten relationalen Modell untersucht werden. Die Modellierung und Implementierung von Webanwendungen wird allerdings auch in der Softwaretechnik untersucht und hat zu der Entwicklung von domänenspezifischen Sprachen geführt. Domänenspezifische Sprachen Domänenspezifische Sprachen sind Programmiersprachen, die im Hinblick auf die Anwendungen einer speziellen Domäne entworfen sind. Für Webanwendungen gibt es eine Reihe von solchen Sprachen, die Unzulänglichkeiten der Web-Plattform vor dem Programmierer verbergen und die Anwendungsentwicklung der von Desktopanwendungen angleichen. Sie verfolgen dabei meist den sessionbasierten Ansatz und geben Laufzeitgarantien für die Wohlgeformtheit und Validität der XML- bzw. HTML-Ausgabe, die Korrektheit des Kontrollflusses, die Typkorrektheit oder die globale Konsistenz von Parametern. Einer der ersten Ansätze war dabei das Bigwig-Projekt [BMS02]. Bigwig ist eine eigenständige, C-artige domänenspezifische Sprache, die im Wesentlichen einen Sessionbegriff einführt und zum Kompilierzeitpunkt die Wohlgeformtheit von XHTML-Fragmenten garantiert. Dazu ist XHTML als Datentyp direkt in die Sprache integriert, der wie bei TemplateSystemen Platzhalter enthalten kann, die über spezielle Operationen andere Fragmente integrieren und so Dokumente dynamisch erzeugen können. Sowohl die RPC-ähnliche Interaktion der Clients mit dem Server als auch deren Kontrollfluss wird direkt im Quellcode der Anwendung definiert. JWig [CMS03] ist das Nachfolgeprojekt von Bigwig und ersetzt im Wesentlichen die eigenständige Sprache des Vorgängers durch Java. Dabei wurden die grundlegenden Ideen und Konzepte weitgehend übernommen bzw. an Java angepasst. Es existieren auch verschiedene Ansätze für funktionale domänenspezifische Sprachen: WASH [Thi05] ist dabei der wohl verbreitetste Ansatz. Es bietet in Haskell ein High-LevelInterface für die Programmierung von Webseiten und unterstützt dabei Konzepte wie Sessions, XHTML-Validierung, Typsicherheit und Konsistenz von Parametern. In [Thi06] wird eine Implementierung von WASH innerhalb eines Webservers vorgestellt. Hier wird ein sessionbasierter Ansatz verfolgt, wodurch WASH-Programme effizienter verarbeiten können, da eine komplette Session innerhalb eines Threads im Webserver abgearbeitet wird. Formularvalidierung Normalerweise wird erst serverseitig überprüft, ob Formularinhalte ihrem Typ genügen. Im Rahmen des Bigwig-Projekts ist mit PowerForms [BMRS00] ein Framework für die clientseitige Typprüfung von Formularfeldern entstanden. Dabei werden Inhalte von Formularfeldern mittels JavaScript überprüft und die notwendigen Javascriptprogramme können automatisch erzeugt und in den Browser integriert werden. Es war das erste Projekt, das 16 2.1 Das World Wide Web dabei auf Standard-HTML-Formulare setzte, während frühere clientseitige Lösungen wie Active Forms [TB96] auf Tcl-Applets beruhen oder wie Web Dynamic Forms [GL97] ein eigenes Formularmodell innerhalb von Java-Applets implementieren. Das WWW aus Sicht der Datenbankgemeinschaft Aus Sicht der Datenbankgemeinschaft ist das WWW eine große verteilte Datenbank, die im Vergleich zu relationalen Systemen andere Modelle und Anfragekonzepte benötigt. So entstand das semistrukturierte Datenmodell und daraus XML mit seinen bekannten Anfragesprachen wie XPath und XQuery. Anfragen, die sich über das gesamte Web erstrecken, sind die klassische Domäne von Suchmaschinen. Webseiten werden hier als Knoten von Graphen betrachtet, bei denen die Kanten den Links entsprechen. Suchmaschinen kombinieren dabei die klassische inhaltsbezogene Suche und die Suche auf der Struktur von Webseiten. Aber auch für die Erzeugung bzw. Verwaltung von Web-Sites ist die Modellierung der Struktur und Definition von Integritätsbedingungen an diese Struktur sinnvoll. Strudel [FFK+ 98] ist eine der wichtigsten Arbeiten, die Datenbankkonzepte auf die Web-SiteErzeugung anwenden. Die Schlüsselidee ist die Trennung von 1) der Verwaltung der Daten, 2) der Erzeugung und Verwaltung der Struktur der Site und 3) der visuellen Repräsentation der einzelnen Seiten. Modellierung von Web-Anwendungen Schon früh wurde erkannt, dass die Erzeugung und das Management von Webseiten Datenmanagementprobleme sind, die von Datenbanktechnologie und deklarativer Spezifikation der Inhalte und Struktur profitieren. HDM [GPS93] hatte das Ziel, die Entwicklung von Webanwendungen weitestgehend zu automatisieren. Es bahnte den Weg für das model-driven design von Hypermedia-Anwendungen und beeinflusste spätere Arbeiten wie OOHDM [RSL99] und WebML [CFB00]. [RSL99] beschreibt die Web-Modellierung mit OOHDM, das vier Modelle definiert, die jeweils als Sicht der darunterliegenden Modellschicht definiert sind: Neben dem konzeptuellen Modell, gibt es jeweils eines für Navigation, Schnittstellen und die Hypertexterzeugung. WebML [CFB00] verfolgt eine datenorientierte Modellierungsmethode die auf das ERModell als Modellierungssprache zurückgreift und deren Stärken bei datenintensiven Webseiten liegt. Ein großer Vorteil von WebML ist die Unterstützung durch die kommerzielle Web-Entwicklungssoftware WebRatio. Template-Systeme Die Trennung von Inhalt und Layout ist auch die Idee von Template-Systemen. Dabei werden Vorlagen für das Layout eines HTML-Dokuments durch Template Engines dynamisch mit Inhalt gefüllt, der aus einer Datenbank gelesen wird. 17 Kapitel 2 Hintergrund MyXML [KK00] ist ein Beispiel einer solchen Template Engine. Die Templates sind dabei spezielle Elemente eines XML-Dokuments, die SQL-Anfragen enthalten, Loops definieren oder CGI-Parameter bereithalten können. Template-Dokumente enthalten also dynamisch erzeugten Inhalt, der mit XSL in endgültige Formate wie HTML transformiert wird. Das System erzeugt dabei automatisch den Java-Code für ein Servlet, das die enthaltenen SQLAnfragen dynamisch ausführt. Als Gegenstück auf Clientseite werden Formulare bereitgestellt [KKK02], über die Datenbankinhalte bearbeitet werden können. Relationale Datenbanken und XML Da XML die Grundlage des Datenaustauschs im E-Commerce bildet, Daten normalerweise aber in relationalen Datenbanken gehalten werden, hat sich der Import von XML und der Export nach XML bei relationalen Datenbanken als wichtiger Gegenstand der Forschung etabliert. Als XML-Publishing wird dabei der Export von Datenbankinhalten nach XML bezeichnet, der von den großen kommerziellen Datenbanksystemen in jeweils unterschiedlicher Form schon lange unterstützt wird und mittlerweile als SQL/XML im SQL:2003-Standard [EMK+ 04] enthalten ist. Dem entgegengesetzt ist der Import, also die Speicherung von XML-Dokumenten in relationalen Datenbanken. Eng damit verknüpft ist die Auswertung von XQuery- bzw. XPath-Anfragen auf solchen XML-Dokumenten mittels SQL. Es existieren zahlreiche Ansätze, von denen frühe wie [DFS99] noch mit den ersten Anfragesprachen für semistrukturierte Daten wie Lorel arbeiteten, während spätere Arbeiten [YASU01, DTCO03] direkt XPath/XQuery auswerten. XTABLES [FKS+ 02b] bzw. sein Vorgängerprojekt XPERANTO [CFI+ 00] ist eine Middleware, die auf einem beliebigen relationalen Datenbanksystem aufbaut und versucht, die Lücke zwischen XML-basiertem Datenaustausch und relationaler Datenhaltung zu schließen. Es stellt dabei ein Framework bereit, um einerseits XML-Views von relationalen Daten zu erzeugen und andererseits XML-Dokumente relational abzuspeichern. Dabei benutzt XTABLES XQuery als universelle Sprache sowohl für die Erzeugung der Sichten als auch für nahtlose Anfragen über den Sichten, den relationalen Daten sowie Metadaten und den abgespeicherten XML-Dokumenten. Mit SilkRoute [FKS+ 02a] können XML-Sichten von relationalen Daten erzeugt und angefragt werden [FMS01]. In SilkRoute wird dazu eine spezielle Sprache namens RXL für die Erzeugung eingeführt, während für Anfragen eine andere Sprache namens XML-QL [DFF+ 98] vorgesehen ist. 2.2 Transaktionsverarbeitung Geschäftsabschlüsse oder Geschäfts-Transaktionen bezeichnen in der Regel ein Wechselspiel zwischen Unternehmen untereinander oder mit Personen, bei denen Geld, Dienstleistungen, Produkte o.Ä. ausgetauscht werden. Die dafür notwendige Buchhaltung wird 18 2.2 Transaktionsverarbeitung dabei mittlerweile meist elektronisch von sogenannten Transaktionsverarbeitungssystemen (transaction processing systems, TP-Systemen [BN97]) erledigt, die für die benötigten Geschäftsabläufe eine Reihe von Transaktionsprogrammen durchführen. Eines der ersten und immer noch größten TP-Systeme war dabei das Reservierungssystem Sabre [CMM95], das Anfang der 60er Jahre von IBM und American Airlines entwickelt wurde. Heutzutage gibt es eine ganze Reihe von großangelegten TP-Anwendungen für Geschäftsfelder wie das Bankwesen oder die Bestandsverwaltung. Eine Transaktion ist dabei die Ausführung eines Transaktionsprogrammes, das für die Ausführung seiner Funktion auf eine mit vielen anderen Transaktionen gemeinsam benutzte Datenbank (shared database) zugreift. Wenn wie in obigen Anwendungsbeispielen das Ergebnis eines Transaktionsprogramms direkt erwartet wird, spricht man klassischerweise von online transaction processing (OLTP) im Gegensatz zu einem Batch-Betrieb, in dem Transaktionen offline durchgeführt werden. TP-Anwendungen werden von einem großen Spektrum von Computersystemen verarbeitet. Das können einfache PCs für Anwendungen mit direktem Zugriff auf einen (lokalen) Datenbankserver sein. Typischerweise haben wir es jedoch mit in großem Maßstab verteilten Systemen und heterogenen Komponenten zu tun. Diese Computersysteme bilden die eigentlichen TP-Systeme und bestehen neben Software eventuell aus speziell angepasster Hardware, beispielsweise, wenn Geldautomaten zum Einsatz kommen. Sie erfüllen dabei folgende drei Hauptfunktionen, die für jede Transaktion genau einmal komplett abgearbeitet werden und dabei permanente Ergebnisse erzeugen: 1. Beschaffung der Eingabe auf Seiten des Clients: Das klassische Interface sind Formulare bzw. Terminals. Möglicherweise kommen aber auch spezielle Bausteine wie Sensoren oder Barcode-Scanner zum Einsatz. Jedenfalls wird in Reaktion auf die Eingabe eine Anfrage generiert. 2. Vermittlung der Anfrage: Wenn die Anfrage bzw. der Request akzeptiert wird, muss das entsprechende Transaktionsprogramm ermittelt und aufgerufen werden. In verteilten Systemen kommt hier ein TP-Monitor zum Einsatz, der diese Vermittlung auch im Netzwerk sicher durchführt. 3. Transaktionsausführung: Schließlich erfolgt die eigentliche Verarbeitung der Daten. Dazu kommt üblicherweise eine Datenbank zum Einsatz. 2.2.1 Benutzerschnittstellen Die klassische Benutzerschnittstelle von TP-Systemen sind die Block-Mode-Terminals früherer Mainframe-Architekturen, bei denen immer ein kompletter Bildschirminhalt übertragen wurde. Obwohl solche Benutzerschnittstellen zwischenzeitlich als überholt galten, sind sie mit dem Aufkommen von Browsern als Clients für WWW-basierte TP-Systeme wieder aktuell geworden. Die Ähnlichkeit zu Web-Formularen ist nicht zu übersehen. 19 Kapitel 2 Hintergrund Im Rahmen der formularorientierten Analyse [DW04] werden solche formularbasierten Schnittstellen als Submit-Response-Style-Interfaces bezeichnet, bei denen die Mensch-Computer-Interaktion als alternierender Austausch von Nachrichten modelliert wird. Sie zeigen dem Benutzer zu jedem Zeitpunkt eine aktuelle Seite, die Current Page und erlauben dem Benutzer zwei Formen der Interaktion mit dem Interface: Page Edits und Page Changes. Page Changes sind Interaktionen, die zu einem Seitenwechsel führen. Sie tauschen die aktuelle Current Page gegen eine neue aus. Page Edits sind Interaktionen innerhalb der Current Page, bei denen Formulare ausgefüllt werden. Formulare sind dabei die einzigen editierbaren Bereiche einer Seite. Da Page Edits immer in Vorbereitung eines Page Changes erfolgen, spricht man auch von einem 2-stufigen Interaktions-Paradigma. 2.2.2 Das Transaktionskonzept Eine entscheidende Rolle in jedem TP-System spielt natürlich die Datenbank, die erst eine fehlerfreie Verarbeitung von simultanen Datenzugriffen garantiert. Dazu hat die Datenbankgemeinschaft das Transaktionskonzept [Gra81, WV01] entwickelt, dessen Hauptidee es ist, die konsistente Verarbeitung von Daten auch in einem nicht fehlerfreien Umfeld garantieren zu können, selbst wenn diese Daten von mehreren Programmen gleichzeitig bearbeitet werden. Eine Schlüsseleigenschaft dabei ist, dass dieses als Abstraktionskonzept in generischer Art und Weise erreicht wird. Die Anwendungslogik kann also von einer idealen Umgebung ausgehen, in der folgende Effekte maskiert sind: • Nebenläufigkeit: alle Effekte, die entstehen, wenn mehrere Programme gleichzeitig gemeinsame Daten bearbeiten. Jede Transaktion hat den Eindruck, der einzige Client zu sein. • Fehlersituationen: alle Effekte, die entstehen, wenn Programme abstürzen, unterbrochen werden oder wenn Hardwarefehler auftreten. Transaktionen sind so etwas wie ein Kontrakt zwischen Anwendung und Transaktionsserver: die Anwendung gibt die Transaktionsgrenzen und die gewünschte Terminierung bekannt. Der Server betrachtet alle Anfragen innerhalb dieser Grenzen als zu einer Transaktion gehörend und garantiert gewisse Eigenschaften für diese Menge von Anfragen in Bezug auf die Daten. Der Transaktionsserver muss dazu folgende Aufrufe anbieten: 1. Begin Transaction: legt den Anfang einer Transaktion fest. 2. Commit Transaction: legt das Ende einer Transaktion fest. Damit verbunden ist die Aufforderung, alle Effekte der Transaktion dauerhaft zu machen. 3. Abort Transaction: legt den Abbruch einer Transaktion fest. Damit verbunden ist die Aufforderung, alle Effekte der Transaktion ungeschehen zu machen. 20 2.2 Transaktionsverarbeitung Es haben sich vier elementare Eigenschaften herauskristallisiert, die ein Transaktionsserver für die Maskierung von Fehlersituationen und Nebenläufigkeit während der Transaktionsausführung garantieren muss, die als sogenannte ACID-Eigenschaften bekannt sind: • Atomizität: Die Atomizität fordert, dass die Schritte einer Transaktion entweder komplett oder gar nicht in die Datenbank übertragen werden und für andere Transaktionen erst sichtbar sind, wenn die Transaktion erfolgreich abgeschlossen ist. Im Falle von System- und Transaktionsfehlern muss der Eindruck erweckt werden, dass die Transaktion nie stattgefunden hat. • Konsistenz-Erhaltung: Diese Eigenschaft verlangt, dass Integritätsbedingungen in Bezug auf die Daten von Transaktionen eingehalten werden. Eine Transaktion darf die Datenbank nur von einem konsistenten Zustand in einen anderen konsistenten Zustand überführen. Nur innerhalb einer Transaktion sind inkonsistente Zwischenzustände erlaubt. • Isolation: Diese Eigenschaft verlangt, dass Transaktionen voneinander isoliert sind. Jede Transaktion verhält sich, als ob sie die einzige wäre und sieht nur konsistente Zustände. • Dauerhaftigkeit: Die Dauerhaftigkeit garantiert im Falle eines erfolgreichen Transaktionsabschlusses, dass die Daten erhalten bleiben, egal welche Fehlersituationen auch auftreten. 2.2.3 TP-Monitore TP-Monitore [Ber90] sind Software-Systeme, die Kernfunktionen für verteilte TP-Systeme bereitstellen und zwischen dem Anwendungsprogramm und der Datenbank stehen. Sie sorgen neben einer effektiven Ausnutzung der Systemressourcen für einen korrekten Ablauf der Transaktionen und für zusätzliche Datensicherheit in großen Netzwerken. Für einfache Client-Server-Verbindungen in lokalen Netzen sind sie überdimensioniert. Die grundlegende Architektur umfasst dabei Komponenten für alle Hauptfunktionen eines TP-Systems: 1. Präsentations-Server: Sie regeln die Interaktion mit einem Endbenutzer über Menüs oder Formulare. Dabei sammelt ein Präsentations-Server Eingabeparameter, identifiziert Transaktionen und ist für die Authentifizierung zuständig. 2. Workflow-Controller: Seine Hauptaufgabe ist die Vermittlung zwischen 1. und 3. Dabei wählt er die Transaktionsprogramme aus, steckt Transaktionsgrenzen ab und behandelt Fehlersituationen. 3. Transaktions-Server: Die Anwendung, die die eigentlichen Transaktionsprogramme ausführt. Dazu wird in der Regel auf eine Datenbank zugegriffen. 21 Kapitel 2 Hintergrund Damit die Kommunikation zwischen unterschiedlichen Prozessen sicher durchgeführt werden kann, wird oft das sogenannte queued transaction processing [BHM90] verwendet. Im Gegensatz zu einer direkten Kommunikation beispielsweise über RPC [BN84] kommt hier eine persistente Warteschlange zum Einsatz, in die Clients und Server Anfragen und Antworten einfügen bzw. herausnehmen. Diese Art der Kommunikation ist asynchron, kann also auch benutzt werden, wenn der Kommunikationspartner gerade nicht verfügbar ist. Es gibt eine ganze Reihe von kommerziellen Transaktionsmonitoren. Das Customer Information Control System (CICS) [IBM] ist der wohl verbreitetste und steht für viele Plattformen zur Verfügung. Tuxedo [ACM94] ist ein auf Unix-Systeme beschränkter TP-Monitor, der für ein AnfrageAntwort-Paradigma mittels persistenter Warteschlangen optimiert ist und mittels des 2Phasen-Commit-Protokoll verteilte Transaktionen unterstützt. Encina [She93] ist ein weiterer Monitor für UNIX-Plattformen und basiert auf dem Architekturmodell der X/Open für verteilte Transaktionsverarbeitung. Obwohl TP-Monitore in den 90er-Jahren gut verstandene und etablierte Softwaresysteme waren, entstanden in dieser Zeit neue Herausforderungen, vor allem durch das WWW. 2.3 Transaktionsverarbeitung im WWW Dank seiner Natur als Client/Server-System und der Allgegenwart von Browsern mit ihren HTML-Formularen ist das WWW auch als Plattform für TP-Systeme sehr attraktiv. Die Architektur von Web-Anwendungen erlaubt unterschiedliche Ansätze für die Umsetzung des Transaktionsmanagements. Wir können dabei folgende Klassifizierung vornehmen [RS00]: 1. clientseitig: Hier erfolgt der Datenbankzugriff direkt aus dem Browser heraus. Dazu kommen externe Viewer oder Plugins wie Java-Applets oder Flash zum Einsatz, die innerhalb des Browsers eine eigene Anwendungsplattform installieren. Der Webserver liefert lediglich noch den Anwendungscode aus. [GL97] ist ein Beispiel eines solchen Systems aus der Forschung, bei dem ein eigenes Formularmodell durch JavaApplets implementiert wird. 2. serverseitig: Hier erfolgt der Datenbankzugriff direkt aus dem Webserver heraus. Die Transaktionsverarbeitung ist komplizierter, da weder Webserver noch Datenbankserver für dieses Szenario entworfen sind. 3. middleware-basiert: Bei diesem Ansatz werden Transaktionsdienste in zusätzlichen Komponenten implementiert. Auch dieser Ansatz stellt in gewisser Weise eine Emanzipation von der Web-Architektur dar. Die Konsequenz ist die Festlegung auf die spezielle Architektur und Schnittstellen, die die Middleware vorgibt. Dieser Ansatz bietet größtmögliche Freiheit im Entwurf der Systeme. 22 2.3 Transaktionsverarbeitung im WWW Der serverseitige Ansatz stellt dabei die größten Herausforderungen, da er als einziger an die Architektur des WWW gebunden ist und weder auf Seiten des Browsers noch des Webservers besondere Anforderungen stellt. Neben der HTTP-Verbindung zwischen dem Browser und dem Webserver macht dabei vor allem die Datenbankverbindung Probleme für die Transaktionsverarbeitung. Das gilt allerdings nicht für alle Anwendungen. Eine Möglichkeit, Unterstützung für Transaktionen in Webanwendungen zu integrieren, ist die direkte Zuordnung von HTTP-Anfragen zu Transaktionsprogrammen. Die nötigen Parameter sind dabei in der URL enthalten. Angewendet auf die Hauptfunktionen eines TP-Monitors agiert der Webserver dabei als Workflow-Controller, der mit dem Transaktionsserver in Verbindung steht, während der Webbrowser die Rolle eines Präsentations-Server übernimmt. Wenn diese Zuordnung ausreichend ist, können die Transaktionen der Datenbank benutzt werden. In vielen Fällen ist das allerdings nicht möglich, gerade bei der Umsetzung formularbasierter OLTP-Anwendungen. Wie wir schon in der Einleitung gesehen haben, müssen hier mehrere HTTP-Anfragen einer Transaktion zugeordnet werden. 2.3.1 Datenbankverbindungen Normalerweise besitzt jeder Datenbank-Server eine eigene Schnittstelle für den Zugriff von Clients. Die prinzipielle Funktionsweise ist dabei allerdings immer die gleiche. Für den Zugriff auf den Datenbankserver muss der Client zunächst eine Verbindung aufbauen. Eine Verbindungsanfrage enthält dabei neben Parametern, die Verbindungsoptionen festlegen, auch Authentifizierungsinformationen. Sobald die Verbindung etabliert ist, kann der Client entweder Anfragen für die Datenverarbeitung abschicken oder Transaktionen über die üblichen Kommandos steuern. Bei Verbindungsende werden alle nicht abgeschlossenen Transaktionen des Clients automatisch abgebrochen. Da clientseitig alle identifizierenden Daten für die Verbindung im Kontext des Clientprozesses gespeichert sind, gehen diese bei Prozessende verloren. Man kann also keine Verbindung von einem Prozess in einen anderen „herüberretten“. Funktionsweise eines Webservers Genau das wäre aber die Voraussetzung, um Transaktionen auf mehrere Anfrage-Zyklen des Webservers, also server actions, auszudehnen, da im Allgemeinen diese Skripte in genau einem Prozess ausgeführt werden. Das liegt an der prinzipiellen Funktionsweise von Webservern. Dabei müssen drei Fälle unterschieden werden: • CGI-Wrapper: Ein CGI-Skript bzw. der Interpreter einer Skriptsprache wie PHP wird für jede Anfrage in einem neuen Prozess separat gestartet. So müssen Datenbankverbindungen immer wieder auf- und abgebaut werden. Obwohl die Performance unter dem Overhead der ständigen Prozess-Erzeugung leidet, wird dieses Modell sehr oft 23 Kapitel 2 Hintergrund bei Web-Hosting-Providern eingesetzt, da durch die komplette Trennung der Prozesse fehlerhafte Skripte keinen Einfluss auf andere Skriptabläufe nehmen können. • Prozesspool/Multiprozess-Webserver: Hier verteilt ein Koordinator-Prozess die Anfragen an Kindprozesse, die in einem Pool von Prozessen bereitstehen. Da Skriptinterpreter nicht immer neu gestartet werden müssen, kann so die Leistung gesteigert werden. Da die Prozesse nicht beendet werden, können Ressourcen prinzipiell geteilt und Datenbankverbindungen an die nächste Skriptverarbeitung weitergereicht werden. Allerdings werden aufeinanderfolgende Clientanfragen nicht notwendigerweise von demselben Web-Server-Prozess bearbeitet. Es kann also nicht garantiert werden, dass eine bestimmte Verbindung dem nächsten Skript zur Verfügung steht. • Threadpool/Multithread-Webserver: Hier verteilt der Koordinator die Anfragen an verschiedene Threads. Da diese Threads auf mehrere Prozesse aufgeteilt sind, gelten die gleichen Überlegungen wie bei einem Multiprozess-Webserver. Es handelt sich um die effizienteste Möglichkeit für die Implementierung von Webservern. Allerdings muss hier zusätzlich die Threadsicherheit der Skriptinterpreter gewährleistet sein. Persistente Datenbankverbindungen Die Möglichkeit des Verbindungsrecycling hat zu der Idee von persistenten Datenbank-Verbindungen geführt. Diese werden bei Skriptende nicht automatisch geschlossen, sondern für die weitere Verwendung durch andere Skripte offengehalten. Bei Verbindungsaufbau wird nun zunächst überprüft, ob eine identische Verbindung bereits zur Verfügung steht und in diesem Fall weiterverwendet. Andernfalls muss die Verbindung neu aufgebaut werden und es besteht überhaupt kein Unterschied zu nicht persistenten Verbindungen. Verbindungen gelten dabei als identisch, wenn sie mit den gleichen Verbindungsoptionen und Authentifizierungsparametern auf die Datenbank zugreifen. Als direkter Ersatz zu normalen Verbindungen dienen persistente Verbindungen einzig der Reduzierung der Kosten, die durch den Verbindungsaufbau entstehen. Sie bringen im Vergleich zu diesen keinerlei Mehrwert für die Unterstützung von Sessions oder Transaktionen, wie wir im letzten Abschnitt festgestellt hatten. Sie führen im Gegenteil sogar zu zusätzlichen Problemen. Da die Verbindungen nicht geschlossen werden, bleiben ohne ein automatisch durchgeführtes Rollback auch alle Transaktionen offen. Da Verbindungen lediglich über Aufruf-Parameter identifiziert werden, kann ein Skript eine Verbindung erhalten, die noch offene Transaktionen eines anderen Skriptes mit identischen Parametern enthält. So können Transaktionen sozusagen entführt und ohne Absicht geteilt werden. Durch das Offenhalten von Verbindungen stößt man auch sehr viel schneller an das Limit gleichzeitiger Verbindungen, die ein Datenbankserver zulässt. 24 2.3 Transaktionsverarbeitung im WWW 2.3.2 Relevante Forschungsarbeiten Rein serverseitige Ansätze werden in der Forschung außen vor gelassen. Bei den etablierten Frameworks wie PHP, ASP.NET oder Java muss die Nebenläufigkeitskontrolle in der Anwendungslogik untergebracht werden. Bei [LSCI97] handelt es sich um eine frühe Arbeit, die einen clientseitigen Ansatz verfolgt, bei der die Webanwendung lokal im Browser mittels eines objektorientierten Toolkits anstatt im Web-Server ausgeführt wird und direkt und ohne Umweg über den Webserver auf die Datenbank zugreift. So kann das native Transaktionsmanagement der Datenbank benutzt werden. Das WWW wird nur noch zur Auslieferung des Anwendungscodes benutzt und bildet nicht mehr die eigentliche Anwendungsplattform. Obwohl sich das System nicht durchsetzen konnte, lebt die Idee in den mittlerweile allgegenwärtigen FlashAnwendungen weiter. Middleware-basierte Ansätze JPernLite [YK99] bietet Webanwendungen die Unterstützung von hochentwickelten, transaktionalen Features. JPernLite ist prinzipiell ein Transaktionsserver, der unabhängig vom Webserver arbeitet. Der Transaktions-Server ist entweder ein Webserver, der eine HTTPErweiterung unterstützt, bei der URLs Transaktionsoperationen repräsentieren oder ein HTTP-Proxy. Clients können nicht direkt auf Datenobjekte zugreifen, sondern nur über JPernLite, das sich dann wiederum um verteilte Recovery und Commitment kümmert. Es gibt prinzipiell zwei Mechanismen für die Nebenläufigkeitskontrolle: Zeitmarken sowie Sperren mit konfigurierbaren Sperrtabellen. Persistenz wird in dem Sinne unterstützt, dass Abstürze und Neustarts des JPernLite-Servers transparent für Clients sind. Verbindungen mobiler Clients können unterbrochen und wieder aufgenommen werden. Das System ist über Java-Plugin-Funktionen auf Gebieten wie Sperren, Zeitmarken, Transaktionsoperationen, Mitteilung von Ereignissen oder Datenoperationen erweiterbar. So können unterschiedliche Transaktionsmodelle in JPernlite umgesetzt werden. Mit Cheetah [PA00] lassen sich Komponenten zusammensetzen, die in Transaktionen miteinander interagieren. Es handelt sich um eine Java-basierte Lösung, deren Hauptbeitrag in der Unterstützung von verschachtelten Transaktionen durch ihre Komponentenarchitektur liegt. Anpassen des Transaktionsmodells Aus der Beobachtung, dass volle ACID-Garantien für das Web zu stark sind, sind eine Reihe von neuen Transaktionsmodellen entstanden. [YEH00] kommt zu dem Schluss, dass die klassischen ACID-Eigenschaften nicht passend als Korrektheitskriterium für Transaktionen im Web sind und schlägt neue Kriterien vor, die 25 Kapitel 2 Hintergrund sogenannten SACReD-Eigenschaften. Diese sind semantische Atomizität, (Effekte abgebrochener Transaktionen werden über Kompensierungs-Transaktionen rückgängig gemacht), Konsistenz (Consistency), Dauerhaftigkeit und Resilience (Ausfallsicherheit durch Bereitstellung von alternativen (Sub-)Transaktionen). Verletzungen der Isolation werden als Konsequenz der semantischen Atomizität in Kauf genommen. Diese Eigenschaften werden in dem geschachtelten Web-Transaktionsmodell WebTraM im Rahmen einer CORBA-basierten Middleware umgesetzt. WebDAV WebDav [EJWG99] ist eine HTTP-Erweiterung, über die Sperren auf Webseiten bei einem Web-Server angefordert werden können. In [SH04] machen die Autoren davon Gebrauch und bieten den Zugriff auf einen Datenbankserver über das WebDav-Protokoll, bei dem einzelne Datensätze einer relationalen Datenbank anstelle von Dateien eines Dateisystems adressiert werden. [DN99] beschreibt ein Groupware-System basierend auf WebDAV. Es erweitert Web-Formulare, um WebDAV-Methoden zu genügen. Transaktionen werden nicht erwähnt. Integration von Transaktions-Unterstützung in die WWW-Infrastruktur Das Transaction Internet Protocol [LEK98] ist ein einfaches 2-Phasen-Commit-Protokoll das aus der Beobachtung heraus entstanden ist, dass Transaktions-Protokolle wie beispielsweise das CORBA-basierte OTS oder OSI-TP komplex, schwer umsetzbar und wenig verbreitet sind und es deshalb keinen allgemein akzeptierten Standard gibt. Es setzt deshalb auf ein einfacheres Konzept, bei dem das Protokoll lediglich angibt, wie unterschiedliche Web-Sites sich über das Transaktionsergebnis einigen. Die eigentliche Kommunikation muss immer noch über andere Protokolle stattfinden. Recovery EOS2 [SW06] ist ein Framework, mit dem eine exactly-once Ausführungssemantik für WebServices auch im Falle von verlorenen Nachrichten und Abstürzen von Komponenten transparent für den Programmierer erreicht wird. Der dazu nötige Recovery-Layer besteht aus einem modifizierten PHP-Interpreter und setzt auf einem erweiterten Cookie-Begriff auf. Transaktionsmodelle für XML-Datenbanken Obwohl Anfragesprachen für semistrukturierte Daten schon lange Gegenstand der Forschung sind, wurde die Möglichkeit für Datenänderungen bisher nur wenig untersucht und wenn, sind wie in [TIHW01] nur Änderungen eines Benutzers berücksichtigt. Insbesondere die ungeordnete Natur semistrukturierter Daten ist bei simultanen Änderungen mehrerer Benutzer schwierig zu handhaben. So werden bei XML-Datenbanksystemen Updates auf Dokumentenebene durchgeführt, auch wenn nur ein kleines Fragment des Dokuments wirklich betroffen ist. In [DHP04] wird gezeigt, dass klassische Verfahren für die Nebenläufigkeitskontrolle 26 2.3 Transaktionsverarbeitung im WWW nicht für die komplexeren Änderungmöglichkeiten des XML-Datenmodells geeignet sind. Deshalb werden zwei eng mit der Dokumentinstanz verknüpfte Sperrmechanismen, Scheduling-Algorithmen sowie ein dazu passendes Transaktionsmodell eingeführt, die zusammen Serialisierbarkeit garantieren. Dabei wird ein XML-Dokument von einem vereinfachten Datenmodell repräsentiert und eine XPath-ähnliche Anfragesprache sowie eine Updatesprache verwendet, mit der Knoten hinzugefügt und gelöscht, nicht aber verschoben werden können. 27 Kapitel 3 TransForm Wie wir bereits in der Einleitung angedeutet haben, handelt es sich bei TransForm nicht um ein in sich geschlossenes System, sondern um eine Art Bauplan für die Realisierung eines transaktionalen Datenzugriffs in Webanwendungen. Dieser Bauplan sieht dabei neben einer speziellen Art von Formularen einen Webservice vor und lässt sich in den unterschiedlichsten Sprachen und Frameworks für die Entwicklung von Webanwendungen in die Realität umsetzen. TransForm definiert dabei verschiedene Modelle, die in enger Zusammenarbeit die ACIDEigenschaften für diese Transaktionen garantieren. Umgesetzt werden diese Modelle von Komponenten wie Schedulern oder Datenbank-Backends, deren Schnittstellen fest vorgegeben sind und so für Kompatibilität untereinander sorgen. So können Komponenten entweder individuell an eigene Ansprüche angepasst oder auch vorgefertigt übernommen werden, beispielsweise aus Bibliotheken. Da TransForm lediglich Rahmen und Schnittstellen dieser Komponenten vorgibt, kann man auch von einem Architekturstil für OLTPAnwendungen im Web sprechen. 3.1 Architektur TransForm ist so entworfen, dass es sich in die klassische Architektur von Webanwendungen einfügt, also die eines 3-stufigen Client-Server-Systems mit einem Webbrowser als Client, einem Webserver, der Programmlogik ausführen kann und einer Datenbank, in der die persistenten Daten gespeichert sind. In Abschnitt 2.3 hatten wir verschiedene Möglichkeiten für den Datenzugriff solcher Systeme vorgestellt. TransForm verwendet dabei eine Mischung aus clientseitigem und serverseitigem Ansatz und ist deshalb in Abbildung 3.1 in der Mitte als Kombination dieser beiden Ansätze dargestellt. Der TransForm-Ansatz ist in dem Sinne clientbasiert, dass der Zugriff auf die Datenbank direkt aus dem Browser bzw. aus Formularen im Browser heraus erfolgt. Da aber auf einen Webserver als Wrapper für den eigentlichen Datenbankserver zugegriffen wird und nicht auf zusätzliche externe Komponenten, wird auch der serverbasierte Ansatz verfolgt. Die TransForm-Architektur besteht also prinzipiell aus zwei Teilen. 28 3.1 Architektur DB WS DB WS ok ok DB WS ok Abbildung 3.1: Architektur der Datenverarbeitung in TransForm als Kombination aus clientseitigem Ansatz (links) und serverseitigem Ansatz (rechts). 1. Formulare als Clientkomponente: Der Browser enthält Formulare, die wie normale HTML-Formulare im Seitenquelltext definiert sind. Ein Javascript-basierter Controller kümmert sich dann um die Formularverarbeitung. 2. Web-Service als Daten-Server: Serverseitig erfolgt die Datenverarbeitung über einen Web-Service, der Anfragen codiert in HTTP-Variablen entgegennimmt. Er bildet dabei einen Wrapper für eine Datenquelle wie beispielsweise eine relationale Datenbank oder ein Filesystem und fasst Anfragen in Transaktionen zusammen. 3.1.1 Architektur als TP-System Die in Kapitel 2.2 vorgestellten drei Hauptkomponenten von TP-Systemen werden in der TransForm-Architektur folgendermaßen abgebildet: 1. Präsentation: Die Präsentation auf Clientseite wird von den Formularen übernommen. Ihre Aufgabe ist die Beschaffung der Eingabe, die Präsentation der Ausgabe sowie die Interaktion mit dem Benutzer. 2. Workflow-Controller: Diese Aufgabe wird von einem JavaScript-Programm im Browser übernommen, der damit in die Rolle eines Fat-Client schlüpft. Der Controller vermittelt und regelt die Kommunikation zwischen der Präsentation und dem Transaktionsserver und achtet dabei auf die Einhaltung der Regeln und Protokolle von TransForm. 3. Transaktions-Server: Diese Rolle wird von dem Webservice übernommen, der als Ressource im Webserver Transaktionsschritte entgegennimmt und diese mit Hilfe des Transaktionsmechanismus der Datenbank atomar ausführt. 29 Kapitel 3 TransForm Daten ok WebServer ok ok Anwendungslogik Abbildung 3.2: Die Architektur von TransForm in Bezug auf Web-Anwendungen. 3.1.2 TransForm als Architekturstil Für die Formularverarbeitung sieht TransForm also in Anlehnung an das MVC-Entwurfsmuster eine saubere Trennung von Datenmodellierung, Präsentation der Daten im Client sowie der Steuerung des Ganzen vor. In Bezug auf die Architektur einer gesamten Webanwendung lässt TransForm aber Freiheitsgrade. Bei der Implementierung 3-stufiger Webanwendungen lassen sich drei unterschiedliche Aufgabenbereiche separieren: 1) die Implementierung der Anwendungslogik, 2) die Verwaltung der persistenten Daten, sowie 3) die Erzeugung des Markups für die Darstellung der Webseiten. Klassischerweise werden diese Aufgaben von einem Programm übernommen und es findet keine strikte Trennung dieser Bereiche statt. In TransForm sind Anwendungslogik und Datenverarbeitung getrennt. Die Anwendungslogik wird weiterhin im Webserver implementiert. Die Datenverarbeitung wird dort aber lediglich definiert, ausgeführt wird sie dann von dem Controller der Webseite. Das Seiten-Markup kann nun prinzipiell auf zwei Arten erzeugt werden, die in Abbildung 3.2 schematisiert dargestellt sind. Sie unterscheiden sich in der Art der verwendeten Formulare. Die linke Seite zeigt eine Anwendung, die aus mehreren Seiten besteht und lediglich Formulare für den Datenzugriff innerhalb einzelner Seiten einsetzt. Hier wird das Markup für die Darstellung vom Webserver erzeugt und ausgeliefert. Anwendungslogik und Darstellung sind vermischt. Die rechte Seite zeigt eine Anwendung, die über Formulare Seitenbereiche dynamisch nachlädt und deshalb nur aus einer Seite besteht. Hier gibt es Formularelemente für Menüs und andere Widgets. Für die Darstellung dieser Widgets sind die Formularelemente mit einem Dienst verbunden, der Anwendungslogik enthält. Wenn dieser Dienst lediglich logisches Markup ausliefert und das Formular dieses über ein Stylesheet in darstellbares HTML wandelt, erreicht man eine komplette Trennung von Darstellung und Anwendungslogik. 30 Arch:Schichten 3.1 Architektur Browser Web-Service Formularmanager Schicht 3 Transaktionsmanager Schicht 2 Datenmanager Schicht 1 Datenbank Abbildung 3.3: Die Schichten eines TransForm-Systems. 3.1.3 Schichten-Modell Wie es beim Entwurf von Datenbanksystemen üblich ist, bildet auch bei TransForm ein Schichtenmodell die Grundlage für die Systemarchitektur. Der Sinn dieser Aufteilung in Schichten liegt in der Reduzierung der Gesamtkomplexität durch eine Aufteilung der Problemstellung in überschaubare Teilaufgaben. Schichten haben den Zweck, den jeweils höheren Schichten Dienstleistungen anzubieten, ohne diese mit den Einzelheiten zu behelligen, die für die Implementierung zu beachten sind. Normalerweise greifen sie dazu auf die Dienste der darunterliegenden Schichten zurück. In Anlehnung an die Architektur klassischer Datenbanken, bei denen die Teilaufgaben von Komponenten wie Scheduler oder Datamanager übernommen werden, ist auch ein TransForm-System in Schichten angeordnet, die verschiedene Systemkomponenten enthalten. Dabei sind für Komponenten lediglich das zugrundeliegende Modell und das Interface nach außen fest vorgegeben. Ein Modell legt dabei den Rahmen für das Verhalten und den inneren Aufbau einer Komponente fest. Zusätzlich definiert es das Interface für die Benutzung von außen. So ist es möglich, die einzelnen Komponenten in unterschiedlichen Implementierungen an unterschiedliche Gegebenheiten anzupassen und trotzdem sicherzustellen, dass alles reibungslos funktioniert. In Abbildung 3.3 sind die drei Schichten der TransForm-Architektur schematisch dargestellt: der Daten-, der Transaktions- sowie der Formularmanager. Die unterste Schicht in der Abbildung bildet eine Datenbank, die die persistenten Daten enthält. Normalerweise handelt es sich hier um eine relationale Datenbank, prinzipiell können das aber beliebige Datenquellen sein. 31 Kapitel 3 TransForm Der Datenmanager bietet in der darüberliegenden Schicht einen einheitlichen, abstrahierten Zugriff auf diese Datenbank. Dabei bildet er Lese- und Schreibzugriffe eines abstrahierten Datenmodells in die native Anfragesprache der zugrundeliegenden Datenbank ab. Neben den eigentlichen Daten verwaltet er auch noch Metadaten, die zusammen mit den Nutzdaten persistent gespeichert werden. Das Interface nach außen ist für alle Daten gleich, die interne Modellierung der Daten kann dabei je nach Datenbank variieren. Der Transaktionsmanager bildet die nächste Schicht und bietet als zusätzliche Funktionalität die Kapselung des Daten-Zugriffs in Transaktionen. Da er zusammen mit der Datenschicht den Webservice ausmacht, stellt er ein webbasiertes Interface für diese Transaktionen zur Verfügung. Die oberste Schicht in der Abbildung bildet der Formularmanager, der im Browser angesiedelt ist und Formularbearbeitungsschritte des Benutzers in Transaktionsschritte übersetzt und die Interaktion mit dem Transaktionsmanager organisiert. 3.1.4 Vergleich zu Datenbank-Servern In klassischen Datenbanken ist das Transaktionsmanagement in den Datenbankserverprozess integriert und erstreckt sich nicht über mehrere Prozesse. Zu Clients besteht eine bidirektionale Kommunikationsverbindung. Als Hintergrundprozess kann der Transaktionsmanager die Gesamtsituation im Auge behalten. Wenn Schritte momentan nicht ausführbar sind, später aber möglicherweise doch, kann er diese zunächst blockieren und zur späteren Ausführung in eine Warteschlange einreihen. So kann er jeweils die im Hinblick auf die Gesamtsituation geeignetste Operation aus dieser Warteliste auswählen. Im Vergleich dazu bestehen in TransForm folgende hervorzuhebende Unterschiede für den Transaktionsmanager: 1. In jedem Anfrage/Antwort-Zyklus wird exakt der angeforderte Transaktionsschritt bearbeitet. Dieser kann entweder direkt ausgeführt oder abgewiesen werden. 2. Der Webservice kann lediglich passiv Anfragen entgegennehmen und nicht von sich aus Kontakt zum Client aufnehmen. Das hat zur Folge, dass es in TransForm so etwas wie eine Warteschlange nicht gibt und Entscheidungen immer aus dem Blickwinkel der aktuellen Anfrage entschieden werden müssen. Ohne Möglichkeit, Kontakt zum Client aufzubauen, ist der Web-Service darauf angewiesen, dass der Client blockierte Operationen wiederholt. Da dieser keinerlei Kenntnis über parallele Transaktionen besitzt, kann er nur in regelmäßigen Abständen eine erneute Ausführung ohne Garantie auf Erfolg anfordern. So entsteht eine unnötig hohe Last und Aktionen müssen im Zweifelsfall abgelehnt werden. 32 Modelle 3.2 Modelle Formularschicht Transaktionsschicht Datenschicht Formularmodell Transaktionsmodell AuthentifizierungsModell Datenmodell: Nutzdatenmodell, Metadatenmodell Abbildung 3.4: Modelle. 3.2 Modelle Die Aufteilung der Transaktionsverarbeitung auf eigenständige und zustandslose Inkarnationen des Webservices wirft die Frage auf, wie der Zustand aller Transaktionen zwischen diesen geteilt werden kann. Da es keinen gemeinsam nutzbaren Hauptspeicherbereich gibt, müssen alle benötigten Metainformationen neben den eigentlichen Daten in der Datenbank gehalten werden. Bei der Zuordnung der einzelnen Anfragen zu Transaktionen ist der Web-Service dabei auf die Mithilfe der Clients angewiesen, die in jeder Anfrage einen Transaktions-Identifizierer als Parameter übergeben müssen. So erstreckt sich in TransForm das Transaktionsmanagement über drei Modelle, die sich über Browser (Formularmodell) und Webservice (Transaktions- und Datenmodell) erstrecken und dabei grob den Schichten der TransForm-Architektur entsprechen. Zusammen mit dem Authentifizierungsmodell sind sie in Abbildung 3.4 dargestellt. 3.2.1 Datenmodell Das Datenmodell sorgt für einen einheitlichen Zugriff auf unterschiedliche Daten, indem es 1) mittels einer Abstraktionsschicht die Datenbank in relevante Datenobjekte aufteilt und Lese- und Schreibzugriffe auf diesen Objekten in die eigentliche Anfragesprache der Datenbank übersetzt und 2) für die Metadaten Strukturen sowie den Zugriff darauf vorgibt und diese neben den eigentlichen Nutzdaten in der Datenbank speichert. Zugriff auf Nutzdaten Die Anfragesprache besteht aus der Spezifikation eines Objektes zusammen mit der Art des Zugriffs. Die Einführung eines solchen abstrakten Modells für den Datenzugriff ist die entscheidende Grundlage eines funktionierenden Transaktionsmanagements in TransForm. Es leistet dabei den Modellen aus Abbildung 3.4 folgende unerlässliche Dienste: • deklarative Objektspezifikation: Da jedes Formularelement mit einem Objekt des Datenmodells verknüpft ist, kann der Formularmanager in Reaktion auf Benutzerevents 33 Kapitel 3 TransForm entweder einen lesenden oder schreibenden Zugriff auf dieses Objekt veranlassen. So muss in der Formular-Definition nicht für jede Art des Zugriffs eine eigene Anfrage hinterlegt werden. Außerdem lässt sich je nach Modellierung die eigentliche Struktur der Datenbank verbergen, da die Objekte anstelle von SQL-Anfragen im Quelltext sichtbar sind. • Konflikterkennung: Das Metadatenmodell sieht interne Strukturen vor, in denen die betroffenen Objekte aller Datenzugriffe gespeichert werden. So können zueinander in Konflikt stehende Datenzugriffe ermittelt werden. • Konstantes Interface für den Datenzugriff: Die Hauptaufgabe des Datenmodells ist ein standardisierter Datenzugriff und damit die Übersetzung der Lese- und Schreibzugriffe in die native Anfragesprache der zugrundeliegenden Datenbank. So kann eine Vielzahl verschiedener Datenbanksysteme unterstützt werden, ohne dabei die darüberliegenden Modelle speziell anpassen zu müssen. Formales Modell Wir nehmen an, eine Datenbank D enthält eine disjunkte Menge von Objekten {x, y, z, ...}, also D = {x, y, z, ...}. Jedes Objekt o hat eine Domain dom(o) und einen Wert val(o) ∈ dom(o). Auf diesen Objekten sind elementare Lese- und Schreiboperationen für den Datenzugriff definiert: r(o): steht für lesenden Zugriff auf das Objekt o und liefert dessen Wert val(o) zurück; w(o, v): steht für das Schreiben des Wertes v in das Objekt o, falls v ∈ dom(o). Die Semantik des Schreibzugriffs deckt dabei Einfüge-, Lösch- und Änderungsoperationen folgendermaßen ab: falls o ∈ D, v 6= ∅: überschreibe den Wert von o (val(o) = v); falls o ∈ D, v = ∅: lösche o aus D; falls o ∈ / D, v 6= ∅: füge o zu D hinzu mit val(o) = v; Auf den Objekten von D ist die Relation conf ⊆ D × D definiert, die angibt, ob zwei Objekte potentiell zueinander in Konflikt stehen. Ein Schedulingverfahren kann dann anhand dieser Relation, der beteiligten Transaktionen und der Art des Zugriffs feststellen, ob es sich tatsächlich um einen Konflikt handelt. Im einfachsten Fall gilt: conf = {(x, y)|x, y ∈ D ∧ x = y}. Umsetzung des Modells in XML/XPath Prinzipiell können die Objekte des Datenmodells durch beliebige Zeichenketten repräsentiert werden. Für den Zugriff auf eine Datenbank ist es jedoch entscheidend, dass sich die 34 3.2 Modelle Datenobjekte des Modells eindeutig den realen Objekten dieser Datenbank zuordnen lassen, bzw. dass sich aus den Objekten des Modells Anfragen berechnen lassen, über die die realen Datenobjekte gelesen und geschrieben werden können. Es hat sich dabei als sinnvoll erwiesen, die Datenbank in XML zu modellieren, wobei das Datenbankschema einer DTD und die Instanz einem XML-Dokument entsprechen. XML unterstützt die Abbildung von unterschiedlichsten Datenbankmodellen. Insbesondere das relationale Modell und Dateisysteme sind in intuitiver Weise unterstützt. XML-Elemente bzw. deren Attribute bilden dabei die Menge der Objekte D, die über XPath-Ausdrücke identifiziert werden. Je nach Datenbank bzw. Modellierung lässt sich die Konflikterkennung so auf Stringvergleiche reduzieren. Normalerweise ist dabei eine Untermenge der erlaubten XPath-Syntax völlig ausreichend wie in Kapitel 4 ersichtlich werden wird, wo wir eine auf XPath basierende einfache selectproject-join-Anfragesprache für den Zugriff auf relationale Datenbanken vorstellen. Auch andere Datenhaltungssysteme lassen sich auf natürliche Weise in unser Datenmodell integrieren: Dateisysteme, bei denen die Objekte dann Pfade von der Wurzel bis zu den Blättern sind, oder Key-Value-Datenbanken [OBS99], die den Ansprüchen vieler einfacher Anwendungen genügen. Metadatenmodell Neben dem Zugriff auf die Nutzdaten modelliert das Datenmodell auch die datenbankunabhängige Verwaltung der Metadaten. Sie werden zusammen mit den Nutzdaten in der Datenbank gespeichert. Je nach Datenbanksystem kommen dabei unterschiedliche interne Strukturen zum Einsatz. Das Modell sieht dabei Strukturen vor, in denen sowohl die Datenzugriffe als auch die Zustände aller Transaktionen gespeichert und jederzeit ausgelesen werden können. Transaktionsstatus: Der Status alle Transaktionen wird in einer Liste modelliert, die für jede Transaktion einen Eintrag vorsieht. Diese Einträge bestehen aus Tupeln (tid, status, timestamp). Dabei enthält tid den Identifizierer der Transaktion, status den aktuellen Transaktionsstatus und timestamp eine Zeitmarke. Der Status einer Transaktion ist dabei entweder aktiv, abgeschlossen, abgebrochen oder in Konflikt. Datenzugriffe: Zusätzlich werden alle Datenzugriffsoperationen geloggt. Dazu sind verschiedene Strukturen wie Readset RS, Writeset WS oder die Sperrtabellen RL und WL vorgesehen. Sie enthalten Tupel (id, tid, object, xpath, value, timestamp). Dabei wird eine Operation über id eindeutig bestimmt. Über die tid werden die Operationen Transaktionen zugeordnet, über timestamp sind sie geordnet, während object das eigentliche Objekt benennt, auf das zugegriffen wurde. Gelesene oder geschrieben Werte werden in value gespeichert und xpath enthält den XPath-Ausdruck, über den der Datenzugriff definiert wurde. 35 Kapitel 3 TransForm In Abhängigkeit von konkreten Schedulingprotokollen und Backends werden wir diesen Tupeln allerdings bei Bedarf weitere Einträge hinzufügen. 3.2.2 Transaktionenmodell Direkt über dem Datenmodell ist in Abbildung 3.4 das Transaktionsmodell angeordnet, das die Datenzugriffe in Transaktionen mit ACID-Garantien bündelt. Seine Aufgabe ist die Modellierung des üblichen Transaktionsbegriffs innerhalb der Grenzen unseres Systems, damit wir uns auf bewährte und gut verstandene Strategien zur Nebenläufigkeitskontrolle und Recovery stützen können. Die Schwierigkeit liegt dabei in der Aufteilung der Transaktionsverwaltung auf unterschiedliche Webservice-Inkarnationen, in denen jeweils ein Transaktionsschritt ausgeführt wird. Definition 3.1 (Transaktionsschritt) Ein Transaktionsschritt ist ein Paar (t, a), wobei t ein Transaktionsidentifizierer ist und a eine Aktion, die der Transaktionsschritt bewirkt. Eine Aktion spezifiziert dabei eine der folgenden Operationen: read Leseoperation auf dem Datenmodell write Schreiboperation auf dem Datenmodell begin startet die Transaktion und generiert den Transaktionsidentifizierer abort bewirkt den Abbruch der Transaktion commit bewirkt den Abschluss der Transaktion Jeder Transaktionsschritt ist eine atomare, unteilbare Einheit. Definition 3.2 (Transaktion) Eine Transaktion ist eine geordnete Sequenz von atomaren Transaktionsschritten. Dabei muss der ersten Schritt das begin enthalten und der letzte Schritt das Ende der Transaktion bewirken, entweder durch abort oder commit. Da für einen Scheduler lediglich die Ordnung unter den Transaktionsschritten unterschiedlicher Transaktionen bezüglich der Datenobjekte entscheidend ist, können wir in einem Schritt den Zugriff auf mehrere, unterschiedliche Objekte zulassen. Atomizität und Dauerhaftigkeit der Transaktionsschritte Die Atomizität von Transaktionsschritten bedarf weiterer Erläuterung. In jedem Transaktionsschritt wird im Allgemeinen auf mehrere Objekte der Datenbank zugegriffen, seien es Nutzdaten oder auch Metadaten. Dazu sind unterschiedliche Anfragen der nativen Anfragesprache der Datenbank nötig, wie in Abbildung 3.5 beispielsweise Select- und Update-Statements der SQL-Datenbank in den verschiedenen Transaktionsschritten. Wenn diese Schritte wie in der Abbildung in zwei Web-Service-Inkarnationen seriell hintereinander ausgeführt werden, können sich die unterschiedlichen Anfragen nicht gegenseitig 36 3.2 Modelle Datenbank T1 T2 Webservice B R BOT... select... insert... EOT ... W BOT ... select ... update ... EOT C Abbildung 3.5: Ausführung von Transaktionsschritten in Transaktionen der Datenbank. ins Gehege kommen. Im Allgemeinen müssen wir aber davon ausgehen, dass WebserviceInkarnationen parallel ausgeführt werden, was zu einer verzahnten Ausführung der Anfragen in der Datenbank führen kann. Ohne weitere Maßnahmen können dabei unerwünschte Effekte wie Lost-Update-Situationen auftreten. Ein weiteres Problem sind Fehlersituationen während der Ausführung eines Schrittes wie verlorene Nachrichten durch Netzwerk-Ausfälle oder Abstürze der Datenbank. Obwohl diese über Exceptions der Datenbankverbindung erkannt und abgefangen werden können, muss damit gerechnet werden, dass einige Änderungen in der Datenbank ankommen, während andere verloren gehen. Es müssen also die ACID-Eigenschaften Isolation, Atomizität und Dauerhaftigkeit in Bezug auf die einzelnen Transaktionsschritte gelten. Da jeder Transaktionsschritt in einem Webserver-Prozess verarbeitet wird, können alle Anfragen in einer Datenbankverbindung ausgeführt und somit in eine Transaktion eingeschlossen werden. Dabei muss allerdings darauf geachtet werden, dass die Datenbank das Isolationslevel [GLPT94, ALO00] serialisierbar benutzt. Der SQL-Standard definiert vier verschiedene Grade der Unterstützung von Isolation, die sich darin unterscheiden, welche Phänomene sie zulassen bzw. ausschließen. Der Isolationsgrad serialisierbar schließt dabei alle drei Phänomene aus: Dirty Read, Nonrepeatable Read und Phantom Read. Es werden also alle Datenbankzugriffe eines Schrittes in einer Transaktion zusammengefasst. Sollte dies nicht möglich sein, da nicht auf eine Datenbank mit entsprechendem Transaktionsmechanismus zugegriffen wird, beispielsweise bei einem Dateisystem, müssen diese Eigenschaften entweder im Webservice implementiert werden oder entsprechend Abstriche in Bezug auf die ACID-Eigenschaften gemacht werden. Wenn ein Fehler in der Datenbankverbindung signalisiert wird, ist es entscheidend, wann er geschieht. Aus Sicht des Web-Service müssen drei Phasen unterschieden werden, die in Abbildung 3.6 dargestellt sind: 1. In der ersten Phase ist klar, dass noch keine Effekte in der Datenbank materialisiert bzw. für andere Transaktionen sichtbar sind. Hier bewirkt ein Fehler den Abbruch der Transaktion, die deshalb gefahrlos wiederholt werden kann. Diese Phase erstreckt sich vom Transaktionsbeginn über alle weiteren Datenbankanfragen bis hin zum Absenden des Commit. 2. Es schließt sich Phase zwei an, die mit dem Erhalt der Nachricht über ein erfolg- 37 Kapitel 3 TransForm Web-Service Datenbank BOT Phase 1 Select ... Phase 2 EOT Phase 3 t Abbildung 3.6: Die Phasen eines Transaktionsschrittes. reiches Commit endet. Hier ist nicht sicher, ob in der Datenbank das Commit schon durchgeführt wurde oder nicht. 3. In der abschließenden dritten Phase ist durch die Benachrichtigung der erfolgreiche Transaktionsabschluss und die damit erfolgte Materialisierung der bewirkten Effekte sichergestellt. Für Fehlersituationen sowohl in der Datenbank als auch im Netzwerk ist also lediglich Phase 2 interessant. Da wir nicht wissen können, ob die Transaktion in der Datenbank erfolgreich abgeschlossen ist, bleibt uns keine andere Möglichkeit, als die Transaktion zu wiederholen. Dazu muss allerdings dafür gesorgt werden, dass eventuell mehrfach ausgeführte Schritte keine Seiteneffekte in der Datenbank bewirken und die gleichen Resultate zurückliefern. Idempotenz-Check Das kann erreicht werden, indem in der Ausführung jedes Schrittes zuerst die Metadaten konsultiert werden. Bei Datenzugriffen kann im Readset bzw. Writeset überprüft werden, ob der Zugriff schon einmal ausgeführt wurde. Die Rückgabe wird in diesem Fall rekonstruiert. Für Kontrolloperationen kann anhand des Transaktionsstatus ermittelt werden, ob die entsprechende Operation schon ausgeführt wurde. Wenn dieser aktiv ist, können beispielsweise Abort oder Commit nicht erfolgreich gewesen sein. Diese Vorgehensweise hat zusätzlich noch den Vorteil, dass ein Absturz des Webservices zu keinen unerwünschten Effekten führen kann, da ein Aufruf im Zweifel gefahrlos wiederholt werden kann ohne Seiteneffekte zu erzeugen. Wir können also im unseren weiteren Betrachtungen von atomaren, dauerhaften und idempotenten Transaktionsschritten ausgehen. 38 3.2 Modelle 3.2.3 Formularmodell Als clientseitiges Gegenstück zum Transaktionsmodell schließen TransForm-Formulare den kompletten Datenzugriff ihrer Formularelemente in Transaktionen ein. Der Formularbegriff geht dabei über den herkömmlicher HTML-Formulare hinaus. Neben der Vielfalt in der visuellen Gestaltung der Eingabeelemente trifft dies auch auf Verhalten und Fähigkeiten der Formulare zu. Dabei liegt allen Formularen ein einheitliches Modell zugrunde, das eine Schablone für die interne Repräsentierung von TransForm-Formularen festlegt und im Wesentlichen zwei Aufgaben erfüllt: Die Hauptaufgabe liegt in der automatisierten Handhabung des Dienstes, der ja über eine wenig komfortable Schnittstelle erfolgen muss. Die zweite Aufgabe ist die Maskierung von Fehlersituationen. Netzwerkausfälle und verloren gegangene Nachrichten sollen möglichst vor dem Benutzer verborgen bleiben. Nach Browserabstürzen soll der Bearbeitungszustand der Formulare möglichst automatisch wiederhergestellt werden. Dazu ist lediglich ein erneutes Aufrufen der Webseite seitens des Benutzers nötig. Modellierung Das Formularmodell sieht für jedes Formular ein Objekt vor, das neben Variablen und Methoden für die Kommunikation mit dem Webservice weitere Objekte für seine Formularelemente enthält. Variablen: Sie enthalten alle für das gesamte Formular gültigen Parameter. Sie können dabei statisch in der Formulardefinition oder während der Laufzeit dynamisch bestimmt werden. id url auth session tid Der eindeutige Identifizierer des Formulars, der entweder explizit als Tag-Parameter gegeben ist oder implizit als Hash über die Formulardefinition berechnet wird. Dieser Parameter wird immer als Attribut des Formular-Tags bestimmt und legt die Adresse des Web-Service fest, mit dem das Formular verbunden ist. Dieser Parameter verweist auf ein in der Seite enthaltenes Authentifizierungs-Objekt, über das Authentifizierungsinformationen dynamisch ermittelt werden können. Diese Variable enthält die jeweils aktuelle Session-ID. Diese Variable enthält den Identifizierer der Transaktion. Formularelemente: Ein Formularelement e wird repräsentiert durch ein Tupel (id, object, value, type, status), wobei id eine eindeutige ID des Formularelements, object das betroffene Objekt, value den aktuellen Wert dieses Objekts, type optional den erwarteten Typ des Objekts sowie status den aktuellen Status angibt. 39 timer Kapitel 3 TransForm Formular Web-Service Anfrage 1 2 Antwort 3 t Abbildung 3.7: Fehlersituationen. Methoden: Für jeden möglichen Transaktionschritt sieht das Formularmodell eine Methode vor, über die der Schritt über den Web-Service aufgerufen werden kann. Zusätzlich ist ein Konstruktor vorgesehen, der die Definition aus den Tags ausliest, eine Visualisierung in HTML erzeugt und die Kommunikationsmethoden an Ereignisse bindet. begin abort commit read write fordert eine Transaktions-ID an und speichert diese in der Variable tid; sorgt für den Abbruch der aktuellen Transaktion, tid wird gelöscht; fordert einen erfolgreichen Abschluss an, tid wird gelöscht; liest den Ausgangswert; eventgesteuert, propagiert Änderungen des Benutzers an den Service; Persistente Speicherung des Formular-Zustands Damit auch nach einem Absturz des Browsers der letzte Zustand des Formulars wiederhergestellt werden kann, werden alle relevanten Daten in Cookies gespeichert. Cookies sind Einträge einer speziellen Key-Value-Datenbank, die Webbrowser zur Verfügung stellen. Ein Webserver kann dort Informationen für eine besuchte Webseite hinterlegen, die der Browser beim nächsten Besuch dieser Seite an den HTTP-Header seiner Anfrage anhängt. Sie werden üblicherweise für die Speicherung von Sessioninformationen benutzt, können aber auch clientseitig durch JavaScript erzeugt und ausgelesen werden. Wir können sie deshalb zur persistenten Speicherung des Formularzustands lokal im Browser verwenden. In den Cookies werden alle dynamischen, zur Laufzeit ermittelten Variablen wie Transaktions- und Session-IDs, Statusinformationen sowie die aktuellen Werte von Formularelementen gespeichert. Um die Größenbeschränkungen von Cookies zu umgehen, verwenden wir für jedes Formular und für jedes Formularelement ein eigenes Cookie. 1 Als Name eines Formular-Cookies wird die ID des Formulars verwendet, bei Cookies einzelner Elemente wird die Formular-ID mit der des Elements verknüpft. Während der Ini1 Obwohl die maximale Anzahl von Cookies begrenzt ist, stellt das in der Praxis keine Einschränkung dar. Firefox speichert beispielsweise bis zu 65535 Cookies. 40 3.2 Modelle fig:Timer Formular Timer Web-Service BOT Timer Timer Antwort t Abbildung 3.8: Timer. tialisierung eines Formulars wird nun zunächst überprüft, ob ein alter Zustand aus Cookies wiederhergestellt werden muss. Maskierung von Kommunikationsfehlern In einer nicht fehlerfreien Umgebung wie dem Web kann es zu Kommunikationsfehlern kommen, die dazu führen, dass ein Formular auf eine Anfrage keine Antwort erhält. Dabei kann, wie es in Abbildung 3.7 zu sehen ist, ein Fehler auf dem Weg zum Webservice, auf dem Rückweg oder während der Abarbeitung der Anfrage im Webservice auftreten. Ein Formular kann nicht wissen, wann ein Fehler passiert ist, bzw. ob überhaupt ein Fehler passiert oder die Antwort noch unterwegs ist. Da jeder Transaktionsschritt idempotent ist, kann aber die Anfrage wiederholt werden, wenn nach Ablauf einer gewissen Zeit noch keine Antwort eingetroffen ist. Dazu wird mit dem Absenden der Anfrage ein Timer gestartet, der die Anfrage wiederholt, sobald er abgelaufen ist. Mit dem Eintreffen der Antwort wird auch der entsprechende Timer zurückgesetzt. Die Wartezeit des Timers ist ein wichtiger Parameter, der sich nicht pauschal festlegen lässt, sondern von der Netzwerksituation abhängt. Eine zu kurze Wartezeit führt zu unnötigen Wiederholungen, während eine zu lange Zeitspanne zu unnötig langen Wartezeiten führt. Deshalb wird sie an die aktuelle Situation angepasst und aus der durchschnittlichen Antwortzeit der vorigen Anfragen berechnet. Zusätzlich wird der Timeout mit jeder erfolglosen Anfrage verlängert. In Abbildung 3.8 ist exemplarisch die Abwicklung einer Anfrage mit Timern dargestellt. Es sind verschiedene Fehlersituation skizziert, die zu wiederholten Anfragen führen. Bei der ersten Anfrage geht die Antwort auf dem Rückweg verloren, während bei er zweiten ein Fehler im Service auftritt. Erst die letzte Anfrage führt zum Erfolg, woraufhin der Timer 41 Kapitel 3 TransForm abgebrochen wird. Exactly-Once-Garantie Die erzwungene Idempotenz der Transaktionsschritte bewirkt, dass jeder Schritt effektiv höchstens einmal ausgeführt wird, auch wenn die Ausführung mehrmals in Auftrag gegeben wird. Die Timer der Formulare bewirken, dass ein Schritt auch mindestens einmal ausgeführt wird, vorausgesetzt, dass fehlerhafte Komponenten nicht dauerhaft ausfallen. Die Kombination dieser zwei Mechanismen garantiert, dass jeder Transaktionsschritt exakt einmal ausgeführt wird. 3.2.4 Authentifikation Wir hatten im letzten Abschnitt mit den Parametern auth und session schon einen ersten Hinweis auf einen Authentifikationsmechanismus in TransForm erhalten. Dieser wurde bisher außen vor gelassen, da er für die eigentliche Transaktionsverarbeitung nicht entscheidend ist. Allerdings ist in realen Systemen, insbesondere in Mehrbenutzersystemen, ein Mechanismus für die Authentifizierung von Benutzern unumgänglich. TransForm sieht für diese Authentifizierung ein sessionbasiertes Modell vor, das sich über alle drei Schichten der TransForm-Architektur erstreckt: • Formularschicht: Die Benutzer-Session wird im Browser mittels spezieller Anmeldeformulare verwaltet. Der Formularmanager authentifiziert in jedem Transaktionsschritt seine Anfragen mit einer Session-ID gegenüber dem Webservice. • Transaktionsschicht: Die Gültigkeit einer Session wird bei Transaktionsbeginn validiert. Alle Schritte sind einer Session zugeordnet. • Datenschicht: Hier werden Benutzer- und Sessiondaten gespeichert. Authentifikationmodell Auf Datenebene gibt es zwei Strukturen, die neben Read- und Writesets sowie dem Transaktionsstatus über das Metadatenmodell in der Datenbank gespeichert werden: – Benutzerdaten sind als Tupel (User-ID, Passwort) gespeichert. – Eine Session ist ein Tupel (session-ID, User-ID, Gültigkeitsdauer). Für die Verwaltung der Sessions sind folgende Methoden vorgesehen: – login: nimmt Benutzer-ID und Passwort als Argument und erzeugt die Session-ID. – validate: nimmt als Argument eine Session-ID und überprüft deren Gültigkeit. Die Speicherung weiterer Daten wie Namen oder Adresse wollen wir aus unseren Betrachtungen ausschließen. Sonst wären auch weitere Funktionen nötig, über die diese Daten verwaltet werden können. 42 3.2 Modelle Benutzer-ID: Passwort: swort Benutzer-ID + Pas n Sessio AuthentifizierungsDienst -ID Session-ID validate(Session-ID) begin(Session-ID) Formular TransFormDienst Abbildung 3.9: Der Authentifikationsmechanismus von TransForm. Architektur Für die Umsetzung des Modells ist in der TransForm-Architektur ein Dienst vorgesehen, der nach erfolgreicher Authentifizierung eines Benutzers durch seinen Anmeldenamen und Passwort eine Session startet. Diese Session wird durch einen String identifiziert und hat eine begrenzte Gültigkeitsdauer. Die Authentifizierung kann entweder über einen externen Dienst abgewickelt werden oder in einen normalen TransForm-Dienst integriert sein. – externe Authentifikation: Ein externer Web-Service bietet lediglich Authentifizierungsdienste an. Diese Variante ist in Abbildung 3.9 dargestellt. – integrierte Authentifikation: Hier ist der Authentifikations-Mechanismus in einen normalen TransForm-Dienst für den Zugriff auf eine Datenbank integriert. Der Vorteil dieser Variante ist, dass die Validierung ohne Anfragen an einen weiteren Dienst erfolgen kann und somit schneller und zuverlässiger ist. Ablauf Der Ablauf des Anmeldemechanismus lässt sich ebenfalls Abbildung 3.9 entnehmen. Auf der linken Seite stellt ein Browser eine Webseite dar, die einen Login-Bereich und im unteren Teil ein Formular enthält. Der Login-Bereich wird von einem Authentifizierungs-Objekt auth verwaltet, das Benutzereingaben als Benutzer-ID und Passwort an den Dienst sendet und eine Session-ID erhält, wenn die Anmeldedaten korrekt sind. Die Session-ID wird in einer globalen Variable Session-ID gespeichert und kann von den Formularen ausgelesen werden. Das Formular ist mit dem Login-Feld über den Tag-Parameter auth in der Formulardefinition verbunden und weiß so, wo es die Session-ID auslesen kann, die in allen Operationen der Formularverarbeitung als Authentifikation mitgesendet wird. In der Begin-Operation wird die Session-ID dem Transaktionsservice übermittelt, der diese über die validate-Methode bei dem Anmelde-Service überprüfen lässt. Die validierte 43 Transaktionen Kapitel 3 TransForm Datenbank BOT ... select ... insert ... EOT BOT sel. upd. EOT ... ... BOT ... select ... update ... EOT Webservice B R C Formular B R C Abbildung 3.10: 2 Ebenen von Transaktionen: Transaktionen und Transaktionsschritte. Session-ID wird nun zusammen mit ihrer Gültigkeitsdauer der Transaktion zugeordnet und in den Metadaten festgehalten. So kann in jedem weiteren Transaktionsschritt die Gültigkeit der Session anhand des Transaktionsstatus überprüft werden. Prinzipiell wäre es auch möglich, die Session in jedem Transaktionsschritt neu zu validieren. Da der Anmeldedienst normalerweise aber in einem separaten Dienst realisiert ist, ist das nicht praktikabel. Logout Da die Dauer einer Session begrenzt ist, ist ein separater Abmelde-Vorgang eigentlich nicht nötig. Wenn dies aber doch unterstützt werden soll, muss ein Authentifikations-Dienst die Methode logout anbieten, wodurch die Session-ID ungültig wird. Ein Datendienst wertet diese allerdings weiterhin als gültig, da die Session nur bei Transaktionsbeginn beim Authentifikations-Dienst validiert wird. Deshalb muss der Authentifikations-Service dem Datendienst den Ablauf der Session signalisieren. Dazu muss der Datendienst eine Methode invalidateSession(session-ID) anbieten und beim Aufruf von validate die URL dieser Methode dem Authentifikations-Dienst mitteilen. Dieser kann sich so seine Clients merken und ihnen über invalidateSession mitteilen, wenn eine Session vorzeitig beendet wird. 3.3 ACID-Garantien Wir hatten es bei der Diskussion der Modelle im letzten Abschnitt mit Transaktionen auf zwei unterschiedlichen Ebenen zu tun, wie es auch in Abbildung 3.10 angedeutet ist. 1. Zum einen haben wir die Transaktionen des Datenbanksystems für die Gewährleistung der Atomizität und Dauerhaftigkeit einzelner Inkarnationen des Web-Service benutzt. 2. Zum anderen haben wir auf einer zweiten Ebene das eigentliche TransForm-Transaktionsmodell entwickelt, das aus Transaktionsschritten besteht, die einzelnen Inkarnationen des Web-Service entsprechen. 44 3.3 ACID-Garantien Browser 5 4 t Web-Service 4 BOT 3 EOT 2 2 DB 1 Abbildung 3.11: Fehlersituationen während der Ausführung eines Schrittes. Es bleibt zu zeigen, dass unser Modell auch auf dieser zweiten Ebene korrekt ist und für die Transaktionen dort die ACID-Eigenschaften garantiert. Dafür müssen wir zunächst zeigen, wie wir die Transaktionen auf der ersten Ebene dazu verwenden, die Transaktionsschritte atomar und dauerhaft zu gestalten und welche zusätzlichen Bedingungen erfüllt sein müssen, wenn wir alle möglichen Fehlersituationen berücksichtigen wollen. 3.3.1 Atomizität und Dauerhaftigkeit von Transaktionsschritten Wir können aufgrund der Diskussionen des Transaktions- sowie des Formularmodells von folgenden zwei Voraussetzungen ausgehen: 1. Das Transaktions-Modell verlangt Idempotenz der Schritte. Diese können also gefahrlos wiederholt werden. 2. Timer im Formular sorgen dafür, dass Anfragen sooft wiederholt werden, bis sie erfolgreich ausgeführt werden. In Kombination ergeben sich daraus Anfragen mit einer exactly-once-Garantie in Bezug auf die Ausführung. Damit werden Ausfälle folgender Komponenten abgedeckt, indem die Komponente wiederhergestellt und der Schritt wiederholt wird. Die Nummerierung entspricht dabei den Fehlersituationen in Abbildung 3.11. 1. Datenbankfehler: Da alle Operationen eines Schrittes in eine ACID-Transaktion eingeschlossen sind, werden Transaktionen abgebrochen und können wiederholt werden. Medienfehler werden von der Wiederherstellung der Datenbank abgedeckt. 2. Kommunikation zwischen Datenbank und Web-Service: Netzwerkfehler führen zu einem Verbindungsabbruch. Die Transaktion ist entweder erfolgreich abgeschlossen oder wurde abgebrochen. Der Web-Service kann im Unklaren über den Transaktionszustand sein und überprüft in einer neuen Transaktion anhand der Metadaten, ob alle Änderungen in der Datenbank angekommen sind. 45 Kapitel 3 TransForm 3. Web-Service: Bei einem Absturz kann die Ausführung aufgrund der Idempotenz wiederholt werden. Das muss allerdings nach Ablauf des Timers vom Formular initiiert werden. 4. Kommunikation zwischen Formular und Web-Service: Die Folge ist wie in 3., dass keine Antwort beim Formular ankommt. Die Anfrage wird nach Ablauf des Timers wiederholt. 5. Absturz des Browsers: Nachdem der Benutzer den Browser erneut gestartet hat, wird der Zustand aus Cookies wiederhergestellt. Damit ist klar, dass jeder Transaktionsschritt genau einmal effektiv ausgeführt wird und atomar und dauerhaft in Bezug auf die Datenbank ist. 3.3.2 TransForm-Transaktionen Eine Ebene über den Transaktionsschritten wollen wir uns nun den ACID-Eigenschaften unserer Transaktionen widmen. Wir müssen uns dazu mögliche Fehlersituationen ansehen und Bedingungen für einen Schedulingalgorithmus zusammenstellen, die genügen, damit dieser die ACID-Eigenschaften garantiert. Diskussion möglicher Fehlersituationen Wir müssen dabei zwischen Transaktionsfehlern, also nicht zu Ende gebrachten Transaktionen, und Systemfehlern, also dem Ausfall bzw. Absturz von Komponenten unterscheiden. • Transaktionsfehler entstehen, wenn Benutzer oder Scheduler Transaktionen abbrechen (abort). Diese müssen im Schedulingalgorithmus berücksichtigt werden. • Systemfehler bezeichnen im Allgemeinen Fehlersituationen, die zu Hauptspeicherverlust und damit verbunden dem Verlust des Zustands führen. Das betrifft bei uns den Webserver bzw. den Datenbankserver. Wir hatten im letzten Abschnitt gezeigt, wie Transaktionsschritte trotz Ausfällen in diesen Komponenten genau einmal durchgeführt werden können. • Medienfehler entstehen normalerweise durch Verlust des Hintergrundspeichers und bezeichnen Fehlersituationen im externen Speicher, also der Festplatte. Da wir ein Datenbanksystem als Hintergrundspeicher einsetzen, können wir uns auf dessen Wiederherstellungsstrategien verlassen, mit deren Hilfe es die Dauerhaftigkeit garantiert. • Netzwerkfehler betreffen den Verlust von Nachrichten. Wir hatten im letzten Abschnitt über die Transaktionsschritte gezeigt, wie diese mittels Timern bzw. Datenbankverbindungen umgangen werden. 46 3.3 ACID-Garantien • Fehler im Client betreffen bei uns einen Absturz des Browsers. Das Formularmodell fordert die Speicherung relevanter Daten in Cookies. Wir nutzen das aus, um nach einem Absturz den letzten Zustand im Browser wiederherzustellen. Wir gehen in der folgenden Diskussion davon aus, dass alle Fehler durch einen Neustart der Komponenten behoben werden und keine Komponente dauerhaft ausfällt und dass Netzwerkfehler lediglich den Ausfall einiger Nachrichten bewirken und dass immer wieder Nachrichten zugestellt werden. Es ist klar, dass ein dauerhafter Ausfall des Netzwerks, Webservers oder der Datenbank unser System unbenutzbar macht. Wir müssen also in den nächsten Abschnitten folgende Fehlersituationen behandeln: 1. Das Schedulingverfahren ist für die Handhabung von Transaktions- und Systemfehlern verantwortlich und muss die Strategien aus Abschnitt 3.3.3 für die Handhabung dieser Fehler berücksichtigen. 2. In Abschnitt 3.3.4 stellen wir die Wiederherstellungs-Strategie nach Browserabstürzen mittels Cookies vor. 3.3.3 Recovery-Strategien im Web-Service Es ist das einfachste und sicherste Verfahren, genau mit dem Commit alle Transaktionseffekte in den Hintergrundspeicher zu übertragen. Das wird aber üblicherweise aus Gründen der Performance nicht gemacht: • Da solche Systeme direkten Zugriff auf die Systemressourcen haben, können sie Gebrauch von unterschiedlich performanten Speicherarten wie Hauptspeicher, Cache, Log und Hintergrundspeicher machen. Transaktionseffekte werden dann normalerweise nicht direkt mit dem Commit in den Hintergrundspeicher übertragen, sondern bleiben in einer der schnelleren Speicherarten. • Es kann für die Nebenläufigkeitskontrolle ein weniger restriktives Kriterium als Serialisierbarkeit verwendet werden, wie wir bei der Diskussion der Isolationslevel gesehen hatten. Bei diesen sind Effekte anderer Transaktionen schon vor deren Abschluss sichtbar. So wird mehr Parallelität und infolgedessen eine höhere Gesamtperformance erreicht. Somit müssen bei Transaktionsabbrüchen eventuelle Effekte der Transaktionen im Hintergrundspeicher rückgängig gemacht und bei System- und Medienfehlern eine sogenannte Restart-Prozedur durchlaufen werden. Das wird in klassischen Datenbanksystemen von einem undo/redo-Algorithmus übernommen. Dabei gilt: Ein undo macht Effekte abgebrochener Transaktionen rückgängig und 47 Kapitel 3 TransForm sorgt somit für Atomizität, während ein redo die Dauerhaftigkeit von Effekten abgeschlossener Transaktionen sicherstellt. Dazu wird eine sogenannte Log-Datei geführt, die Veränderungen der Datenobjekte und Anfang und Ende von Transaktionen protokolliert und die für jede Schreibaktion einer Transaktion das sogenannte before-Image und das after-Image speichert. Da unser Metadatenmodell für die Speicherung des Transaktionszustands in Anlehnung an solche Log-Dateien entstanden ist, erfüllt es alle Voraussetzungen für die Umsetzung einer der üblichen Strategien für den Restart. Transaktionsfehler Wir hatten für die Implementierung der Idempotenz gefordert, dass alle Datenzugriffe in den Metadaten festgehalten werden, damit das System erkennen kann, ob die angeforderte Operation schon einmal erfolgreich ausgeführt wurde oder nicht. Irgendwann müssen die Effekte der Transaktionen aber im Nutzdatenbereich der Datenbank materialisiert werden. Wenn wir das erst bei Commit machen, können wir UndoSituationen komplett vermeiden, da es genügt, die Effekte der Transaktion aus den Metadaten zu löschen. Es entsteht auch kein Performance-Penalty, da wir auf diese Art nicht mehr Zugriffe auf den Hintergrundspeicher benötigen, sondern eher weniger: Eventuell können mehrere Updates in einem Statement der Datenbanksprache zusammengefasst werden. Wir fordern deshalb eine deferred-update-Strategie für Scheduler, die keine Effekte vor Transaktionsende also vor der Commit-Operation im Hintergrundspeicher der Datenbank bewirken. Systemfehler In TransForm können wir unser System nicht so frei organisieren wie eine Datenbank die Ressourcen des Datenbankservers. In einem TransForm-System existiert aber neben dem Hauptspeicher lediglich eine Speicherart: die Datenbank. Da in dieser sowohl Metadaten als auch Nutzdaten gespeichert werden, kann auf beide gleich schnell zugegriffen werden. Deshalb ist eine Strategie sinnvoll, die sowohl ohne Undo- als auch ohne Redo-Situationen auskommt. Wir fordern also von einem Scheduler, dass die Commit-Operation alle Effekte der Transaktion im Hintergrundspeicher materialisiert. 3.3.4 Wiederherstellung nach Browserabstürzen Die prinzipielle Handhabung von Browserabstürzen haben wir in der Diskussion des Formularmodells beschrieben. Die Zustände aller Formulare und die Inhalte aller Formularelemente werden über Cookies persistent im Browser gespeichert und können so bei einem Neustart wiederhergestellt werden. 48 3.3 ACID-Garantien Wir müssen dabei unterschiedliche Absturzzeitpunkte unterscheiden. Wenn der Browser noch vor Transaktionsbeginn abstürzt, genügt es, die Seite erneut aufzurufen. Der kritische Punkt ist, wenn der Browser abstürzt, nachdem eine Transaktion serverseitig gestartet wurde, die Speicherung der Transaktions-ID im Cookie aber noch nicht erfolgt ist. Nach einem Neustart hat das Formular keine Kenntnis von dieser Transaktion. Es kommt zu einer Zombie-Transaktion im Web-Service. Da aber noch keine Daten bearbeitet wurden, entsteht kein wirklicher Schaden. Wenn der Browser abstürzt, nachdem das Cookie gesetzt ist, kann die Wiederherstellung wie geschildert erfolgen. Ähnliche Überlegungen gelten für die Speicherung von Inhalten von Formularelementen. Wenn der Absturz vor Speicherung des gelesenen Initialwertes geschieht, enthält das Cookie keinen Wert und der Controller liest den Ausgangswert erneut ein. Alle Änderungen des Benutzers werden nun zuerst im Cookie gespeichert und dann erst an den Dienst weitergeleitet. Ein Absturz vor Speicherung des Cookies führt dabei zum Verlust der Änderung des Benutzers. Ein Absturz nach der Speicherung im Cookie, aber bevor der neue Wert an den Webservice übermittelt werden konnte, ist zunächst unkritisch, da der neue Wert im Formular wiederhergestellt werden kann. Das Formular kann allerdings nicht wissen, ob der neue Wert auch im Dienst gespeichert ist. Deshalb wird dieser Wert zur Sicherheit vor dem Commit noch einmal an den Dienst übertragen, wenn er nicht durch eine weitere Änderung überschrieben wurde. Der letzte erwähnenswerte Absturzzeitpunkt ist nach erfolgreichem Abschluss oder Abbruch der Transaktion aber noch bevor die Transaktions-ID im Cookie gelöscht wurde. In diesem Fall startet der Formularmanager einen unnötigen Wiederherstellungprozess, der allerdings nach der ersten Kontaktaufnahme mit dem Dienst abgebrochen werden kann, da dann der Formularmanager das Transaktionsende erfährt. 3.3.5 Anforderungen an Scheduler Es ergeben sich also folgende Anforderungen, die Schedulingprotokolle einhalten müssen: • deferred-update-Strategie: Ein TransForm-Schedulingprotokoll muss alle Transaktionseffekte in der Commit-Operation in die Datenbank schreiben. • Striktheit: Vermeidet den Zugriff auf Daten, wenn die Transaktion, die diese zuletzt geschrieben hat, noch aktiv ist, also noch abgebrochen werden kann. Wir vermeiden dadurch Situationen, in denen Transaktionen kaskadierend abgebrochen werden müssen, weil wir in unserem Modell keine solchen kaskadierenden Abbrüche umsetzen können. • Idempotenz: Eine wiederholte Ausführung eines Transaktionsschrittes darf zu keinen Seiteneffekten führen und muss exakt die gleiche Antwort zurückliefern wie die erste Ausführung des Schrittes. 49 Kapitel 3 TransForm Wir können also in TransForm mittels eines geeigneten Schedulingverfahrens die ACIDEigenschaften garantieren: Atomizität: Die Atomizität fordert, dass die durch eine Transaktion bewirkten Zustandsänderungen der Daten entweder vollständig oder gar nicht vorgenommen werden. Wir erreichen das mittels der geforderten deferred-update-Strategie, bei der Schreiboperationen zunächst in den Metadaten ausgeführt werden und nur Änderungen erfolgreich abgeschlossener Transaktionen innerhalb der Commit-Operation in die Datenbank geschrieben werden. Wenn nun die Commit-Operation atomar durchgeführt wird und die Änderungen im Log persistent sind, können wir so die Atomizität der gesamten Transaktion garantieren. Konsistenz: Die Konsistenz fordert konsistente Zustandsübergänge in der Datenbank. Sie ist abhängig von der Datenbank und wird von dem Backend garantiert. Wir achten schon auf Clientseite darauf, dass abgeschickte Formularwerte den korrekten Typ haben. Sollte das Datenbankupdate während des Commits Integritätsverletzungen der Datenbank entdecken, wird die Transaktion abgebrochen. Isolation: Die Isolation behandeln wir in Kapitel 5, wo verschiedene Schedulingverfahren vorgestellt werden. Da unser Transaktionsmodell eng am klassischen Transaktionsmodell [EGLT76] angelehnt ist, können wir uns auf klassische Schedulerstrategien berufen, deren Korrektheit schon lange bewiesen ist. Dauerhaftigkeit: Die Dauerhaftigkeit fordert, dass abgeschlossene Transaktionen alle zukünftigen Fehlersituationen überdauern. Da alle Transaktionseffekte mit der Commit-Operation in die Datenbank geschrieben werden und der dazu nötige Transaktionsschritt dauerhaft ist, ist die Dauerhaftigkeit garantiert. 3.4 Komponenten und Schnittstellen Die bisher eingeführten Modelle werden von einem TransForm-System in verschiedenen Komponenten implementiert. Da diese entweder vorgefertigt übernommen werden oder eigenen Bedürfnissen angepasst werden können, ist es wichtig, ihre Schnittstellen genau festzulegen. Neben Formularen als einziger clientseitiger Komponente gibt es mehrere serverseitige, im Web-Service enthaltene Komponenten, die in Abbildung 3.12 dargestellt sind. Diese kommunizieren untereinander über eine Schnittstelle, die aus verschiedenen Funktionen besteht und die wir im Folgenden zusammen mit der Schnittstelle des Dienstes nach außen vorstellen wollen. 3.4.1 Komponenten im Webservice Abbildung 3.12 zeigt die beiden serverseitigen Schichten, den Datenmanager und den Transaktionsmanager zusammen mit ihren Komponenten. Der Transaktionsmanager als oberste Schicht bildet dabei die Schnittstelle des Web-Service nach außen, die im nächsten 50 3.4 Komponenten und Schnittstellen Authentifikationsmanager Scheduler Transaktionsmanager austauschbare Komponente Nutzdatenmanager Metadatenmanager Schichten (feste Komponente) Datenmanager Datenbank externer LoginDienst Abbildung 3.12: Die serverseitigen Komponenten von TransForm. Abschnitt besprochen wird. Seine Aufgabe ist es, Anfragen über diese Schnittstelle entgegenzunehmen, zu dekodieren und folgende zwei Komponenten damit zu füttern: • Der Authentifizierungsmanager überprüft die Authentizität der Anfrage bzw. des Anfragestellers. Normalerweise geschieht das mittels des Authentifizierungsmodells. Bei einem anonymen Dienst kann diese Überprüfung entfallen. • Der Scheduler überprüft die Integrität der Anfragen und führt diese aus. Dazu stehen ihm die Komponenten des Datenmanagers zur Verfügung. Wie gesehen, greifen die beiden Komponenten des Transaktionsmanagers dabei auf die Komponenten des Datenmanagers zurück, die sowohl die Nutzdaten als auch die Metadaten als Abstraktion der zugrundeliegenden Datenbank zur Verfügung stellen: • Der Nutzdatenmanager setzt das Datenmodell als Abstraktion für den Datenzugriff um und übersetzt dazu zwischen Ausdrücken des Datenmodells und der nativen Anfragesprache. • Der Metadatenmanager verwaltet Strukturen wie Read- und Writesets, Transaktionsstatus und Sessiondaten, die in derselben Datenbank wie die Nutzdaten gespeichert werden müssen. Die Schnittstelle des Nutzdatenmanagers Als Umsetzung des Datenmodells besteht die Schnittstelle des Datenmanagers prinzipiell aus Funktionen für die beiden elementaren Datenzugriffe r(x) und w(x, v). Da im Datenmodell für alle Arten von Schreibzugriffen nur eine Schreiboperation vorgesehen ist, 51 Kapitel 3 TransForm muss für die Unterscheidung von Insert- und Update-Operationen zuerst ermittelt werden, ob das entsprechende Objekt bereits in der Datenbank enthalten ist. Wir wollen für den Nutzdaten-Manager aber separate Funktionen für Insert, Update und Delete zur Verfügung stellen. read (o) Liest den Wert von Datenobjekt o aus der Datenbank und liefert diesen eventuell zusammen mit einer Liste anderer betroffener Datenobjekte zurück. write(o, v) Schreibt den Wert v in Datenobjekt o. Dabei wird intern eine der folgenden Funktionen verwendet: insert(o, v) Fügt Datenobjekt o mit Wert v in die Datenbank ein. update(o, v) Schreibt den Wert v in Datenobjekt o. delete(o) Löscht das Datenobjekt o. Diese Funktionen arbeiten immer direkt auf der Datenbank und sind nicht unmittelbar mit den gleichlautenden Funktionen des Schedulers verknüpft. Dieser ermittelt beispielsweise auch bei einem Schreibzugriff über das read des Nutzdatenmanagers die Liste der Objekte, die für die Konflikterkennung die Grundlage bilden. Die Schnittstelle des Metadatenmanagers Der Metadatenmanager bietet über seine Schnittstelle den Zugriff auf die internen Verwaltungstrukturen. Wir können hier nicht das komplette Interface angeben, da dieses sehr umfangreich ist. Es besteht im Wesentlichen aus Funktionen, mit denen man Einträge auslesen, löschen, einfügen und bearbeiten kann. Zusätzlich gibt es Funktionen für Mengenvergleiche zwischen den Datenzugriffstabellen, die für die Konflikterkennung notwendig sind. Die Scheduler-Schnittstelle Die Scheduler-Schnittstelle ist unabhängig von dem konkreten Schedulingprotokoll und sieht neben Funktionen für die unterschiedlichen Operationen der Transaktionsschritte auch die Funktion keep_alive() vor, über die ein Client dem Web-Service mitteilen kann, dass er noch aktiv ist. Außerdem sind neben allgemeinen Schreibzugriffen explizite Funktionen für insert, delete und update vorgesehen. Die Schnittstelle des Authentifikationsmanager Die Schnittstelle des Authentifikationsmanagers besteht aus den in Abschnitt 3.2.4 vorgestellten Funktionen für das Anmelden (login) und die Validierung einer Session-ID (validate) sowie gegebenenfalls für das Abmelden von Benutzern (logout) bzw. das Löschen einer Session (invalidate). 52 3.4 Komponenten und Schnittstellen 3.4.2 Die Web-Service-Schnittstelle Üblicherweise wird ein Web-Service mit der in Abschnitt 2.1.1 vorgestellten Protokollfamilie bestehend aus SOAP, UDDI und WSDL assoziiert. Allerdings sind weder ein Verzeichnisdienst wie UDDI für die Registrierung von Diensten noch eine Beschreibung der Schnittstelle durch WSDL für TransForm-Dienste zwingend erforderlich. Auch die Verwendung von SOAP als Schnittstelle für den Web-Service kommt für uns nicht in Frage, da es sowohl server- als auch clientseitig einen größeren Overhead mit sich bringt als die HTTP/CGISchnittstelle, die für unsere Belange völlig ausreichend ist. In unserer Schnittstelle bilden wir jeden Transaktionsschritt auf einen einzelnen HTTPAnfrage-Antwort-Zyklus ab. Die Anfrage-Parameter werden dabei als HTTP-Variablen übergeben. Normalerweise verwenden wir dabei für alle Zugriffsarten die HTTP-GET-Methode. Alternativ kann aber auch auf die POST-Methode zurückgegriffen werden, wenn es die Anfragelänge erfordert. Die Antwort besteht aus einem XML-Dokument mit einer fest vorgegebenen Struktur, was die Verarbeitung im Browser erleichtert. Wir verfolgen also einen Ansatz, der einige Gemeinsamkeiten mit den aus Abschnitt 2.1.1 bekannten REST-basierten Web-Diensten besitzt, sich allerdings in einigen Punkten von diesen unterscheidet. Gemeinsamkeiten bilden dabei die Abbildung von Ressourcen auf URIs, HTTP-Anfragen als Kommunikationsgrundlage, sowie der Einsatz von XML. Der größte Unterschied ist die Abbildung unterschiedlicher Zugriffsarten auf jeweils eigene HTTP-Methode bei REST, die allerdings aufgrund der Idempotenz der Transaktionsschritte bei uns nicht erforderlich ist. Anfragen Die Schnittstelle des Web-Service besteht aus den Schnittstellen-Funktionen der Komponenten des Transaktionsmanagers in Abbildung 3.12, also des Schedulers und des Authentifizierungsmanagers. Der Aufruf einer solchen Schnittstellen-Funktion erfolgt dabei als HTTP-Anfrage an die URL des Web-Service, wobei die gewünschte Operation dem Dienst über die HTTP-Variable action mitgeteilt wird. Dabei müssen für die einzelnen Funktionen folgende Actions angegeben werden: B (begin), A (abort), C (commit), R (read), W (write), I (insert), U (update), D (delete), L (login), O (logout), V (validate), X (invalidate). Beispielsweise wird über folgende HTTP-Anfrage eine neue Transaktion gestartet (action=B): http://transform.informatik.uni−freiburg.de/pfad/zu/webservice?action=B Abhängig von der aufgerufenen Operation sind neben der action-Variablen weitere Parameter erforderlich, die alle dem jeweiligen Dienstaufruf als HTTP-Variablen angehängt werden. Der Web-Service akzeptiert dabei folgende Parameter: 53 Kapitel 3 TransForm tid Dieser Parameter spezifiziert den Identifizierer der Transaktion. xpath Dieser Parameter enthält den XPath-Ausdruck, über den ein Datenobjekt entweder gelesen oder geschrieben wird. value Durch diese Variable kann der neue Wert eines Datenobjekts bei einer Schreiboperation angegeben werden. session Über diesen Parameter kann der Aufruf einer Session zugeordnet werden. protocol Über diese Variable lässt sich ein Schedulingprotokoll bzw. eine Variante eines Protokolls festlegen bzw. lässt sich überprüfen, ob es von dem Scheduler des Dienstes unterstützt wird. uid Dieser Parameter gibt die Benutzer-ID bei der Authentifizierung an. pwd Dieser Parameter Authentifizierung. rid Über diesen Parameter kann der Anfrage eine Identifizierung zugewiesen werden, die manche Scheduler benötigen. prepared Über diesen Parameter kann beim 2-Phasen-Commit-Protokoll festgelegt werden, ob ein Commit lediglich präpariert werden soll. enthält das Passwort für die Benutzer- In den verschiedenen Operationen werden nun einige dieser Parameter zwingend erwartet, andere sind optional. Rückgabeformat Die Rückgabe besteht immer aus einem XML-Dokument, das eine feste Struktur gemäß unserem Rückgabeformat hat, das in Abbildung 3.13 dargestellt ist. Das <response>-Tag bildet als Wurzelelement den Rahmen und enthält als Attribut die Anfragedauer. Sein erstes Kindelement ist das <request>-Tag, das die gewünschte action und alle GET-Variablen als Attribute besitzt. Mögliche POST-Variablen der Anfrage werden in entsprechenden Tags als Kinder eingefügt. Auch wenn diese Informationen für die eigentliche Antwort nicht notwendig sind, sind sie für die Fehlersuche sehr hilfreich. Das <status>-Tag liefert den Status der Anfrage als Code und im Klartext zurück. Eventuell auftretende Konflikte werden über das <conflict>-Tag signalisiert. Der eigentliche Rückgabewert ist der Inhalt des <result>-Tags. Dabei kann es sich um einen einfachen Wert handeln oder auch um eine weiter strukturierte Rückgabe. Der Typ der Rückgabe kann dabei im type-Attribut angegeben sein. 54 3.4 Komponenten und Schnittstellen <response duration=”Anfragedauer” ...> <request action=”operation” ... alle GET-Parameter ... /> <post name=”parametername”>Parameter-Inhalt </post> ...eventuelle weitere POST-Parameter </request> <status code=”statuscode”>statustext</status> <conflict>Konfliktstatus</conflict> <result type=”ergebnistyp”> Anfrageergebnis </result> </response> Abbildung 3.13: Das XML-basierte Rückgabeformat. 3.4.3 Formulare als Browser-Komponenten Im Gegensatz zum Web-Service gibt es im Browser lediglich eine Komponente. Es handelt sich dabei um den Formular-Manager, der das Formularmodell aus Abschnitt 3.2 im Browser in die Realität umsetzt. Wie wir schon in Abbildung 1.3 gesehen haben, werden Formulare in Anlehnung an HTML-Formulare über Tags im Quelltext einer Webseite definiert. Der Formularmanager übersetzt nun alle im Seitenquelltext definierten TransForm-Tags in sichtbare Formularelemente und Bearbeitungschritte des Benutzers in Aufrufe des Web-Service. Dabei verwaltet der Formularmanager zwei Schnittstellen, die beide in Kapitel 6 beschrieben werden: • Die TransForm-Tags bilden das Programmierinterface für Anwendungsentwickler. • Die Formulare bilden die Benutzer-Schnittstelle, über die Anwender mit einem TransForm-System interagieren. Dabei unterscheidet sich der Umgang mit TransForm-Formularen für Benutzer oft nicht von dem mit normalen Webformularen. 55 Kapitel 4 Backends Wir sind in der bisherigen Diskussion schuldig geblieben, wie der Datenzugriff auf unterschiedliche Backend-Datenbanken konkret erfolgen soll. Im Datenmodell war lediglich von Datenobjekten die Rede, die als XML-Elemente bzw. Attribute modelliert und via XPathartigen Ausdrücken adressiert werden. Der eigentliche Datenzugriff ist mittels elementarer Lese- und Schreiboperationen auf diesen Objekten vorgesehen. Wir wollen nun zunächst eine Charakterisierung unterschiedlicher Backends vornehmen und die Eignung verschiedener Typen von Datenbanksystemen als Backends diskutieren. 4.1 Charakterisierung verschiedener Backends Wir müssen dabei zwischen generischen Backends, die unabhängig vom Datenbankschema agieren, und anwendungsspezifischen Backends unterscheiden, die jeweils an ein spezielles Datenbankschema gebunden sind. Anwendungsspezifische Lösungen werden für ein konkretes Anwendungsszenario maßgeschneidert. Dieser erhöhte Aufwand einer individuellen Anpassung birgt einige Vorteile in sich, da die Modellierung der Datenbank sowie die Struktur der Anfragen völlig frei gestaltet werden kann. So kann die Übersetzung der Datenzugriffe in die native Anfragesprache und die Konflikterkennung üblicherweise mit einem geringeren Overhead als bei generischen Lösungen erfolgen. Weiterhin kann das Schema der zugrundeliegenden Datenbank verborgen bleiben und etwaige Schemaänderungen können so gestaltet werden, dass die Syntax der Anfragen unverändert bleibt in Anlehnung an die Datenunabhängigkeit relationaler Datenbanken. Abschnitt 4.3 skizziert diese Möglichkeiten anhand eines konkreten Szenarios. Generische Backends sind nicht speziell auf ein konkretes Datenbankschema zugeschnitten, sondern definieren eine allgemeingültige Modellierung und Übersetzung der Datenzugriffe in die entsprechende Anfragesprache. Abschnitt 4.2 stellt eine solche generische Lösung für den wichtigen Fall der relationalen Datenbanken vor. 56 4.1 Charakterisierung verschiedener Backends 4.1.1 Datenbank-Typen Als Backends für TransForm kommen nicht nur relationale Datenbanken in Frage, sondern prinzipiell alle Speichersysteme, die sich gemäß unseres Datenmodells in disjunkte Datenobjekte aufteilen lassen. Aufgrund der XML-Modellierung bilden native XML-Datenbanken auf den ersten Blick ein ideales Backend. Obwohl XPath direkt unterstützt wird, können wir die Auswertung allerdings nicht ausschließlich der XML-Datenbank überlassen. Zueinander in Konflikt stehende Zugriffe müssen trotzdem von TransForm erkannt werden, was innerhalb des zugrundeliegenden semistrukturierten Datenmodells aber schwieriger ist als bei starren Modellen wie dem relationalen. Weitere Nachteile im Vergleich mit relationalen Datenbanken sind die weniger ausgeprägte Unterstützung von Transaktionskonzepten sowie die geringe Verbreitung der Systeme bei Webhosting-Anbietern. Obwohl Dateisysteme keine eigentlichen Datenbanksysteme sind und auch keine Transaktionsunterstützung bieten, haben sie ihre Berechtigung als TransForm-Backend, da sie sehr verbreitet sind und in jedem Webhosting-Angebot unterstützt werden. Die Daten sehr spezieller Datenbanken wie beispielsweise Multimediadaten werden oft in Dateisystemen gespeichert. Da Dateipfade eine Untermenge von XPath darstellen, ist die Abbildung trivial. Allerdings müssen hier entweder Kompromisse in Bezug auf die ACID-Eigenschaften eingegangen werden oder die Atomizität einzelner Schritte selbst implementiert werden. In Abschnitt 4.4 wollen wir die Gestaltung eines solchen Backends anhand von MP3-Dateien skizzieren. Das einfache Datenmodell eingebetteter Key-Value-Datenbanken wie der Berkeley DB [OBS99] passt in idealer Weise zu dem Datenmodell von TransForm: Datensätze werden über einen String-basierten Schlüssel adressiert, enthalten einen beliebigen Wert und können gelesen und geschrieben werden. Im Gegensatz zu einem Dateisystem bietet beispielsweise die Berkeley DB native Unterstützung für Transaktionen. Durch die Einbettung als Bibliothek in den Anwendungsprozess, entsteht ein Performancevorteil gegenüber externen Servern. Schwierigkeiten ergeben sich hier allerdings in der Speicherung der Metadaten. Wenn von Datenbanken gesprochen wird, sind üblicherweise die sehr verbreiteten relationalen Datenbanksysteme gemeint, für die es ein breites Spektrum von verfügbaren Angeboten gibt. Sie bieten ein ausgefeiltes Transaktionsmanagement und bilden die wichtigsten Backends für TransForm. 4.1.2 Zugriff auf relationale Datenbanken Für den Zugriff auf eine XML-Sicht einer relationalen Datenbank mittels XPath-Ausdrücken gibt es unterschiedliche Möglichkeiten: Zum einen könnte die XML-Sicht der Datenbank instantiiert und anschließend XPath-Ausdrücke auf dieser Instanz ausgewertet werden. Diese Möglichkeit ist aber komplex und wenig performant, da eine aktuelle XML-Sicht für jede 57 Kapitel 4 Backends Anfrage erzeugt werden müsste. Eine direkte Übersetzung von XPath in SQL-Anfragen ohne den Umweg über XML bietet im Vergleich dazu viele Vorteile, obwohl das Backend XPath-Ausdrücke selbst parsen muss. Der unterstützte Sprachumfang kann eingeschränkt werden, was die Erkennung von Konflikten erleichtert. Die Rückgabe kann direkt aus den SQL-Anfragen konstruiert werden und muss dabei nicht unbedingt dem über den XPath-Ausdruck spezifizierten XMLFragment entsprechen. Insgesamt wird der Overhead reduziert, da immer nur der relevante Ausschnitt der Datenbank ausgelesen werden muss. XML dient als Strukturvorgabe und gibt den Raum aller möglichen XPath-Ausdrücke vor. Die akzeptierte Menge der XPath-Ausdrücke kann weiter eingeschränkt werden, um das Parsen zu erleichtern und zu beschleunigen. Wenn man diesen Ansatz für ein anwendungsspezifisches Backend einsetzt, entsteht eine ähnliche Lösung wie bei dem Template-Ansatz aus [KK00], wo eine XML-basierte TemplateDatei spezielle, mit SQL-Anfragen hinterlegte Tags enthält, die das XML-Fragment ihres Teilbaumes direkt aus dem Ergebnis dieser SQL-Anfrage erzeugen. Allerdings wird dabei kein komplettes Dokument erzeugt und die Anfrageergebnisse müssen auch nicht den kompletten Teilbaum umfassen. Unterschiedliche Hierarchieebenen können für die Spezifikation von Anfrageparametern benutzt werden. Auch die Konflikterkennung kann an die Bedürfnisse der Anwendung angepasst werden. 4.2 Generischer Zugriff auf Relationale Datenbanken Im Folgenden wollen wir zeigen, wie ein Backend aussehen kann, mit dem generisch auf relationale Datenbanken zugegriffen werden kann. Wir definieren dazu ein Modell beliebiger relationaler Datenbankinstanzen in XML, eine XML-Sicht. XPath-Ausdrücke auf dieser Sicht entsprechen dann den Objekten unseres Datenmodells. Da der eigentliche Zugriff auf relationale Datenbanken immer über SQL erfolgt, müssen wir die XPath-Ausdrücke je nach Art des Zugriffs, also lesend oder schreibend, in Select-, Update-, Insert- oder DeleteStatements übersetzen. Es wird dabei aber weder für die Auswertung der XPath-Ausdrücke noch für die Rückgabe nötig sein, die XML-Sicht zu materialisieren. Die entsprechenden SQL-Statements werden direkt aus den XPath-Ausdrücken erzeugt und die XML-basierte Rückgabe ergibt sich direkt aus den Ergebnissen dieser SQL-Anfragen. Bei der Sicht handelt es sich also um ein rein virtuelles XML-Dokument, das der Instanz der relationalen Datenbank entspricht und den Raum für mögliche XPath-Ausdrücke definiert. Obwohl unsere Sicht prinzipiell mit dem in Kapitel 2 vorgestellten XML-Publishing vergleichbar ist, gibt es doch einen entscheidenden Unterschied: Da das XML-Dokument nicht dem Datenaustausch dient und es auch niemals vollständig materialisiert wird, spielt die Größe der Sicht eine untergeordnete Rolle. So kann durch Einführung zusätzlicher Redun- 58 4.2 Generischer Zugriff auf Relationale Datenbanken city id name FR Freiburg B Berlin P Paris country D D F pop 217.547 3.405.342 2.138.551 country id name D Deutschland F Frankreich pop 82.310.000 64.102.140 area 357.092 672.352 Abbildung 4.1: Die Beispieldatenbank Mondial. danzen die Beschränkung von XPath auf Semijoins umgangen werden, indem Tupel an Stellen, an denen sie als Joinpartner in Frage kommen, redundant aufgeführt sind. Im Folgenden werden wir dieses relationale Backend Stück für Stück entwickeln, indem wir zuerst einen nicht redundanten Kern der Sicht definieren, auf dem sowohl einfache Selektions- bzw. Projektionsanweisungen als auch Einfüge-, Lösch- und Änderungsoperationen definiert sind. Anschließend werden wir zeigen, wie zueinander in Konflikt stehende Zugriffe erkannt werden, bevor wir unsere Anfragen schließlich um einfache Joins mittels Redundanzen in der Sicht erweitern. Als Beispiel wird uns dabei die in Abbildung 4.1 gezeigte Datenbank dienen. Es handelt sich dabei um einen Ausschnitt der Lehrdatenbank Mondial mit den beiden Tabellen city und country. 4.2.1 Die XML-Sicht der Datenbank In TransForm ist die XML-Sicht immer über einer virtuellen Datenbank definiert und enthält alle Tupel der Tabellen dieser Datenbank. Eine solche Datenbank kann dabei eine komplette relationale Datenbank oder aber auch nur einen konfigurierbaren Ausschnitt mit festgelegten Tabellen umfassen. Der Zugriff auf bestimmte Tabellen kann so unterbunden werden. Wenn wir im Folgenden von einer Datenbank sprechen, ist damit immer der von der Sicht definierte Ausschnitt einer kompletten relationalen Datenbank gemeint. Der Kern einer TransForm-Sicht ist sehr einfach strukturiert. Das Wurzelelement bildet den Container für eine Datenbank, deren Name dabei dem Namen des Wurzelelements entspricht. Innerhalb der Wurzel sind die Tupel aller Relationen als direkte Kindelemente enthalten, wodurch eine sehr flache Hierarchie entsteht. Der Name der Tupel-Elemente entspricht dem Namen der jeweiligen Tabelle. Die Attribute dieser Tupel-Elemente repräsentieren die Spalten der Tabellen. Die DTD der Beispieldatenbank in Abbildung 4.1 enthält zunächst folgende Elementdefinitionen für das Wurzelelement sowie die beiden Tabellen: <!DOCTYPE mondial [ <!ELEMENT mondial (city∗, country∗)> <!ELEMENT city (EMPTY)> <!ELEMENT country (EMPTY)> 59 Kapitel 4 Backends <mondial> <city id="FR" name="Freiburg" country="D" pop="217.547" /> <city id="B" name="Berlin" country="D" pop="3.405.342" /> <city id="P" name="Paris" country="F" pop="2.138.551" /> <country id="D" name="Deutschland" pop="3.405.342" area="357.092" /> <country id="F" name="Frankreich" pop="2.138.551" area="672.352" /> </mondial> Abbildung 4.2: Die XML-Sicht der Mondial-Beispieldatenbank. Das Wurzelelement mondial darf beliebig viele city-Elemente und country-Elemente enthalten, eventuell auch gar keine, wenn beide Tabellen leer sind. Tupelelemente enthalten keine weiteren Elemente, allerdings muss für jede Elementdefinition noch eine Attributliste ergänzt werden, die sich aus den Spalten der jeweiligen Tabelle ergibt. Alle Attribute erhalten die Typdefinition CDATA #REQUIRED. <!ATTLIST city id CDATA #REQUIRED name CDATA #REQUIRED country CDATA #REQUIRED pop CDATA #REQUIRED> <!ATTLIST country id CDATA #REQUIRED name CDATA #REQUIRED pop CDATA #REQUIRED area CDATA #REQUIRED> ]> Die entsprechende Instanz des XML-Dokuments für unsere Beispieldatenbank ist in Abbildung 4.2 dargestellt. Innerhalb des Wurzelelements sind sowohl alle drei Tupel von city als auch beide country-Tupel als Element enthalten. Die Attribute dieser Elemente enthalten die jeweiligen Werte der Spalten der relationalen Tabellen. Abbildung 4.3 zeigt dieses XML-Modell als Baum. Die ovalen inneren Knoten entsprechen dabei den Elementen und die Rechtecke stehen für Attribute und bilden die Blätter. 4.2.2 Datenzugriff über XPath Auf der im letzten Abschnitt definierten XML-Sicht lassen sich nun die Objekte des Datenmodells mittels XPath-Ausdrücken spezifizieren. Zugelassen ist dabei aber lediglich eine Untermenge von XPath, bei der insbesondere die Achsen auf die Child-Achse beschränkt sind. Durch die starre Struktur lässt sich solch ein Ausdruck aber alleine durch lexikalische Analyse in SQL übersetzen. Die XPath-Ausdrücke haben immer die folgende Struktur: 60 relDBXML 4.2 Generischer Zugriff auf Relationale Datenbanken mondial ... city id='FR' ... country='D' country id='D' ... area= '357.000' Abbildung 4.3: Ein Ausschnitt des XML-Modells der Beispieldatenbank in Baumdarstellung. /db/table[cond1 ]...[condn ]/@column (4.1) db steht dabei für den Namen der Datenbank. Er wird verwendet um in der Konfiguration zu überprüfen, ob der Zugriff auf die angeforderte Tabelle der relationalen Datenbank erlaubt ist. table gibt den Namen der Tabelle an, auf die zugegriffen werden soll. cond1 ... condn steht für eventuell mehrere Selektionsbedingungen, die in der where-Klausel des SQL-Statement Und-verknüpft sind. Eine einzelne Selektionsbedingung kann dabei Attribute untereinander oder mit Konstanten über SQL-Vergleichsoperationen enthalten. column steht für ein Attribut, das im letzten Lokationsschritt schließlich über die Attributachse ausgewählt wird. Mit unseren XPath-Ausdrücken lassen sich also Selektionen und Projektionen in folgender Form ausdrücken: π[column](σcond1 ...σcondn table) (4.2) Ausgehend von einer Tabelle werden dabei durch eventuell mehrere aufeinanderfolgende Selektionsbedingungen (σcond1 ...σcondn ) Tupel ausgewählt und diese schließlich mit der abschließenden Projektion π auf ein Attribut reduziert. Bezogen auf die Baumdarstellung in Abbildung 4.3 führt ein Ausdruck nach Muster 4.1 also immer auf die unterste Ebene zu Blättern, die ja den Feldern der Datenbank entsprechen. Es ist klar, dass dabei genau eine Spalte betroffen ist. Allerdings können je nach Selektionsbedingung auch mehrere Tupel betroffen sein. Da es schlussendlich aber vom Anwendungskontext abhängig ist, ob ein solcher XPathAusdruck genau ein Datenobjekt spezifizieren muss oder eventuell ein XML-Fragment zurückliefern kann, muss seitens der Formulare überprüft werden, ob das Ergebnis den Erwartungen entspricht. 61 Kapitel 4 Backends Deshalb wird im <result>-Tag der Rückgabe in dem Attribut type der Typ der Rückgabe spezifiziert. Falls der Inhalt eines Datenbankfelds zurückgeliefert wird, ist ein atomarer Typ wie Integer oder String angegeben. Sollte mehr als ein Datenbankfeld in der Rückgabe enthalten sein, ist diese als XML-Fragment weiter strukturiert und der Typ lautet ’XML’. Formulare können nun anhand des Rückgabe-Typs erkennen, wie viele Felder betroffen sind und brechen gegebenenfalls die Transaktion mit einer entsprechenden Fehlermeldung ab. Datenzugriffsoperationen Für den Datenzugriff sieht das Datenmodell elementare Lese- und Schreiboperationen vor, über die der Wert eines solchen per XPath-Ausdruck spezifizierten Datenobjekts entweder gelesen oder geschrieben werden kann. Das Backend sieht dabei für die drei Arten von Schreibzugriffen jeweils separate insert-, update- und delete-Operationen vor. Für die Ausführung des Datenzugriffs müssen diese Operationen nun in geeignete SQL-Statements übersetzt werden. Bei Leseoperationen werden dabei neben dem Wert des Datenobjekts alle für die Konfliktberechnung relevanten Datenobjekte ermittelt. Diese Operationen werden nun vom Scheduler für die Implementierung seines Verfahrens benutzt. Während er Leseoperationen üblicherweise direkt über read an das Backend zur Ausführung weiterleitet, ermittelt er bei Schreibzugriffen zunächst lediglich die betroffenen Datenobjekte (auch über read) und hinterlegt diese zusammen mit dem zu schreibenden Wert in den Metadaten. Erst bei Transaktionsende werden über die Schreiboperationen des Backends die Transaktions-Effekte in die Datenbank übertragen. Dabei werden alle Schreibzugriffe auf demselben Tupel akkumuliert in einem SQL-Statement ausgeführt. In den folgenden Betrachtungen dieser Operationen setzen wir stillschweigend voraus, dass alle XPath-Ausdrücke genau ein Datenobjekt adressieren, also genau ein Attribut eines Tupels betreffen. Lesezugriff Für die Auswertung von lesendem Zugriff müssen die XPath-Ausdrücke in Select-Anfragen übersetzt werden. Dazu werden zunächst die Selektionsbedingungen cond1 bis condn , die Spalte column sowie der Tabellenname table aus dem XPath-Ausdruck extrahiert, um anschließend eine Anfrage in folgender Form zusammensetzen zu können: SELECT FROM WHERE column table cond1 ... AND condn Die Rückgabe enthält neben dem Ergebnis der SQL-Anfrage noch dessen Typ, der aus den Metadaten extrahiert wird. Zusätzlich werden alle von der Anfrage betroffenen Datenobjekte zurückgeliefert, die für die Konfliktberechnung (siehe Abschnitt 4.2.3) nötig sind. 62 4.2 Generischer Zugriff auf Relationale Datenbanken Schreibzugriffe Bei Schreibzugriffen wird dem XPath-Ausdruck ein Wert zugewiesen: /db/table[cond1 ]...[condn ]/@column = value Änderungsoperationen Updates sind als direktes Gegenstück zu Leseoperationen die häufigsten Schreiboperationen bei TransForm, da sie immer zum Einsatz kommen, wenn Benutzer Formularinhalte geändert haben und diese Änderungen bei Transaktionsabschluss in die Datenbank geschrieben werden. Neben dem neuen Wert value müssen auch hier die Tabelle table, die Selektionsbedingungen condn und die betroffene Spalte column bekannt sein, um ein UpdateStatement der folgenden Form zu erzeugen: UPDATE SET WHERE table column = value cond1 ... AND condn Jedes Update betrifft dabei genau ein Feld der Datenbank. Da Update-Operationen des Backends üblicherweise erst bei Transaktionsabschluss aufgerufen werden, sind in den Metadaten möglicherweise Änderungen für mehrere Felder eines Tupels hinterlegt. In diesem Fall können alle Update-Operationen auf diesem Tupel akkumuliert ausgeführt werden, indem alle betroffenen Spalten und deren neue Werte in der SET-Klausel des Statements zusammengefasst werden: SET column1 =value1 , ..., columnk =valuek Einfügeoperationen Im Gegensatz zu Änderungen müssen Einfüge-Operationen akkumuliert durchgeführt werden, da immer nur komplette Tupel eingefügt werden können. Aus den hinterlegten Werten valuei der Spalten columni wird dabei ein Insert-Statement auf Tabelle table der folgenden Form erzeugt: INSERT INTO VALUES table ( column1 , ..., columnn ) ( value1 , ..., valuen ) Das Insert-Statement fügt dabei für jede nicht aufgelistete Spalte entweder deren Vorgabewert oder einen NULL-Wert ein. Sollte beides nicht möglich sein, wird ein Fehler signalisiert. Wenn innerhalb einer Transaktion mehrere Tupel in dieselbe Tabelle eingefügt werden sollen, entsteht das Problem, die einzelnen Werte den Tupeln zuzuordnen. Da für jede Tabellenspalte eventuell mehrere Werte zur Verfügung stehen, ist es nicht eindeutig, wie diese den einzelnen Tupeln zuzuordnen sind. Deshalb führen wir einen Identifizierer ein, über den einzufügende Werte Tupeln zugeordnet werden. Diese ID wird in dem XPathAusdruck über die Selektionsbedingung angegeben: /db/table[INSERT=id]/@column = value 63 Kapitel 4 Backends Bei Transaktionsabschluss werden nun alle neu einzufügenden Werte gesammelt und pro virtueller Tupel-ID zu einem SQL-Insert-Statement zusammengesetzt. Löschoperationen Auch Löschoperationen betreffen immer komplette Tupel, da in relationalen Datenbanken keine einzelnen Felder eines Tupels gelöscht werden können. Deshalb wird zum Löschen eines Tupels ein XPath-Ausdruck der Form /db/table[cond1 ]...[condn ]/ benötigt, der in Bezug auf Abbildung 4.3 nicht an einem Blatt sondern an einem inneren Knoten endet. Dabei wird ein SQL-Statement der folgenden Form erzeugt: DELETE FROM WHERE table cond1 ... AND condn Natürlich können die Selektionsbedingungen auch leer sein. In diesem Fall werden alle Tupel der Tabelle table gelöscht. Sollte für eine Löschoperation doch ein XPath-Ausdruck angegeben sein, der auf ein Attribut zeigt, wird in das entsprechende Feld ein NULL-Wert geschrieben bzw. ein Fehler erzeugt, wenn das nicht erlaubt ist. 4.2.3 Konflikterkennung Um Konflikte unter den Datenzugriffen erkennen zu können, müssen wir für jeweils zwei XPath-Ausdrücke entscheiden können, ob diese auf dasselbe Datenobjekt zeigen, bzw. ob die Menge der jeweils spezifizierten Datenobjekte einen nicht-leeren Schnitt besitzt. Wir können dafür aber nicht einfach die Zeichenketten der jeweiligen XPath-Ausdrücke miteinander vergleichen, da ein Datenobjekt über unterschiedliche Selektionskriterien spezifiziert werden kann. Beispielsweise zeigen in unserer Beispieldatenbank die beiden Ausdrücke /mondial/city[@name=’Paris’]/@pop und /mondial/city[@country=’F’]/@pop auf dasselbe Tupel bzw. Datenobjekt, ohne dass das anhand der Zeichenkette syntaktisch zu erkennen wäre. Normalisierte Datenobjekte Betroffene Datenobjekte der XPath-Ausdrücke müssen also in eine normalisierte Form gebracht werden, um miteinander verglichen werden zu können. Wir nutzen dazu den Umstand, dass in unserem Backend jedes Objekt über ein Tripel, bestehend aus dem Namen der Tabelle, einem Identifizierer des Tupels sowie dem Namen der Spalte eindeutig bestimmt werden kann. Für das Tupel muss zunächst ein Identifizierer gefunden werden. Genau das ist die Idee eines Schlüssels. Da allerdings nicht jede Tabellendefinition einen Schlüssel enthält, nutzen wir dazu die internen Tupel-IDs. Bei diesen handelt es sich um interne Schlüssel, die das Datenbanksystem für jede Tabelle anlegt, unabhängig von eventuell für die Tabelle definierten logischen Schlüsseln. Obwohl es keine standardisierte Zugriffsmöglichkeit gibt, lassen sie sich in allen Datenbanksystemen auslesen. In PostgreSQL beispielsweise können sie als Objekt-IDs über die Pseudospalte oid ausgelesen werden. 64 4.2 Generischer Zugriff auf Relationale Datenbanken Datenzugriff Bei der Auswertung der XPath-Ausdrücke lesen wir diese oid-Spalte also zusätzlich aus, um die identifizierenden Tripel zu erzeugen. SELECT FROM WHERE column, oid table cond1 ... AND condn Angenommen obiges Paris-Tupel wäre unter der ID 16435 gespeichert, hätten beide XPath-Ausdrücke das Tripel (city, 16435, pop) ergeben. Der Scheduler speichert dieses Tripel zusammen mit dem jeweiligen XPath-Ausdruck, dem gelesenen bzw. geschriebenen Wert, der Transaktions-ID sowie einer Zeitmarke für den Zugriff in den Metadaten. Da im Allgemeinen einer Anfrage mehrere solcher Tripel entsprechen können, können auch mehrere Einträge in den Metadaten entstehen. XPath-Ausdrücke, die wie obige Löschoperation ein ganzes Tupel betreffen, stehen natürlich zu Zugriffen auf einzelne Felder dieses Tupels potentiell in Konflikt. Damit wir nicht jedes einzelne Feld des betroffenen Tupels über ein separates Tripel identifizieren müssen, führen wir eine Wildcard ein, mit der alle Felder eines Tupels über ein Tripel adressiert werden, dessen Feld-Anteil einen Null-Wert enthält. Konfliktberechnung In welcher Form die Konfliktberechnung konkret erfolgt, hängt vom verwendeten Scheduler ab. Das Backend stellt deshalb unterschiedliche Funktionen bereit, beispielsweise für das Suchen von Tripeln im Readset oder Mengenvergleiche über Tripeln. Jedenfalls muss bei allen Vergleichen darauf geachtet werden, dass Null-Werte als Wildcards betrachtet werden. In obigem Beispiel würde das Tripel (city, 16435, NULL) für das komplette Paris-Tupel der Mondial-Datenbank stehen und würde zu den XPath-Ausdrücken, die das Attribut mit der Einwohnerzahl betreffen potentiell in Konflikt stehen. Übertragung der Metadaten in die Datenbank Wenn bei Transaktionsende die Effekte einer Transaktion in die Datenbank geschrieben werden, müssen zunächst alle Einträge der Schreiboperationen anhand der TransaktionsID aus den Metadaten ermittelt werden. Wenn für ein Objekt unterschiedliche Schreiboperationen hinterlegt sind, wird nur die neueste behalten. Diese werden dann gruppiert nach Tabellen und Tupeln und akkumuliert ausgeführt, wobei virtuelle Tupel-IDs zu Einfügeoperationen führen und Löschoperationen über Null-Werte erkannt werden. Ansonsten wird ein Update durchgeführt. Dabei wird die Transaktion abgebrochen, sobald eine dieser Schreiboperationen einen Fehler liefert. 4.2.4 Erweiterte Sicht und Verbundanfragen Bisher waren die XPath-Ausdrücke auf Tupel-Selektion und Attribut-Projektion beschränkt und alle Ausdrücke konnten sowohl in Lese- als auch in Schreibzugriffe übersetzt werden. 65 Kapitel 4 Backends Die bisherigen Ausdrücke waren auf die Formularverarbeitung zugeschnitten, wo Formularfelder üblicherweise den Inhalt eines Datenbankfeldes widerspiegeln und die eindeutige Abbildung zwischen Formular- und Datenbankfeld die Updatebarkeit gewährleistet. Wir wollen in diesem Abschnitt zeigen, wie unsere Anfragesprache um Verbundanfragen erweitert werden kann. Wir wollen die grundsätzliche Idee zunächst anhand von Joins über referentielle Integritätsbedingungen zeigen. Dazu enthalten referenzierte Tupel wie in [KL02] direkt Kindelemente für jedes referenzierende Tupel. Wir werden diese Idee anschließend noch auf allgemeine Joins erweitern. Aggregierungen, Sortierung und weitere Sprach-Konstrukte von SQL wollen wir nicht ausführen, da sie auf sehr ähnliche Weise in unserer Anfragesprache unterstützt werden können. Joins über referentielle Integritätsbedingungen Referentielle Integritätsbedingungen fügen sich in natürlicher Weise in Hierarchien wie die XML-Sicht unser Datenbank ein. Sie definieren nämlich Inklusionsabhängigkeiten, bei der die Kindtabelle in den referenzierenden Attributen nur Werte enthalten darf, die in den entsprechenden Spalten der Elterntabelle enthalten sind. Unsere Beispieldatenbank enthält eine referentielle Integritätsbedingung. Die countryTabelle ist dabei die Elterntabelle, deren id-Spalte von der Kindtabelle city referenziert wird. create table country ( ... varchar id ... ); create table city ( ... varchar country references country.id ... ); Dabei gilt π[country]city ⊆ π[id]country. Da einem Tupel der Kindtabelle für jeden Fremdschlüssel ein Tupel dessen jeweiliger Elternrelation zugeordnet ist, können wir die referenzierenden Tupel direkt als Kinder ihrer entsprechenden Referenzen anhängen, wie es in Abbildung 4.4 für den Fall des einen Fremdschlüssels der Beispieldatenbank gezeigt ist. Wir ändern dazu in der DTD für jede definierte referentielle Integrität die Elementdefinition der Elterntabelle in <!ELEMENT elter ( kind *)> um. Da die Definition des Wurzelelements unverändert bleibt, entsteht Redundanz, da Kindtabellen doppelt aufgeführt werden. <!DOCTYPE mondial [ <!ELEMENT mondial (city∗, country∗)> <!ELEMENT city (EMPTY)> <!ELEMENT country (city∗)> ]> Es ist dabei zu beachten, dass im Fall von zyklischen Referenzen die DTD ein unendlich großes XML-Dokument erlaubt. Auch kann über die DTD nicht ausgedrückt werden, dass jedes Eltern-Tupel natürlich nur diejenigen Tupel der Kindtabelle als Kinder enthält, die 66 4.2 Generischer Zugriff auf Relationale Datenbanken <mondial> <country id="D" name="Deutschland" pop="3.405.342" area="357.092"> <city id="FR" name="Freiburg" country="D" pop="217.547" /> <city id="B" name="Berlin" country="D" pop="3.405.342" /> </country> <country id="F" name="Frankreich" pop="2.138.551" area="672.352"> <city id="P" name="Paris" country="F" pop="2.138.551" /> </country> <city id="FR" name="Freiburg" country="D" pop="217.547" /> <city id="B" name="Berlin" country="D" pop="3.405.342" /> <city id="P" name="Paris" country="F" pop="2.138.551" /> </mondial> Abbildung 4.4: Die um referentielle Joins erweiterte XML-Sicht der Beispieldatenbank. darauf verweisen. So enthält in Abbildung 4.4 beispielsweise das Deutschland-Tupel nur die beiden deutschen Städte. Die Tupel der referenzierenden Tabelle city sind doppelt aufgeführt. Einmal als direkte Kinder des Wurzelknotens, wie es in der Basissicht für jede Tabelle vorgesehen ist und noch einmal redundant als Referenzen. So entspricht der XPath-Ausdruck /mondial/country/city/ ausgewertet auf dem Dokument in Abbildung 4.4 dem Join country ./country.id=city.country city. Die Elementauswahl kann über Selektionskriterien natürlich weiter eingeschränkt werden. Konflikte lassen sich bei der Ermittlung des entsprechenden Wertes über die Tupel-ID der Kindtabelle ermitteln. Für einen XPath-Ausdruck /db/elterntabelle/kindtabelle/@spalte ergibt sich eine SQL-Anfrage der Form: SELECT FROM WHERE k.spalte, k.oid elterntabelle e, kindtabelle k, e.referenzierteSpalte = k.referenzierendeSpalte Allgemeine Verbundanfragen und Kreuzprodukte Um allgemeine Joins bzw. Kreuzprodukte zu ermöglichen, erweitern wir die XML-Sicht nochmals. Dazu erhält jedes Tupelelement ein <cross>-Element als Kind, das wiederum alle Element-Tupel der anderen Relationen enthält. Diese Element-Tupel besitzen nicht nur Attribute für die Spalten der eigenen Tabelle, sondern enthalten zusätzlich alle Attribute der Großelternelemente. Damit keine Namenskonflikte entstehen können, enthalten die Namen dieser Attribute zusätzlich den Tabellennamen. Abbildung 4.5 zeigt diese erweiterte Sicht für unsere Mondial-Datenbank. Man sieht beispielsweise, dass das Deutschland-Tupel innerhalb eines <cross>-Elements alle Städte ent- 67 Kapitel 4 Backends <mondial> <country id="D" name="Deutschland" pop="3.405.342" area="357.092"> <cross> <city id="FR" name="Freiburg" ... country.id="D" country.name="Deutschland" ... /> <city id="B" name="Berlin" ... pop="3.405.342" country.pop="3.405.342" ... /> <city id="P" name="Paris" country="F" ... country.id="F" ... country.area="357.092" /> </cross> </country> <country id="F" name="Frankreich" pop="2.138.551" area="672.352"> <cross> <city id="FR" name="Freiburg" country="D" pop="217.547" /> <city id="B" name="Berlin" country="D" pop="3.405.342" /> <city id="P" name="Paris" country="F" pop="2.138.551" /> </cross> </country> <city id="FR" name="Freiburg" country="D" pop="217.547"> <cross> <country id="D" name="Deutschland" ... city.country="D" ... city .pop="217.547" ... /> <country id="F" name="Frankreich" ... city .country="D" ... city .pop="217.547" ... /> </cross> </city> <city id="B" name="Berlin" country="D" pop="3.405.342"> <cross> <country id="D" name="Deutschland" ... city.country="D" city.name="Berlin" ... /> <country id="F" name="Frankreich" ... city .country="D" city.name="Berlin" ... /> </cross> </city> <city id="P" name="Paris" country="F" pop="2.138.551"> <cross> <country id="D" name="Deutschland" ... city.country="F" city.name="Paris" ... /> <country id="F" name="Frankreich" ... city .country="F" city.name="Paris" ... /> </cross> </city> </mondial> Abbildung 4.5: Die um Kreuzprodukt-Elemente erweiterte XML-Sicht der Beispieldatenbank. hält und diese die Attribute des Landes wiederholen. So enthält das Element für Freiburg die Attribute country.id und country.name. Die weiteren Attribute sind aus Platzgründen ausgespart. Da solche allgemeinen Joins üblicherweise nicht dazu benutzt werden, um Werte für einzelne Formularelemente auszulesen, wollen wir die Beschränkung auf einzelne Tupel bzw. Attribute aufheben und erwarten allgemeine XML-Fragmente als Rückgabe. Solche XML-Fragmente dienen beispielsweise als Quelle für XSL-Templates, über die der Datenbankausschnitt in ein HTML-Fragment gewandelt werden kann. Da diese erweiterte Sicht und somit auch ein Teilbaum der Sicht sehr groß sein kann, wollen wir die Rückgabe-Semantik der XPath-Ausdrücke der Situation anpassen. Normalerweise spezifiziert ein XPath-Ausdruck einen oder mehrere Knoten eines XML-Dokuments. 68 4.2 Generischer Zugriff auf Relationale Datenbanken Dabei steht ein Knoten immer für den kompletten Teilbaum, für den er die Wurzel bildet. Wir wollen aber alle Knoten, die zu der erweiterten Sicht gehören aus diesem Teilbaum aussparen und lediglich direkt adressierte Wurzelknoten und Elemente des nicht redundanten Kerns der Sicht in die Rückgabe einschließen. Beispiel: Ein Join unserer Beispieltabellen über die Spalten city.country und country.id kann über den Ausdruck /mondial/city/CROSS/country[@city.country=@id]/ realisiert werden und liefert folgendes Ergebnis zurück: <result type="XML"> <country id="D" name="Deutschland" pop="3.405.342" area="357.092" city . id="B" city .name="Berlin" city.country="D" city.pop="3.405.342" /> <country id="D" name="Deutschland" pop="3.405.342" area="357.092" city . id="B" city .name="Berlin" city.country="D" city.pop="3.405.342" /> <country id="F" name="Frankreich" pop="2.138.551" area="672.352" city . id="P" city .name="Paris" city.country="F" city.pop="2.138.551" /> </result> Bei dem Wurzelelement des Ergebnisses handelt es sich um das <result>-Tag des Rückgabeformats aus Abschnitt 3.4.2. Aus dem Attribut type kann der Typ der Rückgabe ausgelesen werden. Für die Verarbeitung in einem Formularelement muss allerdings darauf geachtet werden, dass die Rückgabe einen atomaren Typ enthält und nicht wie hier ’XML’. Fazit Bei unserer Anfragesprache für das generische relationale Backend handelt es sich um eine einfache select-project-join-Sprache, bei der spezielle XPath-Ausdrücke auf einer XML-Sicht der relationalen Datenbank automatisch in SQL-Statements übersetzt werden können. Das XML-Dokument ist virtuell und dient im Wesentlichen als Vorgabe für die Struktur der XPath-Ausdrücke. Aufgrund dieser fest vorgegebenen Struktur können XPath-Ausdrücke relativ einfach geparst und direkt in SQL übersetzt werden, ohne die XML-Sicht zu materialisieren. Es sollte hier im Wesentlichen die Idee vermittelt werden, wie eine solche Anfragesprache aussehen kann. Raum für Erweiterungen ist in Form von Aggregierung, Sortierung oder Mengenoperationen gegeben. Wichtig war uns neben der Unterstützung von Verbundanfragen die Anpassung an die Bedürfnisse der Formularverarbeitung. Hier ist vor allem wichtig, dass alle Ausdrücke sowohl in Lese- als auch in Schreiboperationen gewandelt werden können. In der Praxis ist es aber oft sinnvoll, eine anwendungsspezifische Lösung zu entwickeln, da diese insbesondere bei der Konflikterkennung effektiver ist und auch die Struktur der Datenbank verborgen bleiben kann. 69 Kapitel 4 Backends 4.3 Anwendungsspezifischer Zugriff auf relationale Datenbanken Der anwendungsspezifische Zugriff auf eine relationale Datenbank kann natürlich nur anhand eines Beispiels demonstriert werden. Als Anwendungsszenario wollen wir dabei ein PlatzreservierungssysFtem für Kinovorstellungen einsetzen und in diesem Abschnitt zunächst das Backend einer solchen Anwendung vorstellen. In Abschnitt 6.2.2 werden wir geeignete Formulare für ein Anwendungsfrontend vorstellen. 4.3.1 Tabellen der Platzreservierungs-Datenbank Neben den üblichen Tabellen für die TransForm-Metadaten, in denen Sessions, Transaktionszustand und Datenzugriffe gespeichert werden, greift das Backend auf folgende Tabellen zurück, in denen die aus Anwendungssicht interessanten Daten gespeichert sind: Platz: Diese Tabelle enthält die Informationen zu den verfügbaren Sitzen aller Kinos. Jeder Platz ist durch ein Tupel repräsentiert, das folgende Spalten besitzt: id enthält einen Schlüssel für die Tabelle, saal den Namen des Kinosaals, reihe die Sitzreihe und sitz die Sitznummer. Denkbar sind weitere Informationen wie Logenplätze oder Sichtverhältnisse, die wir hier aber aussparen wollen. Besucher: Diese Tabelle enthält alle Benutzerdaten. Neben der im Authentifizierungsmodell geforderten Benutzer-Identifizierung uid samt Passwort und pwd gibt es noch Spalten für Name, Adresse oder ähnliche Informationen. Vorstellung: Diese Tabelle enthält relevante Informationen zu allen Vorstellungen. Die Spalte id enthält einen Schlüssel. Weitere Spalten sind für den Filmtitel (film), Uhrzeit (uhrzeit), Kinosaal (saal) vorgesehen. Reserviert: Diese Tabelle enthält alle Reservierungen. Dazu werden die Entitäten Platz, Besucher und Vorstellung miteinander verknüpft. Jede Reservierung ist durch ein Tupel mit den Schlüsseln der beteiligten Tabellen repräsentiert: Vorstellungs-ID, Platz-ID sowie Benutzer-ID. Anforderungen Die wichtigste Funktion unseres Backends ist das Tätigen einer Reservierung im Namen des angemeldeten Benutzers. Parameter einer Reservierung sind dabei der Platz sowie die Vorstellung. Natürlich muss auch die Möglichkeit gegeben sein, für einen Platz einer Vorstellung den Reservierungsstatus abzurufen. Weiterhin soll eine Liste aller Vorstellungen ausgegeben werden können und es soll die Möglichkeit bestehen, für jeden Kinosaal eine Übersicht über alle verfügbaren Plätze in 70 4.3 Anwendungsspezifischer Zugriff auf relationale Datenbanken <kino> <vorstellung id=’234’ film=’Night on Earth’ uhrzeit=’20.30’ saal=’kino1’> <platz id=’12’ reihe=’2’ sitz =’1’> <reserviert>42543</reserviert> </platz> <platz id=’13’ reihe=’2’ sitz =’2’> <reserviert>234</reserviert> </platz> <platz id=’14’ reihe=’2’ sitz =’3’ /> <platz id=’15’ reihe=’2’ sitz =’4’ /> <platz id=’16’ reihe=’2’ sitz =’5’ /> </vorstellung> <saal id="kino1"> ... HTML−Tabelle ... </saal> </kino> Abbildung 4.6: Ein Ausschnitt aus der XML-Sicht des Reservierungssystems für Kinovorstellungen. Form einer HTML-Tabelle auszugeben. Diese Tabelle soll dabei den aktuellen Reservierungsstatus einer bestimmten Vorstellung anzeigen sowie Reservierungen für diese Vorstellung ermöglichen. 4.3.2 XML-Sicht des Backends Ein Ausschnitt der XML-Sicht unseres Backends ist in Abbildung 4.6 für fünf Plätze einer Vorstellung dargestellt. Im Gegensatz zu der generischen Lösung aus dem letzten Abschnitt sind hier nicht mehr alle Tabellen als direkte Kinder der Wurzel erreichbar. Auf Wurzelebene sind zunächst nur die Vorstellungen aufgelistet. <!DOCTYPE kino [ <!ELEMENT kino (vorstellung∗)> Die vorstellung-Elemente repräsentieren direkt die Tupel der Vorstellung-Tabelle und enthalten in den Attributen alle Informationen der Tabelle über die Vorstellung. <!ELEMENT vorstellung (platz+)> <!ATTLIST vorstellung id CDATA #REQUIRED film CDATA #REQUIRED uhrzeit CDATA #REQUIRED saal CDATA #REQUIRED...> Als Kinder sind Elemente für alle Plätze vorgesehen. Diese platz-Elemente übernehmen als Attribute die Spalten id, reihe und sitz aus der Tabelle Platz. Die Spalte saal findet keine direkte Repräsentierung, da der Kinosaal über das entsprechende Attribut des Elternelements vorstellung ermittelt werden kann. 71 Kapitel 4 Backends <!ELEMENT platz (reserviert?)> <!ATTLIST platz id CDATA #REQUIRED reihe CDATA #REQUIRED sitz CDATA #REQUIRED > <!ELEMENT reserviert (#PCDATA)> Wenn für den Platz eine Reservierung vorliegt, enthält es als Kind ein reserviert-Element mit der uid des entsprechenden Benutzers als Elementinhalt. Freie Plätze haben kein solches Element. Wie in Abbildung 4.6 zu sehen ist, kann das Wurzelelement neben Elementen für Vorstellungen auch welche für Säle besitzen. Diese <saal>-Elemente enthalten einen Übersichtsplan des Kinosaals als HTML-Tabelle. Das einzige Attribut ist eine id, die dem saal-Attribut der Vorstellung entspricht. <!ELEMENT kino (vorstellung∗, saal∗)> <!ELEMENT saal ( table )> <!ATTLIST saal id ... > ]> Diese Übersichtspläne sind statisch in Dateien abgelegt und müssen von Hand für jeden Kino Saal erstellt werden. Jeder Platz wird dabei von einem speziellen Formularelement repräsentiert, das wir in Abschnitt 6.2.2 zusammen mit dem Anwendungs-Frontend vorstellen. Jedes dieser Formularelemente ist mit einem XPath-Ausdruck versehen, über den der Reservierungszustand ausgelesen werden kann. Ein solcher Übersichtsplan ist exemplarisch in Abbildung 4.7 dargestellt. Das Präfix vorstAnker aller XPath-Ausdrücke stellt dabei einen Anker dar, der im Frontend dynamisch durch eine Vorstellung ersetzt wird. Die Ausdrücke ergeben so Anfragen, über die der Reservierungszustand jeweils eines Platzes ausgelesen werden kann. 4.3.3 XPath-Anfragen Es wäre sehr ineffizient, wenn wir alle möglichen legalen XPath-Ausdrücke unterstützen würden, die sich auf dieser XML-Sicht bilden lassen. Insbesondere die Erkennung zueinander in Konflikt stehender Zugriffe wäre mit erheblichem Aufwand verbunden. Deshalb wird in diesem Backend nur eine kleine Untermenge der möglichen Ausdrücke tatsächlich akzeptiert. Diese akzeptierten Anfragen ergeben sich direkt aus den Anforderungen, die wir zu Beginn dieses Abschnitts an das Backend gestellt hatten. Da diese Anfragen eine feste Struktur haben, können die notwendigen Parameter für die Erzeugung der SQL-Anfragen über reguläre Ausdrücke extrahiert werden. /kino/saal[id=saalid]/ 72 4.3 Anwendungsspezifischer Zugriff auf relationale Datenbanken <kino> ... <saal id=’kino1’> <table> <tr> <td><tf:check xpath="vorstAnker/platz[id=’12’]/reserviert" /></td> <td><tf:check xpath="vorstAnker/platz[id=’13’]/reserviert" /></td> <td><tf:check xpath="vorstAnker/platz[id=’14’]/reserviert" /></td> <td><tf:check xpath="vorstAnker/platz[id=’15’]/reserviert" /></td> <td><tf:check xpath="vorstAnker/platz[id=’16’]/reserviert" /></td> </tr> </table> </saal> </kino> Abbildung 4.7: Ein Übersichtsplan eines Kinosaals als HTML-Tabelle. Über einen XPath-Ausdruck dieser Form kann die HTML-Darstellung des Saals mit dem ID-Attribut saalid angefordert werden. Dabei sind nur Lesezugriffe zugelassen. /kino/vorstellung[id=vorstellungsID]/platz[id=platzID]/reserviert Über einen solchen XPath-Ausdruck kann nun der Reservierungsstatus des Platzes platzID für die Vorstellung vorstellungsID entweder ausgelesen oder geschrieben werden. Bei lesendem Zugriff liefert er false, sollte kein Tupel in der Reservierungstabelle für die Vorstellung und den Platz enthalten sein. Falls doch, liefert der Ausdruck true zurück. Obwohl bekannt ist, welcher Besucher den Platz reserviert hat, wird nicht dessen Name bzw. Identifizierer zurückgeliefert sondern aus Gründen des Datenschutz eine anonymisierte Antwort generiert. Wenn der Ausdruck mit dem Wert true geschrieben wird, erzeugt das Backend einen entsprechenden Eintrag in den Metadaten. Dazu werden die Vorstellungs-ID und die Platz-ID aus dem Ausdruck extrahiert und die Benutzer-ID den Anmeldedaten entnommen. Konflikte Für die Konflikterkennung verwenden wir auch eine anwendungsspezifische Lösung. Da Konflikte nur bei Reservierungen auftreten können, werden Lesezugriffe, über die eine Platzübersicht angefordert wird, dabei gar nicht berücksichtigt und erzeugen keine Einträge in den Metadaten. Wie erwähnt, erzeugt eine Reservierung einen Schreibzugriff auf ein <reserviert>-Element aus Abbildung 4.6, wodurch ein Tripel (Vorstellungs-ID, Platz-ID, Benutzer-ID) in das 73 Kapitel 4 Backends Writeset eingefügt wird. Dabei stehen zwei Reservierungen zueinander in Konflikt, wenn derselbe Platz und dieselbe Vorstellung betroffen ist und die Reservierung von unterschiedlichen Benutzern angefordert wird. Die konkrete Handhabung von Konflikten hängt dabei von dem verwendetem Scheduling-Protokoll ab. 4.4 Dateisysteme als Backend Zum Abschluss dieses Kapitels soll noch kurz der generische Zugriff auf ein Filesystembasiertes Backend skizziert werden. Wir erläutern dazu den Einsatz eines solchen Backends als Multimediadatenbank und die dabei entstehenden Schwierigkeiten in Bezug auf ACIDTransaktionen. Wir modellieren ein Filesystem, indem wir sowohl Dateien als auch Verzeichnisse in Elemente abbilden. Datei- und Verzeichnisnamen werden jeweils direkt übernommen. Dateisystempfade entsprechen also direkt XPath-Ausdrücken: /pfad/zu/datei. Für die Unterscheidung von Dateien und Verzeichnissen führen wir neben text() und node() zwei weitere Knotentests ein, die es bei Standard-XPath nicht gibt: 1. /child::file()/ schränkt die Auswahl auf Dateien ein. 2. /child::dir()/ schränkt die Auswahl auf Verzeichnisse ein. Metadaten von Dateien und Verzeichnissen wie Rechte, Mime-type, Änderungszeitpunkt, Name, etc. sind als Attribute der Elemente definiert. In Abhängigkeit des Mime-Typs der Datei können weitere Metadaten definiert sein. Beispielsweise werden bei MP3-Dateien alle MP3-Tags wie Künstler oder Titel als Attribute repräsentiert. In Kombination mit der Descendant-Achse lassen sich so Dateien unabhängig von der Struktur des Dateisystems ansprechen. Der Ausdruck /descendant:: file ()[mime−type=’text/mp3’][genre=’Rock’] liefert beispielsweise alle MP3-Dateien mit dem Genre „Rock“, während folgender Ausdruck alle Verzeichnisse ermittelt, die MP3-Dateien enthalten: //dir()[ child :: file ()[mime−type=’text/mp3/]]/ Relationale Datenbank als Cache Damit für die Auswertung solcher Anfragen nicht immer das Dateisystem durchsucht werden muss, bietet sich der Einsatz einer relationalen Datenbank als Cache an. Dabei würde jede Datei und jedes Verzeichnis durch ein Tupel repräsentiert. Meta-Informationen wie beispielsweise MP3-Tag-Inhalte können in jeweils einer Spalte gespeichert werden. ACID-Eigenschaften Für die Gewährleistung der ACID-Eigenschaften ergeben sich bei Dateisystem-basierten Backends allerdings Schwierigkeiten. Man kann sich jedoch mit Hilfe eines Datenbanksys- 74 4.4 Dateisysteme als Backend tems behelfen, das die Transaktions-Metadaten speichert und als Cache in obigem Sinn fungiert. Wir gehen davon aus, dass eine Cache-Datenbank eine korrekte Repräsentation des Dateisystems besitzt. Jedes Tupel erhält ein zusätzliches Attribut, über das die Datei für ein Update reserviert werden kann, indem die Transaktions-ID der entsprechenden Transaktion eingetragen wird. Ein Schreibzugriff auf eine Datei bzw. ihre Metadaten wird nur angenommen, wenn dieses Attribut keine andere Transaktions-ID enthält und die eigene somit eingetragen werden kann. Die eigentlichen Änderungen werden aber nur im Writeset vorgenommen. Das alles kann durch den Transaktionsmechanismus der Datenbank atomar erfolgen. Bei Transaktionsabschluss müssen nun die im Writeset vorgemerkten Änderungen sowohl in die Datenbank als auch in das Dateisystem geschrieben werden. Zuerst wird das Dateisystem aktualisiert. Die gesetzten Update-Flags für alle Dateien stellen sicher, dass keine anderen Transaktionen auf die gleichen Dateien zugreifen. Wenn alles gut gegangen ist, müssen noch innerhalb einer Transaktion alle Änderungen in die Datenbank geschrieben und die Update-Flags gelöscht werden. Sogar wenn keine Fehlersituationen auftreten, sind die ACID-Eigenschaften nicht garantiert. Angenommen eine Transaktion T1 hat während des Commit gerade eine MP3-Datei im Filesystem umbenannt, die Datenbank aber noch nicht aktualisiert. Eine Transaktion T2 , die den Dateiinhalt dieser Datei an einen Browser streamen will, kann nicht auf sie zugreifen, da der Pfad, den sie aus der Datenbank gelesen hat, nicht mehr aktuell ist. T2 sieht also Effekte der noch nicht abgeschlossenen Transaktion T1 , was nicht möglich wäre, wenn das Commit von T1 atomar erfolgt wäre. Um solche Situationen zu verhindern, muss auch der Lesezugriffe auf Dateien mit gesetztem Update-Flag und das Umbenennen von Verzeichnissen verboten werden. Es kann zwar immer noch zu inkonsistenten Zuständen kommen, allerdings können diese anhand der Flags erkannt und behoben werden. 75 Kapitel 5 Scheduler Scheduler sorgen für eine korrekte nebenläufige Ausführung mehrerer Transaktionen. Sie erzeugen dabei für eine Reihe von Transaktionsschritten eine Ablaufreihenfolge, die den Regeln eines bestimmten Protokolls genügt. Wir wollen in diesem Kapitel geeignete Scheduling-Algorithmen für TransForm entwickeln. Da unser Transaktionsmodell eng an das klassische Modell [Gra81] angelehnt ist, können wir die dafür entwickelten Verfahren einsetzen, deren Korrektheit allgemein akzeptiert ist und deren grundlegende Eigenschaften bekannt sind. Wir richten uns dabei nach den in Kapitel 3 eingeführten Modellen und Schnittstellen und halten uns an die abgesteckten Rahmenbedingungen, die ein Scheduling-Protokoll für die Gewährleistung der Atomizität und Dauerhaftigkeit einhalten muss. Die Konsistenzerhaltung kann allerdings nicht allein durch das Scheduling-Protokoll gewährleistet werden, sondern hängt auch von der jeweiligen Datenbank ab und muss deshalb vom Backend gewährleistet werden. So können wir also bei der Diskussion der ACID-Eigenschaften der Scheduler das Hauptaugenmerk auf die Isolation legen. Bevor wir in die Diskussion der Protokolle einsteigen, wollen wir zunächst relevante Begriffe und Konzepte der Serialisierbarkeitstheorie rekapitulieren. 5.1 Vorbetrachtungen Unser Transaktionsmodell ist an das klassische seitenbasierte Modell [Gra78, Gra81] angelehnt, bei dem eine Transaktion abstrahiert von den Einzelheiten eines Transaktionsprogramms als geordnete Abfolge von Schritten modelliert und jeweils von einer Terminierungsoperation abgeschlossen wird. Nebenläufige Ausführungen mehrerer Transaktionen werden von einer als Schedule bzw. Historie bezeichneten Struktur modelliert. Eine Historie ist dabei ein vollständiger Schedule, der nur aus abgeschlossenen Transaktionen besteht, während ein Schedule als Präfix einer Historie auch Transaktionen ohne Terminierungsoperationen enthält. Schedules behalten dabei die Ordnung der Transaktionsschritte innerhalb einer Transaktion bei und ordnen zueinander in Konflikt stehende Operationen unterschiedlicher Transaktionen. 76 5.1 Vorbetrachtungen Korrektheitskriterien Schedules, bei denen die Schritte unterschiedlicher Transaktionen nicht verzahnt ablaufen, werden als seriell bezeichnet. Im Sinne der Nebenläufigkeit sind solche Schedules zwar immer korrekt, da sie allerdings auch verhältnismäßig ineffizient sind, wird eine verzahnte Ausführung angestrebt, bei der zwischen korrekten und nicht korrekten, also abzulehnenden Schedules unterschieden werden muss. Als Kriterium wird dazu die Äquivalenz zu seriellen Schedules herangezogen. Ein Schedule gilt dabei als serialisierbar, also korrekt im Sinne der Nebenläufigkeit, wenn er äquivalent zu einem seriellen Schedule ist. Es gibt dabei unterschiedliche Äquivalenzklassen wie Final-State-Serialisierbarkeit [BSW79] oder View-Serialisierbarkeit [Yan84]. In der Praxis relevant ist aber lediglich die Konfliktserialisierbarkeit [EGLT76], die zwar nicht alle serialisierbaren Schedules umfasst, dafür aber effizient überprüfbar ist und interessante theoretische Eigenschaften besitzt. Konfliktserialisierbarkeit beruht auf der Idee von Konflikten. Dabei stehen zwei Datenoperationen zueinander in Konflikt bzw. in einer Konfliktrelation, wenn sie auf dasselbe Datenelement zugreifen und es sich bei mindestens einer Operation um einen Schreibzugriff handelt. Ein Schedule gilt nun als (konflikt-)serialisierbar, wenn er zu einem seriellen Schedule konfliktäquivalent ist, also wenn beide Schedules die gleichen Operationen enthalten und wenn alle Paare von zueinander in Konflikt stehenden Operationen der nicht abgebrochenen Transaktionen gleich geordnet sind. 5.1.1 Klassen von Schedules Die Klasse CSR der konfliktserialisierbaren Schedules erlaubt die Definition von Subklassen, die für die Praxis relevante Eigenschaften erfassen [WV01]. Die Landschaft dieser Scheduling-Klassen, die wir in diesem Abschnitt einführen wollen, ist in Abbildung 5.1 dargestellt. Eine erste Einschränkung führt uns zu der Klasse OCSR der ordnungserhaltend konfliktserialisierbaren Schedules. Sie fordert von Schedules, dass die Reihenfolge sich zeitlich nicht überlappender Transaktionen der äquivalenten seriellen Ordnung entspricht. Sie verhindern Schedules, in denen die aus Anwendungssicht „falsche“ äquivalente serielle Reihenfolge eingehalten ist. Eine weitere Einschränkung ist die Klasse COCSR der bezüglich der Freigabe geordneten Schedules. Sie beruht auf der Eigenschaft, dass die Einhaltung der durch die Konflikte festgelegten Reihenfolge bei den Freigabeoperationen bereits für die Serialisierbarkeit ausreicht und ist insbesondere für verteilte Transaktionen wichtig. Da diese Klassen jeweils als Einschränkung definiert sind, gelten die Mengeninklusionen COCSR ⊂ OCSR ⊂ CSR. 77 Kapitel 5 Scheduler alle Historien serialisierbare Historien RC ACA ST CSR OCSR COCSR RG seriell Abbildung 5.1: Der Zusammenhang zwischen den betrachteten Schedulingklassen. Recovery-Klassen Wenn man neben der Serialisierbarkeit noch die Fehlersicherheit betrachtet, ergeben sich weitere Klassen, die mit den bisherigen in Bezug auf Mengeninklusion zum Großteil nicht vergleichbar sind. Die Handhabung von Transaktionsabbrüchen stellt zusätzliche Anforderungen an Schedules. Abgebrochene Transaktionen dürfen dabei keine Auswirkungen besitzen, es muss so aussehen, als ob sie nie stattgefunden hätten. Problematisch sind die sogenannten dirty reads, die entstehen, wenn Effekte nicht abgeschlossener Transaktionen gelesen werden. Diese werden von der Klasse CSR nicht ausgeschlossen. Man stelle sich folgendes Szenario vor: Transaktion T1 liest einen Wert von Transaktion T2 , überschreibt einen anderen Wert und committed schließlich. Wenn nun T2 abbricht, müsste Transaktion T1 aufgrund des dirty read folgerichtig auch abgebrochen werden. Das ist aber nicht möglich, wenn gleichzeitig die Dauerhaftigkeit eingehalten werden soll. Zu verhindern wäre diese Situation nur gewesen, indem man T1 den frühzeitigen Commit verweigert und nach dem Abbruch von T2 auch abgebrochen hätte. Schedules, die genau solche Situationen ausschließen werden als recoverable bezeichnet und bilden die Klasse RC. Hier ist ein Commit erst erlaubt, wenn alle Transaktionen abgeschlossen sind, von denen Werte gelesen wurden. Wie der Abbruch von T1 zeigt, verhindert Recoverability keine Abbrüche weiterer, noch nicht abgeschlossener Transaktionen. Sie schließt lediglich mit der Dauerhaftigkeit nicht zu vereinende Abbrüche bereits abgeschlossener Transaktionen aus und kann deshalb neben CSR als so etwas wie eine Mindestanforderung für Scheduler angesehen werden. 78 5.1 Vorbetrachtungen Abbruch abgeschloss. Transakt. dirty read (WR-Konflikt) dirty write (WW-Konflikt) RW-Konflikt RC √ - ACA √ √ - ST √ √ √ - RG √ √ √ √ Abbildung 5.2: Verhinderte Phänomene der einzelnen Recovery-Klassen. Will man solche kaskadierenden Abbrüche ausschließen, müssen dirty reads verboten werden. Die Klasse ACA (avoiding cascading aborts) fordert, dass Transaktionen nur Effekte abgeschlossener Transaktionen sehen. Es werden also Write/Read-Konflikte zwischen aktiven Transaktionen vermieden. Die Klasse der strikten Schedules (ST) verbietet zusätzlich Write/Write-Konflikte zwischen nicht abgeschlossenen Transaktionen; es dürfen also keine Daten gelesen oder geschrieben werden, die von aktiven Transaktionen geschrieben wurden. So können Schreiboperation immer rückgängig gemacht werden, indem der alte Wert wiederhergestellt wird, was die Handhabung von Transaktionsabbrüchen wesentlich vereinfacht. Wenn man zusätzlich noch Read/Write-Konflikte ausschließt, führt das zu der Klasse RG der rigorosen Schedules, bei denen keine Daten überschrieben werden, bevor alle Transaktionen beendet sind, die sie gelesen haben. Diese Klasse ist vor allem deshalb interessant, weil sie als einzige in Bezug auf Mengeninklusion mit Serialisierbarkeitsklassen vergleichbar ist: RG ⊂ COCSR. Abbildung 5.2 fasst abschließend die verhinderten Phänomene dieser Recovery-Klassen noch einmal tabellarisch zusammen. 5.1.2 Scheduling-Verfahren Scheduler setzen ein bestimmtes Scheduling-Protokoll oder Scheduling-Verfahren in die Realität um. Wenn ein Scheduler eine Operation zur Ausführung erhält, kann er diese prinzipiell entweder direkt ausführen, für eine spätere Ausführung zurückstellen oder endgültig ablehnen und damit die Transaktion abbrechen. Klassifikation Je nachdem, welche dieser Möglichkeiten ein Scheduling-Verfahren bevorzugt, spricht man von aggressiven bzw. konservativen Strategien. Aggressive Scheduler führen in der Regel alle Operationen sofort und ohne Verzögerung aus, wodurch sich das Risiko von Transaktionsabbrüchen erhöht. Konservative Scheduler versuchen Transaktionsabbrüche zu vermeiden, indem in Konflikt stehende Operationen in der Hoffnung verzögert werden, dass sie später ausgeführt werden können. Ein extremes Beispiel wäre eine rein serielle Ausführung, bei der alle bis auf eine Transaktionen geblockt sind. Jeder dieser beiden Ansätze funktioniert für bestimmte Einsatzbereichen besonders gut. Aggressive Verfahren passen zu Szenarien, bei denen Konflikte eher selten vorkommen. 79 Kapitel 5 Scheduler Sie werden auch als optimistisch bezeichnet, da der Zugriff auf die Daten normalerweise zunächst ungeprüft akzeptiert wird und ein Serialisierbarkeitstest erst vor dem Transaktionsabschluss stattfindet. Im Gegensatz dazu profitieren konservative Scheduler von Anwendungsszenarien, in denen sich Transaktionen häufig durch Zugriff auf die gleichen Daten ins Gehege kommen. Sie sind in dem Sinne pessimistisch, dass sie nur Schritte ausführen, wenn sie sicher sind, dass die Serialisierbarkeit nicht gefährdet ist, die folgerichtig für jeden Schritt getestet werden muss. Diese generelle Beurteilung der beiden Strategien ist allerdings mit Vorsicht zu genießen, insbesondere in unserem speziellen Umfeld, in dem sich beispielsweise die Umsetzung von Sperren schwierig gestaltet. Ein anderes Klassifikationsmerkmal ist aus Sicht der Recovery entscheidend und bestimmt den Zeitpunkt der Auswirkung von Transaktionseffekten auf die Datenbank: Bei einer immediate-update-Strategie wirken sich alle Operationen direkt auf die Datenbank aus, während bei einer deferred-update-Strategie Effekte von Schreiboperationen zunächst in Intentionslisten vermerkt und erst bei Transaktionsabschluss in die Datenbank übertragen werden. Letzteres hatten wir in Kapitel 3 als Anforderung an einen geeigneten Scheduler für TransForm gestellt. Obwohl diese Recovery-Strategien orthogonal zu obiger Unterscheidung von optimistischen und pessimistischen Verfahren sind, passen optimistische Verfahren besser zu einem Deferred-Update, während pessimistische normalerweise als Immediate-Update realisiert sind. Scheduling-Verfahren für TransForm Die wegen der Recovery-Strategie naheliegenden optimistischen Verfahren sowie Sperrverfahren werden wir beide in den nächsten Abschnitten näher beleuchten. Andere klassische Verfahren wie das zeitmarkenbasierte oder das Testen des Serialisierungs-Graphen [Cas81] bleiben als TransForm-Verfahren unberücksichtigt. Letzteres Verfahren überprüft in jedem Transaktionsschritt die Zyklenfreiheit des Konflikt-Graphen, welche die Serialisierbarkeit garantiert. Es ist zwar theoretisch interessant, da es alle konfliktserialisierbaren Schedules erzeugen kann, wird allerdings wegen seiner im Vergleich zu anderen Verfahren hohen Kosten in der Praxis sehr selten eingesetzt. Zeitmarken werden in Webanwendungen oft für eine rudimentäre Nebenläufigkeitskontrolle benutzt, bei der vor einer Schreibaktion überprüft wird, ob der zu überschreibende Wert noch „aktuell“ ist. Das hat aber nur bedingt etwas mit dem klassischen TimestampOrdering-Verfahren [Tho79] zu tun. Zeitmarken [Lam78] sind Werte aus einem total geordneten Wertebereich, beispielsweise den natürlichen Zahlen. Jeder Transaktion Ti ist eine eindeutige Zeitmarke ZM(Ti ) zugeordnet, die gleichzeitig als Zeitmarke für alle Operationen dieser Transaktion Ti dient. Zueinander in Konflikt stehende Operationen werden von einem solchen Scheduler [Tho79] gemäß ihrer Zeitmarken geordnet, weshalb man auch von einem zeitmarkengeordneten 80 5.1 Vorbetrachtungen Protokoll spricht. Dabei muss der Scheduler dafür sorgen, dass zwei zueinander in Konflikt stehende Operationen pTi und qTj in der Reihenfolge der Ordnung ihrer Zeitmarken ZM(Ti ) und ZM(Tj ) ausgeführt werden. Der große Nachteil dieses Verfahrens ist die Festlegung der Zeitmarken bei Transaktionsbeginn, die einen flexiblen Umgang mit Konflikten ausschließt. Im Konfliktfall muss die Transaktion mit der älteren Zeitmarke bevorzugt werden. Wir werden in Abschnitt 5.2.1 ein Zeitmarken-basiertes optimistisches Verfahren vorstellen, das diese Nachteile nicht besitzt, da Zeitmarken hier erst bei Transaktionsende vergeben werden. 5.1.3 Ein Rahmen für TransForm-Scheduler Wir wollen zunächst einen Rahmen für die Umsetzung von Schedulern in TransForm vorstellen. Wir lassen dabei Nebenläufigkeitsaspekte noch außer Acht und führen deshalb keinen Serialisierbarkeitstest durch. Dieser Rahmen soll in erster Linie zeigen, wie die Anforderungen für die Recovery aus Kapitel 3 umgesetzt werden können. • Für die deferred-update-Strategie vermerken wir zunächst alle Schreiboperationen im Writeset. • Für die Umsetzung der Idempotenz vermerken wir zusätzlich die ermittelten Werte aller Leseoperationen im Readset. So können wir die Rückgabewerte eventuell bereits ausgeführter Operationen aus den Metadaten rekonstruieren. • Um die Atomizität und Dauerhaftigkeit der Schritte zu gewährleisten, schließen wir alle Zugriffe auf die Datenbank in Transaktionen ein. Neben dem Read- und Writeset, das jeweils die Transaktions-ID, eine Anfrage-ID, das Datenobjekt sowie den zugehörigen Wert enthält, benötigen wir noch die Tabelle TS, in der der Zustand aller Transaktionen gespeichert ist. Bei Lese- und Schreibzugriffen erfolgt der Idempotenzcheck über die Kombination aus der Anfrage-ID und dem Objekt, auf das zugegriffen wird. Sollte eine Anfrage keine Anfrage-Id enthalten, wird diese auf Null gesetzt. In diesem Fall wird lediglich überprüft, ob die Transaktion auf ein Objekt schon einmal zugegriffen hat. Wenn die Scheduler-Strategie garantiert, dass eine Transaktion immer den gleichen Wert eines Datenobjekts sieht, ist das für Lesezugriffe schon ausreichend. Für Schreiboperationen muss in diesem Fall noch überprüft werden, ob der Wert im Writeset aktualisiert werden muss, da eine Transaktion ein Objekt mehr als einmal schreiben kann. Der Client entscheidet also im Prinzip, ob Anfrage-IDs zum Einsatz kommen sollen, bzw. muss wissen, ob diese bei dem verwendeten Scheduling-Protokoll erforderlich sind. Bei beiden später diskutierten TransForm-Verfahren sind sie nicht nötig: Sperren verhindern ein Überschreiben durch andere Transaktionen und bei unserem optimistischen Scheduler 81 Kapitel 5 Scheduler Eingabe: action, tid , rid , obj, val Ausgabe: erzeugt durch print−Statements if (! rid) rid = 0; print <response /∗ Wdh. der Eingabe−Parameter ∗/ >; try { openDBConnection( /∗ Isolations−Level serialisierbar ∗/); beginTransaction(); if ( ! tid ) throw exception: keine tid if ( TS.status( tid ) == ’conflict ’ ) throw exception: Konflikt switch ( action ) { case ’ read’ : v = RS.getValue( tid,rid ,xpath ); if ( !v ) { // Idempotenz−Check v = DB.read(obj); RS.insert( tid , rid ,obj, val ); } print <result> v </result>; case ’ write ’ : v = WS.getValue( tid,rid,xpath ); if ( !v ) WS.insert( tid , rid ,obj, val ); // Idempotenz−Check else WS.update( tid,rid,obj, val ); case ’ begin’ : if ( /∗ Prot. nicht unterstuetzt ∗/ ) throw exception: falsches Protokoll t = generateTid(); TS.setStatus(t , ’ active ’ ); print <tid> t </tid>; case ’ abort’ : RS.delete(t); // wiederholte Ausfuehrung ist unproblematisch WS.delete(t); TS.setStatus(t , ’ abort’ ); case ’ commit’: status = TS.status(tid ); if (status <> ’active’) print( status ) // erzeuge Status−Tag else WS.materialize(tid); RS.delete(tid); WS.delete(tid); TS.setStatus( tid , ’ commit’); default: throw exception: unbekannte action; } commitTransaction(); closeDBConnection(); } catch exceptions { rollbackTransaction (); closeConnection(); } print </response>; Abbildung 5.3: Der Rahmen für TransForm-Scheduling-Algorithmen. 82 5.2 Optimistische Scheduling-Verfahren muss die Transaktion abgebrochen werden, wenn ein Wert von einer parallelen Transaktion bei deren Abschluss überschrieben wird. In Abbildung 5.3 müssen wir den Idempotenzcheck allerdings explizit darstellen, da hier ohne Serialisierbarkeitstest ein Überschreiben durch parallele Transaktionen möglich ist und somit wiederholte Lesezugriffe einer Transaktion durchaus unterschiedliche Werte erhalten können. Die Abbildung enthält eine algorithmische Darstellung unseres SchedulerRahmens. Die Eingabe besteht dabei aus den HTTP-Variablen, die dem Web-Service beim Aufruf übergeben werden. Die Rückgabe besteht aus der Ausgabe, die mittels der printStatements erzeugt werden. Um die Darstellung kompakt zu halten, sparen wir sowohl das Auslesen von Initialwerten für Formularfelder schon in der Begin-Operation als auch die Bündelung mehrerer Datenzugriffe in einer Lese- oder Schreiboperation aus, die im Transaktionsmodell vorgesehen sind. 5.2 Optimistische Scheduling-Verfahren Im Gegensatz zu pessimistischen Protokollen, die bei jedem Schritt die Serialisierbarkeit überprüfen, akzeptieren optimistische Scheduler [KR81] zunächst alle Lese- und Schreiboperationen ungeprüft und sichern die Serialisierbarkeit erst zu Transaktionsende. Dabei durchläuft die Transaktionsausführung drei Phasen: 1. Read Phase: Zunächst werden alle Lese- und Schreiboperationen ungeprüft ausgeführt. Allerdings finden alle Schreiboperationen in einem privaten Arbeitsbereich statt. 2. Validation: Wenn eine Transaktion zum Commit bereit ist, wird überprüft, ob ihre Ausführung korrekt im Sinne der Konfliktserialisierbarkeit war. Sollte das nicht der Fall sein, wird die Transaktion abgebrochen. 3. Write Phase: Im Falle einer erfolgreichen Validation wird der Inhalt des privaten Arbeitsbereichs in die Datenbank übertragen. In unserem Transaktionenmodell initiiert also begin die Read-Phase, in die dann alle nachfolgenden Lese- und Schreiboperationen fallen. Sowohl die Validation als auch die WritePhase werden von der Commit-Operation durchgeführt. Wir sprechen deshalb im Folgenden von der ValWrite-Phase. Die Commit-Operation ist also mit dem größten Aufwand verbunden, während Lese- und Schreiboperationen relativ leichtgewichtig sind. In [KR81] wird die Validation auf serielle Äquivalenz zurückgeführt. Dabei entspricht die durch die Validierungen entstehende Reihenfolge der seriellen, wenn für zwei Transaktionen Ti < Tj eine der folgenden Bedingungen gilt: 1) Ti beendet seine Write-Phase, bevor die Read-Phase von Tj beginnt. 83 Kapitel 5 Scheduler 2) WS(Ti )∩RS(Tj ) = ∅ und Ti beendet Write-Phase, bevor Tj seine Write-Phase beginnt. 3) WS(Ti ) ∩ (RS(Tj ) ∪ WS(Tj )) = ∅ und Ti beendet seine Read-Phase, bevor Tj seine Read-Phase beginnt. Während (1) die serielle Transaktionsausführung beschreibt, stellen (2) und (3) Bedingungen an eine sich überlappende Ausführung. (2) fordert, dass die Schreiboperationen von Ti keinen Effekt auf die gelesenen Werte von Tj haben und dass Ti keine Werte von Tj überschreibt und stellt durch die Ordnung der Schreibphasen sicher, dass Tj keinen Einfluss auf die Read-Phase von Ti hat. Da (3) zusätzlich Auswirkungen von Ti auf die SchreibPhase von Tj verbietet, können hier beide Schreib-Phasen überlappend ausgeführt werden. Da in unserem Modell Write-Phasen komplett innerhalb der atomaren Commit-Operation ausgeführt werden, müssen wir lediglich sicherstellen, dass entweder (1) oder (2) erfüllt sind. Dafür gibt es prinzipiell zwei Zeitpunkte: einmal bei der Validation von Tj gegen bereits abgeschlossene Transaktionen oder schon bei der Validierung von Ti gegen alle noch aktiven Transaktionen. Die erste Möglichkeit wird in der Literatur auch als backward optimistic concurrency control (BOCC) bezeichnet und ist das ursprünglich in [KR81] vorgestellte Verfahren, während die zweite Möglichkeit in [Hä84] eingeführt wurde und auch unter der Bezeichnung forward optimistic concurrency control (FOCC) bekannt ist. 5.2.1 Rückwärtsgerichtete Varianten Bei der rückwärtsgerichteten Variante wird eine validierende Transaktion gegen alle rückwärtigen, also allen schon erfolgreich abgeschlossenen Transaktionen getestet. Dabei ist die Validierung einer Transaktion Tj erfolgreich, d.h. sie wird akzeptiert, wenn eine der folgenden zwei Bedingungen für jede erfolgreich abgeschlossene Transaktion Ti gilt: Commit(Ti ) < Begin(Tj ) RS(Tj ) ∩ W S(Ti ) = ∅ Die erste Bedingung betrifft Transaktionen, die bei Transaktionsbeginn von Tj schon abgeschlossen waren und entspricht damit obiger Anforderung (1), während die zweite Bedingung für alle später validierten Transaktionen Anforderung (2) einfordert. Leider entstehen aus der Validierung gegenüber den bereits abgeschlossenen Transaktionen einige Nachteile: 1. Es müssen Informationen über alle vorherigen Transaktionen und deren Writesets aufbewahrt werden, was unter Umständen sehr viele sein können. Das macht die Validierung teuer. 84 5.2 Optimistische Scheduling-Verfahren 2. Es ist unflexibel in Bezug auf die Konfliktlösung: Als einzige noch aktive Transaktion kann immer nur die zu validierende Transaktion abgebrochen werden. Erforderliche Transaktionsabbrüche können so auch erst bei Transaktionsende festgestellt werden. 3. Es entsteht eine unnötig hohe Rücksetzrate aufgrund einer ungenauen Konfliktanalyse. Beispielsweise werden auch nur-lesende Transaktionen abgebrochen. Einige dieser Nachteile können durch Kombination mit Zeitmarken ausgeglichen werden. BOCC+ Eine Variante von BOCC beruht auf der Idee, Konflikte über Zeitmarken anstatt über Mengenvergleiche zu erkennen. Der entscheidende Unterschied zu klassischen Zeitmarkenverfahren [BG80] ist, dass hier Zeitmarken nicht schon zu Transaktionsbeginn, sondern erst zu Transaktionsende in der Validierungsphase zugewiesen werden. Allen Objekten wird die Zeitmarke der Transaktion, die das Objekt zuletzt geändert hat, zur Identifizierung der Objekt-Version zugeordnet, wozu eine separate Verwaltungsstruktur erforderlich ist. Das Readset erhält nun die Zeitmarke der gelesenen Version für jedes Objekt. In der Validierungs-Phase wird dann für alle gelesenen Objekte überprüft, ob die jeweiligen Versionen noch aktuell sind. Im Vergleich zu BOCC ist die Validierung bei BOCC+ effizienter und die Writesets abgeschlossener Transaktionen müssen nicht mehr aufbewahrt werden. Der große Nachteil dieser Variante ist neben den höheren Verwaltungskosten, da Zeitmarken aller Objekte zusätzlich gespeichert werden müssen, die Inflexibilität bei der Konfliktlösung. Es kann auch hier immer nur die validierende Transaktion abgebrochen werden. Da außerdem nur-lesende Transaktionen nicht automatisch validiert werden, wollen wir uns noch eine weitere optimistische Variante ansehen. 5.2.2 Die vorwärtsgerichtete Variante FOCC In [Hä84] wird die vorwärtsgerichtete Variante FOCC eingeführt, bei der eine validierende Transaktion gegen alle gleichzeitig laufenden und somit noch nicht abgeschlossenen Transaktionen getestet wird. Hier wird eine Transaktion Ti akzeptiert, wenn folgende Bedingung für alle parallelen Transaktionen Tj gilt: WS(Ti ) ∩ RSn (Tj ) = ∅ Es wird also bei der Validierung von Ti zum Zeitpunkt n gefordert, dass keine noch aktive Transaktion einen Wert gelesen hat, den Ti überschrieben hat. Diese Bedingung entspricht obiger Anforderung (2). Anforderung (1) muss hier nicht überprüft werden, da sie bei noch aktiven Transaktionen nie erfüllt sein kann. Im Vergleich zu BOCC und BOCC+ hat diese Variante einige sehr angenehme Eigenschaften: 85 Kapitel 5 Scheduler Metadaten: RS Das Readset als Liste (tid, xpath, confobj, val). WS Das Writeset als Liste (tid, xpath, confobj, val). TS Der Transaktionsstatus als Liste: (tid, status) confobj vom Zugriff betroffene Datenobjekte in normalisierter Form read(tid,xpath) checkIdempotenz(tid); if ( TS.status(tid) == ’conflict’) abort(tid); (v,confobj) = DB.read(xpath); RS.insert(tid,confobj,v); return val; write(tid,xpath,val) checkIdempotenz(tid); if ( TS.status(tid) == ’conflict’) abort(tid); (v,confobj) = DB.read(xpath); WS.insert(tid,confobj,val); begin() abort(tid) commit(tid) tid = new Transaktions-ID(); TS.insert(tid, ’aktiv’); return tid; RS.delete(tid); WS.delete(tid); TS.setStatus(tid, ’abort’); checkIdempotenz(tid); if ( ! validate(tid) ) { /* Es gibt Konflikte */ für alle in Konflikt stehenden Transaktionen Tj : TS.setStatus(Tj , ’conflict’); } materialize(tid); RS.delete(tid); WS.delete(tid); setTAstatus(tid, ’commit’); Abbildung 5.4: Das optimistische TransForm-Schedulingverfahren FOCC. 1. Der Validierungsaufwand ist geringer. Die Write-Sets abgeschlossener Transaktionen müssen nicht aufbewahrt werden, da nur aktive Transaktionen betrachtet werden. 2. Da nur das Write-Set der zu validierenden Transaktion betrachtet wird, werden nurlesende Transaktionen automatisch validiert. Es werden so weniger Transaktionen unnötig zurückgesetzt. 3. Da bei der Validierung alle betrachteten Transaktionen noch nicht abgeschlossen sind, können Konflikte sehr flexibel gelöst werden. Man besitzt die volle Freiheit bei der Wahl der Abbruchopfer. In [Hä84] werden hierzu einige Strategien diskutiert. Dabei 86 5.3 Sperrbasierte Scheduling-Verfahren ermöglichen manche Abbruchstrategien eine frühzeitige Erkennung von Konflikten und damit verbunden einen frühzeitigen Abbruch von Transaktionen. 4. Da die Validierung gegenüber aktiven Transaktionen erfolgt, entspricht die Validierungsordnung der Commit-Ordnung. Alle erzeugten Schedules liegen also in der Klasse COCSR. Diese letzte Eigenschaft gilt allerdings auch für die rückwärtsgerichteten Varianten. Es lässt sich sogar zeigen [BGRS91], dass alle erzeugten Schedules rigoros sind. Da nur während der Validierung geschrieben wird, können keine W/R- und W/W-Konflikte zwischen den aktiven und der zu validierenden Transaktion entstehen. R/W-Konflikte werden über das Validierungskriterium ausgeschlossen. So kann keines der Phänomene auftreten, die laut Abbildung 5.2 für rigorose Schedules ausgeschlossen sein müssen. 5.2.3 Der optimistische TransForm-Scheduler Das Protokoll unserer Wahl ist also die vorwärtsorientierte Variante. Im Konfliktfall wählen wir die „kill and commit“-Strategie aus [Hä84], bei der die validierende Transaktion immer erfolgreich abgeschlossen wird und alle in Konflikt stehenden Transaktionen abgebrochen werden. Das hat zwar den Nachteil, dass eventuell „zu viele“ Transaktionen abgebrochen werden, dafür erfahren abgebrochene und zum Scheitern verurteilte Transaktionen ihr Schicksal frühzeitig, nämlich schon mit ihrer nächsten Kontaktaufnahme zum Scheduler, und müssen so erst gar nicht validiert werden. So wird jede Transaktion, die ihre Validierung starten konnte, auch erfolgreich abgeschlossen. Außerdem können sich verwaiste Transaktionen so nicht störend auswirken, da sie irgendwann einfach abgebrochen werden. Es wird also nach dem first-come-first-serve-Prinzip immer die Transaktion abgeschlossen, die zuerst ihr Commit signalisiert. Die genaue Funktionsweise des Verfahrens ist in Abbildung 5.4 dargestellt. Die Funktion checkIdempotenz() überprüft anhand der Metadaten, ob die aktuelle Anfrage schon einmal ausgeführt wurde und rekonstruiert in diesem Fall eine entsprechende Antwort wie im Scheduler-Rahmen in Abbildung 5.3 gezeigt. Dabei sind confobj die normalisierten Datenobjekte, die von dem Zugriff auf xpath betroffen sind. Es kann sich dabei um mehr als ein Datenobjekt handeln. 5.3 Sperrbasierte Scheduling-Verfahren Das Hauptproblem aggressiver oder optimistischer Protokolle ist neben hohen Rücksetzraten bei hoher Konfliktwahrscheinlichkeit das Verhungern von Transaktionen: Einer aktiven Transaktion kann niemals ein erfolgreicher Abschluss zugesichert werden, da zu jeder Zeit eine andere Transaktion abgeschlossen werden kann, die auf denselben Daten operiert und deshalb in Konflikt zu ihr steht. 87 Kapitel 5 Scheduler read(t, o) write(t, o, v) keepAlive(t) if ( ∃tj | tj 6= t ∧ (tj , o) ∈ WL) return Sperrkonflikt; if ( (t, o) ∈ RL ) val = RL.read(o); else val = DB.read(o); insert(t, o, v) into RL; return val; if ( ∃tj | tj 6= t ∧ (tj , o) ∈ WL ∪ RL) return Sperrkonflikt; if ((t, o) ∈ WL) WL.update(t, o, v); return; else insert (t, o, v) into WL; return; // Sperre exist. // idempotent // Sperr-Anford. // Sperre exist. // idemp. Upd. // Sperr-Anford. aktualisiere ZM(t); Abbruch aller Transaktionen mit abgelaufenen Zeitmarken. Abbildung 5.5: Die Realisierung von Sperren in TransForm. Genau diese Zusicherung eines erfolgreichen Transaktionsabschlusses ist die Idee von Sperren. Sperrbasierte Scheduler synchronisieren den Zugriff auf gemeinsame Daten, indem sie den Datenzugriff mit Sperroperationen augmentieren. Dabei gilt, dass Datenobjekte, für die eine Transaktion eine Sperre besitzt, anderen Transaktionen solange nicht zur Verfügung stehen, bis diese die Sperre wieder freigibt. Obwohl sperrbasierte Verfahren in vielen Systemen erfolgreich eingesetzt werden, bereiten sie als Grundlage eines Scheduling-Protokolls für TransForm Schwierigkeiten: • Durch den Zugriff auf gesperrte Objekte wird eine Transaktion normalerweise blockiert, was in unserem Modell nur unter Schwierigkeiten umzusetzen ist. • Deadlocks: Ohne zentrale Instanz im Hintergrund und wegen der passiven Rolle des Web-Service sind die üblichen Strategien zur Vermeidung von Deadlocks nur schwer umzusetzen. • Zombie-Sperren: Ohne direkten Kontakt zum Client kann der Scheduler nie sicher sein, ob die Transaktionen noch aktiv sind, die Sperren besitzen. Möglicherweise konnte ein Transaktionsabbruch aufgrund eines Netzausfalls noch nicht signalisiert werden oder die Webseite wurde einfach „vergessen“. 5.3.1 Umsetzung von Sperren Sperren werden üblicherweise über eine Sperrtabelle implementiert, die jede Sperre ihrem Besitzer zuordnet. Dabei wird zwischen geteilten und exklusiven Sperren unterschieden. Sperranforderungen müssen immer atomar erfolgen. Wir haben dafür in unserem Metadatenmodell bereits die Sperrtabellen RL für die geteilten und WL für die exklusiven Sperren vorgesehen und betrachten alle dort enthaltenen Objekte als gesperrt. Es muss dann nur noch vor jedem Datenzugriff überprüft werden, ob das gewünschte Objekt von einer anderen Transaktion im RL bzw. WL als gesperrt markiert ist. 88 5.3 Sperrbasierte Scheduling-Verfahren # Sperren Sperrpunkt t Abbildung 5.6: Die Wachstumsphase vor dem Sperrpunkt und die anschließende Schrumpfungsphase des 2-Phasen-Sperrverfahrens. Die genaue Funktionsweise ist in Abbildung 5.5 dargestellt. Wie in unserem Modell gefordert, sind beide Operationen idempotent. Die üblicherweise für Sperroperationen eingeforderte Atomizität, wird von unserem Modell ohnehin für die gesamte Datenzugriffsoperation verlangt. Separate Entsperroperationen sind nicht explizit notwendig, wie in Abschnitt 5.3.3 gezeigt wird. Auch die Handhabung von Sperrkonflikten, bzw. den Zugriff auf gesperrte Objekte sowie den Umgang mit Deadlocks werden wir dort diskutieren. Für die Vermeidung von Zombie-Sperren haben wir einen Timeout-Mechanismus vorgesehen, der garantiert, dass Transaktionen, die Sperren besitzen, noch aktiv sind. Jeder Transaktion ist dabei eine Zeitmarke zugeordnet. Wenn diese Zeitmarke ein gewisses Alter erreicht hat, kann der Scheduler die Transaktion abbrechen. Clients senden in regelmäßigen Abständen Keep-Alive-Nachrichten an den Web-Service, woraufhin dieser die Zeitmarke der Transaktion aktualisiert und somit den Timeout neu aufzieht. Natürlich löst auch jede andere Operation eine Aktualisierung der Zeitmarke aus. In jeder Keep-Alive-Nachricht werden zusätzlich alle Transaktionen mit abgelaufenen Zeitmarken abgebrochen. 5.3.2 2-Phasen-Sperrprotokolle Das 2-Phasen-Sperrprotokoll, kurz 2PL [EGLT76] ist das meistverwendete Protokoll in realen Datenbankimplementierungen. Die 2-Phasigkeit ist in Abbildung 5.6 dargestellt und bezieht sich dabei auf eine erste Phase, in der Sperren angefordert und eine zweite Phase, in der diese wieder freigegeben werden. Die beiden Phasen sind über den sogenannten Sperrpunkt, der über die erste Entsperroperation definiert ist, strikt voneinander getrennt. Wenn der Sperrpunkt einmal erreicht ist, dürfen keine weiteren Sperroperationen mehr folgen. Das 2-Phasen-Sperrprotokoll vermeidet aber keine Deadlocks. Diese müssen also entweder schon in ihrer Entstehung durch Verfahren wie Wait-die/Wound-Wait [RSL78] oder Running-Priority [FR85] verhindert werden oder sie müssen erkannt und aufgelöst werden. In [ACM87] wurden unterschiedliche Strategien ausführlich untersucht. Eine Variante des 2-Phasen-Sperrprotokolls, die auch als konservativ (C2PL) bezeichnet 89 Kapitel 5 Scheduler S2PL/ SS2PL C2PL (a) Konservatives 2-Phasen-Sperren. (b) Striktes 2-Phasen-Sperren. Abbildung 5.7: Varianten des 2-Phasen-Sperrprotokolls. wird und in Abbildung 5.7(a) schematisiert ist, vermeidet Deadlocks, indem alle benötigten Sperren in einer atomaren Operation zu Transaktionsbeginn angefordert werden. Da später keine weiteren Sperren mehr angefordert werden dürfen, können auch keine Deadlocks entstehen. Der große Nachteil dieser Variante ist ihre Statik. Das komplette Readset und Writeset einer Transaktion muss im Voraus bekannt sein. Interessanterweise ist das bei unseren Formularen der Fall, da hier alle Datenobjekte in der Formulardefinition enthalten sind. Das gilt zumindest, wenn keine weiteren Formularelemente dynamisch nachgeladen werden. Abbildung 5.7(b) skizziert mit dem strikten 2PL (S2PL) eine weitere Variante, die in realen Implementierungen häufig zum Einsatz kommt. Hier werden alle Schreibsperren einer Transaktion bis ans Ende der Transaktion gehalten. Es basiert auf der Überlegung, dass man bei dynamischen Situationen nie wissen kann, ob eine Transaktion gehaltene Sperren weiterhin benötigt oder eventuell sogar weitere anfordern wird. Genau das ist auch bei Formularen der Fall, da der Benutzer jederzeit weitere Änderungen bewirken kann. Wie es der Name schon andeutet, produziert dieses Verfahren strikte Historien. Wenn nicht nur die Schreibsperren, sondern alle Sperren erst zu Transaktions-Ende freigegeben werden, spricht man von starkem 2PL (SS2PL), das sogar Rigorosität garantiert. Natürlich gilt folgende Inklusionsbeziehung: Gen(SS2PL) ⊂ Gen(S2PL) ⊂ Gen(2PL) 5.3.3 Der sperrbasierte TransForm-Scheduler Da ein Scheduler zu keinem Zeitpunkt wissen kann, wann ein Benutzer ein Formularelement schreibt, können keine Sperren vorzeitig freigegeben werden, sondern müssen bis Transaktionsende gehalten werden. Da das für Lese- wie auch für Schreibsperren gilt, entspricht diese Situation genau dem starken 2-Phasen-Sperrprotokoll, das wir deshalb als Grundlage unseres sperrbasierten TransForm-Schedulers gemäß Abschnitt 5.3.1 umsetzen wollen. Zunächst müssen wir aber klären, wie Sperrkonflikte und Deadlocks gehandhabt werden. 90 5.3 Sperrbasierte Scheduling-Verfahren Sperrkonflikte Sperrbasierte Scheduler versetzen die Transaktion üblicherweise in einen Wartezustand, wenn das angeforderte Objekt gerade gesperrt ist und aktivieren sie wieder, sobald das Objekt zur Verfügung steht. In der Zwischenzeit werden Aktionen anderer Transaktionen vorgezogen. In unserem Transaktionsmodell ist das so nicht möglich. Der Scheduler kann immer nur die aktuell angeforderte Aktion entweder ausführen oder mit dem Hinweis auf einen Sperrkonflikt ablehnen. Die Initiative für eine wiederholte Sperranforderung muss also vom Client ausgehen. Da dieser in Form des Formularmanagers wiederum im Ungewissen über die Situation des Web-Service ist und keinerlei Informationen über andere Transaktionen besitzt, kann er nur in bestimmten Abständen die Sperre solange neu beantragen bis sie schlussendlich gewährt wird. Da er die Erfolgsaussichten nicht abschätzen kann, führen die eventuell vielen erfolglosen Wiederholungen zu einer unnötig hohen Serverlast. Eine andere Möglichkeit wäre es, im Falle von Sperrkonflikten sofort die Transaktion abzubrechen. Ein darauf folgender Neustart der Transaktion würde allerdings auch zu wiederholten Sperranforderungen führen. Immerhin wären Deadlocks von vornherein ausgeschlossen. Deadlocks Da SS2PL nicht Deadlock-frei ist, müssen diese also berücksichtigt werden. Um Deadlocks zu erkennen, müsste ein Graph mit Sperrabhängigkeiten verwaltet und auf Zyklen hin überwacht werden, die mittels Transaktionsabbrüchen aufgelöst werden. Üblicherweise wird ein solcher Graph im Hintergrund gehalten und immer nur um die aktuelle Aktion ergänzt. Bei uns müsste dieser Graph allerdings in jedem Schritt neu berechnet oder in den Metadaten modelliert werden. Da aber auch hier die für den Abbruch nötige Kontaktaufnahme zum Client nicht möglich ist, führt uns das zur gleichen Situation wie im letzten Abschnitt. Der Formularmanager müsste also auch hier in regelmäßigen Abständen Kontakt zum Scheduler aufnehmen. Wir setzten deshalb auf eine Strategie, die die Behandlung von Deadlocks dem Formularmanager überlässt: Jeder Client wiederholt im Falle eines Sperrkonflikts die Sperranforderung nach einer gewissen Zeit. Die Abstände zwischen den Anforderungen werden von Mal zu Mal erhöht. Allerdings ist die maximale Anzahl an Wiederholungen begrenzt und der Formularmanager bricht die Transaktion ab, wenn diese Obergrenze erreicht ist. Eine andere Möglichkeit wäre der Einsatz der konservativen 2PL-Variante, bei der Deadlocks vermieden werden und Sperrkonflikt nur bei der Begin-Operation möglich sind. Damit alle benötigten Sperren in einem Schritt gesetzt werden können, müssen Formulare statisch sein und dürfen keine dynamisch nachgeladenen Elemente enthalten. Das ist allerdings bei vielen Formularen der Fall und stellt somit ein geringeres Problem dar als 91 Kapitel 5 Scheduler die Notwendigkeit, gleich alle Datenobjekte exklusiv zu sperren, ohne zu wissen, ob diese Sperren später auch wirklich benötigt werden. Da Formulare im Allgemeinen aber dynamisch sind und wir keine der beiden Varianten generell bevorzugen können, wollen wir beide Methoden kombinieren, indem unser Scheduler in zwei Modi betrieben werden kann: 1. C2PL: In diesem Modus müssen alle benötigten Sperren bei Transaktionsbeginn angefordert werden. Dabei wird nicht zwischen Lese- und Schreibsperren unterschieden. 2. SS2PL: In diesem Modus wird zwischen Lese- und Schreibsperren unterschieden. Deadlocks werden über obigen Timeout-Mechanismus gelöst und es gibt keinerlei Restriktionen, wann Sperren angefordert werden können. Das TransForm-Sperrverfahren Abbildung 5.8 beschreibt das Verfahren. Auch hier kommt eine deferred-update Strategie zum Einsatz, bei der Schreiboperationen erst mit Transaktionsabschluss in die Datenbank übertragen werden. Dazu werden die Werte aller geschriebenen Datenobjekte in der Sperrtabelle WL zwischengespeichert. Da gesperrte Objekte von keiner anderen Transaktion geschrieben werden dürfen, wird für den Test, ob eine angeforderte Operation bereits ausgeführt wurde, keine separate Anfrage-ID benötigt. Bei der Begin-Operation kann über einen Parameter festgelegt werden, ob zwischen Leseund Schreibsperren unterschieden wird. Wenn das nicht der Fall ist, wird bei jedem Lesezugriff nicht nur eine Lesesperre angefordert, sondern auch noch eine Schreibsperre. Damit diese Einträge aber später nicht zu Schreibaktionen in der Datenbank führen, wird der gelesene Wert in die Tabelle WL eingetragen. Weiterhin können mit der Begin-Operation weitere Datenobjekte spezifiziert werden, die gesperrt werden sollen. Die Operation ist nur erfolgreich, wenn alle Sperren auch erworben werden. Der Client kann zwischen den beiden Betriebsmodi auswählen, wenn kein Modus in der Formulardefinition fest vorgegeben ist. Dazu muss im Formular ein spezielles Formularelement definiert sein, über das der Modus per Hand festgelegt werden kann. Für beide Betriebsmodi sieht die Begin-Operation folgendermaßen aus: 1. C2PL: begin(’exclusive’, {o1 , ..., on }) mit Preclaiming aller Objekte. Der Formularmanager ist selbst dafür verantwortlich, keine weiteren Sperren mehr anzufordern. 2. SS2PL: begin(’shared’, {o1 , ..., on }). Auch hier kann eine Objektliste enthalten sein, deren Initialwerte ausgelesen werden. Dazu werden aber lediglich geteilte Lesesperren angefordert. Der Formularmanager muss den Timeout-Mechanismus umsetzen. Zusätzliche Sperren werden bei Bedarf angefordert. 92 5.3 Sperrbasierte Scheduling-Verfahren Metadaten: TS (tid, status, modus) RL (tid, object) WL (tid, object, value) Parameter: tid modus {o1 ...on } Liste, in der die Transaktionen verwaltet werden Liste für die Verwaltung von Lesesperren Liste für die Verwaltung von Schreibsperren Transaktions-ID Konfigurationsoption: ist entweder exclusive oder shared - exclusive: ausschließlich Exklusivsperren - shared: Unterscheidung exklusiver und nicht-exklusiver Sperren Datenobjekte Operationen: begin(modus, {o1 ...on }) read(), write() tid = new Transaktions-ID; if ( modus=’exclusive’ ){ fordere eine Exklusivsperre für o1 ...on an. } else { fordere geteilte Sperren für o1 ...on an. } if ( alle Sperren erworben ) { TS.insert(tid, ’aktiv’); return tid; } siehe Abbildung 5.5 abort(tid) RL.delete(tid); WL.delete(tid); TS.setStatus(tid, ’abort’); commit(tid) checkIdempotenz(tid); materialize(tid); TS.setStatus(tid, ’commit’); RL.delete(tid); WL.delete(tid); Abbildung 5.8: Das TransForm-Sperrverfahren. 5.3.4 Diskussion weiterer Sperrverfahren In der Literatur existieren zahlreiche Sperrverfahren, die nicht dem 2PL-Sperrprotokoll folgen und trotzdem sicher und teilweise deadlockfrei sind. Bei Ordered Sharing Locks handelt es sich um eine Erweiterung des 2PL-Protokolls, das exakt die Klasse OCSR der ordnungserhaltend konfliktserialisierbaren Schedules erzeugen kann [AA90, AA95]. Dieses Verfahren erweitert den traditionellen Sperrbegriff, der lediglich zwischen exklusiven und nicht-exklusiven Sperren unterscheidet und auf dem Konflikt zwischen Operationen beruht. Die Idee des ordered sharing von Sperren beruht nun auf der Tatsache, dass die Ordnung der Konfliktoperationen entscheidend für die Serialisierungs- 93 Kapitel 5 Scheduler ordnung zwischen Transaktionen und somit für die Serialisierbarkeit ist. Das Verfahren berücksichtigt bei Sperren sowohl Konflikte als auch Ordnungsrelation zwischen Transaktionen und fordert die Ausführung von Operationen in der gleichen Reihenfolge, in der sie die Sperren erhalten. Dabei sind acht verschiedene Sperrtabellen L1 bis L8 definiert, die unterschiedliche Grade an Parallelität zulassen und auch unterschiedlichen Schedulerklassen angehören: L1 entspricht der üblichen Sperrtabelle. L8 lässt am meisten Parallelität zu, liegt aber lediglich in RC. Deadlocks sind außer bei L8 überall möglich. Eine Performancestudie der verschiedenen Modi ist in [AAL94] zu finden. Da wir Striktheit einfordern, erhalten wir mit diesem Protokoll nur wenig mehr an Nebenläufigkeit (shared Read dann Write) bei erhöhtem Verwaltungsaufwand. Ähnlich wie Ordered Sharing Locks führt Altruistic Locking [SGMS94] eine neue Kontrolloperation ein, die donate genannt wird. Mit dieser Operation kann angezeigt werden, dass auf ein Datenobjekt nicht mehr länger zugegriffen wird und dieses deshalb anderen Transaktionen zur Verfügung gestellt werden kann. Da wir nie wissen können, ob auf ein Datenobjekt noch einmal zugegriffen wird, kommt diese Verfeinerung für einen Einsatz in unserem Szenario nicht in Frage. Nicht zweiphasige Sperrverfahren Erfolgt der Datenzugriff unter Einhaltung gewisser Muster, kann auf die 2-Phasen-Eigenschaft verzichtet werden. Wir geben zwei Beispiele: Baumbasierte Sperren: Hier wird die Datenbank als Baum betrachtet. Der Zugriff auf die Datenobjekte muss dabei in der vom Baum vorgegebenen Reihenfolge erfolgen. Dabei darf auf ein Objekt nur zugegriffen werden, wenn man auf das Elternobjekt zugreifen darf. Der Grad der Parallelität hängt davon ab, wie schnell Vorgängerknoten freigegeben werden. In unserem Szenario müssen Sperren bis Transaktionsende gehalten werden. Das macht baumbasierte Sperren für uns ungeeignet. Das Verfahren eignet sich eigentlich nur für Szenarien, in denen die Transaktionen im Vorhinein bekannt sind. Geometrische Sperrverfahren [LSSW84, LSSW90]: Hier wird die Schrittfolge einer Transaktion als Folge von Punkten auf den Achsen eines euklidischen Raumes dargestellt. Zueinander in Konflikt stehende Operationen definieren dabei einen Konfliktpunkt. Ein Schedule wird durch eine monotone Kurve repräsentiert und ist genau dann in CSR, wenn seine Kurve keine zwei Konfliktpunkte separiert. In [LSSW86] wird ein Verfahren vorgestellt, das vor allem in Bezug auf die mögliche Nebenläufigkeit sehr interessant ist. Da aber auch bei diesem Ansatz alle Transaktionen im Vorhinein für eine Analyse bekannt sein müssen, kommt auch dieses Verfahren für uns nicht in Betracht. 94 5.4 Ein hybrider TransForm-Scheduler 5.4 Ein hybrider TransForm-Scheduler Sowohl optimistische als auch sperrbasierte Verfahren haben Vor- und Nachteile. Während optimistische Scheduler vor allem von Szenarien mit wenigen Konflikten profitieren, aber bei häufigerem Vorkommen mit hohen Rücksetzraten und der Gefahr des Verhungerns einzelner Transaktionen zu kämpfen haben, entwickeln Sperrverfahren gerade in der Vermeidung dieser zwei Punkte ihre Stärken. Es lohnt also darüber nachzudenken, diese beiden Verfahren zu kombinieren. Typischerweise kann ein Scheduler nicht im Voraus wissen, wie Transaktionen aussehen und wie häufig Konflikte sind. Deshalb kann man auch nicht wissen, welches Protokoll die aktuelle Auslastung besser handhabt. In [Lau82] wird deshalb ein Verfahren vorgeschlagen, das Sperren und das optimistische Verfahren BOCC in einen Hybrid-Scheduler integriert. In diesem Verfahren ist es einer Transaktion erlaubt, die Datenzugriffe, für die Konflikte erwartet werden, mit Sperren zu versehen oder eine optimistische Variante zu wählen, wenn bei einem Zugriff davon ausgegangen wird, dass keine Konflikte auftreten. Die Sperren werden dabei gemäß dem 2PL-Protokoll erlangt. In der Tradition optimistischer Protokolle ist hier zusätzlich eine Validierungsphase vorgesehen. Alle Sperren werden erst in dieser Validierungsphase freigegeben. Es handelt sich also um starkes 2-Phasen-Sperren. Die Validierung von sperrbasierten Datenzugriffen ist immer erfolgreich. Für alle nicht-gesperrten Datenzugriffe muss in der Validierungsphase sichergestellt werden, dass diese nicht mit gesperrten Objekten in Konflikt stehen. Im Folgenden werden wir ein hybrides Schedulingprotokoll für TransForm entwickeln, das unsere beiden bisher vorgestellten TransForm-Scheduler integriert. Es handelt sich dabei um das erste Verfahren, das 2-Phasen-Sperren mit einem vorwärtsgerichteten optimistischen Protokoll kombiniert. Kombination unseres optimistischen und sperrbasierten Verfahrens Dieser Hybrid-Scheduler akzeptiert eine optimistische Transaktionsausführung, gemischt mit einer sperrbasierten in ähnlicher Weise, wie wir die unterschiedlichen Sperrmodi in den sperrbasierten Scheduler integriert haben. Die Protokollauswahl kann dabei entweder nach gescheiterten Transaktionen automatisch auf Sperren umgestellt werden oder es kann dem Benutzer überlassen bleiben, das Verfahren über spezielle Formularelemente auszuwählen. Für den Scheduler spielt das keine Rolle: Er liest über den protocol-Parameter der Begin-Operation die gewünschte Betriebsart aus und speichert diese als Betriebsmodus der Transaktion in der TS-Tabelle. Die Lese- und Schreibzugriffe werden nun ausgeführt, wie es von den Protokollen vorgegeben ist. Natürlich muss der Scheduler zunächst anhand der TS-Tabelle ermitteln, welche Betriebsart dabei zum Einsatz kommen soll. 95 Kapitel 5 Scheduler RL WL RS WS tj o Lese-Sperren Schreib-Sperren Lesezugriffe der optimistischen Transaktionen Schreibzugriffe der optimistischen Transaktionen parallele Transaktionen Datenobjekt commitSperren(t) if ( ∃tj | tj 6= t ∧ (t, o) ∈ WL ∧ (tj , o) ∈ RS) { TS.setStatus(tj , ’conflict’); /* führt zu Abbruch von tj */ } materialize(t); RL.delete(t); WL.delete(t); TS.setStatus(t, ’commit’); commitOptimist(t) if (∃tj | tj 6= t ∧ (t, o) ∈ WS ∧ (tj , o) ∈ RL) { abort(t); /* Validierung erfolglos */ } if (∃tj | tj 6= t ∧ (t, o) ∈ WS ∧ (tj , o) ∈ RS) { TS.setStatus(tj , ’conflict’); /* führt zu Abbruch von tj */ } materialize(t); RS.delete(t); WS.delete(t); TS.setStatus(t, ’commit’); Abbildung 5.9: Das hybride Scheduling-Verfahren für TransForm. Korrektheit Wie bei unserem optimistischen Scheduler müssen wir nur die Serialisierungsbedingung (2) aus Abschnitt 5.2 testen. Es muss dazu bei der Validierung beider Arten von Transaktionen überprüft werden, ob die überschriebenen Werte nicht von parallelen Transaktionen gelesen wurden. Dabei müssen wir für die Korrektheit unseres Verfahrens sicherstellen, dass für alle vier Kombinationen von Konflikten zwischen sperrenden und optimistischen Transaktionen obige Bedingung (2) eingehalten wird. Folgende Validierungsregeln stellen dies sicher: 1. Validierung einer optimistischer Transaktion Topti : Hier kann es sowohl mit sperrbasierten als auch mit anderen optimistischen Transaktionen zu Überschneidungen kommen: a) Konflikt mit sperrenden Transaktionen: Falls WS(Topti ) ∩ RLn (Tspj ) = ∅ nicht gilt, muss die validierende Topti selbst abgebrochen werden, da Sperren Vorrang besitzen. b) Konflikt mit optimistischen Transaktionen: Falls WS(Topti ) ∩ RSn (Toptj ) 6= ∅ 96 5.5 Verteilte Transaktionen gilt, wenden wir wie bei unserem optimistischen Scheduler die kill and commit-Strategie an und bewirken den Abbruch der entsprechenden Transaktionen. 2. Validierung einer sperrender Transaktion Tspi : Da es der Sperrmechanismus ausschließt, dass eine parallele Transaktion eine Sperre auf ein von Tspi gesperrtes Objekt besitzt, muss lediglich für die parallelen optimistischen Transaktionen Toptj überprüft werden, ob W L(Tspi ) ∩ RS(Toptj ) = ∅ gilt. Sollte das nicht der Fall sein, bleibt uns keine andere Möglichkeit, als diese optimistische Transaktion abzubrechen. Die Funktionsweise der Validierung des hybriden TransForm-Schedulers ist in Abbildung 5.9 detailliert dargestellt. Die anderen Operationen werden gemäß den vorgestellten Protokollen durchgeführt und sind deshalb nicht noch einmal aufgeführt. 5.5 Verteilte Transaktionen Verteilte Transaktionen greifen auf Ressourcen zu, die von Datenbanken an unterschiedlichen sites eines Netzwerks verwaltet werden. Dabei werden die unterschiedlichen Datenbanksysteme, die Subtransaktionen einer globalen Transaktion ausführen, als Kohorten der globalen Transaktion bezeichnet. Unter der Voraussetzung, dass die ACID-Eigenschaften an jeder site garantiert sind, muss für die globale Transaktion noch folgendes gelten: Atomare Terminierung: Entweder schließen alle Kohorten erfolgreich ab, oder es werden alle zusammen abgebrochen. Globale Deadlockfreiheit/Serialisierbarkeit: Es muss sichergestellt sein, dass eine globale Serialisierung existiert, die für alle Transaktionen gilt. 5.5.1 Das 2-Phasen-Commit-Protokoll Um die globale Atomizität zu gewährleisten, wird normalerweise ein Verfahren wie das 2-Phasen-Commit-Protokoll [Gra78] eingesetzt, das von einem sogenannten Koordinator eingeleitet wird, um die globale Transaktion abzuschließen: In der ersten Phase sendet der Koordinator eine prepare-Nachricht an alle Kohorten, mit der die Vorbereitung des Commits anfordert wird. Nach Erhalt einer solchen Nachricht überprüft eine Kohorte, ob die Subtransaktion erfolgreich abgeschlossen werden kann. Wenn das der Fall ist, versetzt sie die Transaktion in einen Zustand, in dem sie nicht mehr abgebrochen werden kann und antwortet dem Koordinator mit einer ready-Nachricht. Andernfalls antwortet die Kohorte mit einer aborting-Nachricht und bricht die Subtransaktion ab. In der zweiten Phase wartet der Koordinator auf die Antworten aller Kohorten. Nur wenn alle Kohorten mit ready geantwortet haben, veranlasst der Koordinator ein globales Commit, indem er eine commit-Nachricht an alle Kohorten sendet. Ansonsten schickt er diesen 97 Kapitel 5 Scheduler eine abort-Nachricht. Die Kohorten schließen oder brechen nun die Subtransaktionen ab, je nachdem, welche Nachricht sie erhalten und teilen dies dem Koordinator mittels einer done-Nachricht mit. Dieser betrachtet die globale Transaktion als abgeschlossen, sobald er von jeder Kohorte die done-Nachricht erhalten hat. Das 2-Phasen-Commit-Protokoll alleine garantiert allerdings noch keine globale Serialisierbarkeit, da die Serialisierungsreihenfolgen der lokalen Transaktionen unterschiedlich sein können. In Abhängigkeit der lokalen Schedulingprotokolle kann aber sichergestellt werden, dass mit dem 2PC-Protokoll aus der lokalen Serialisierbarkeit an jeder Site globale Serialisierbarkeit folgt [LBK02, S.897]. Da bei Schedulern der Klasse COCSR die Freigabeordnung der Konfliktordnung entspricht, entstehen an allen Sites, bei denen die Freigabe erfolgt, die gleichen Serialisierungsreihenfolgen und somit auch eine global eindeutige. In [Wei84] wird zeigt, dass wenn an jeder site entweder ein striktes 2-Phasen-Sperrprotokoll oder ein optimistisches Verfahren zum Einsatz kommt, unter der Verwendung des 2-Phasen-Commit-Protokolls jeder globale Schedule serialisierbar ist. Die Reihenfolge wird dabei durch die Koordinatoren bestimmt. Die Beweisidee beruht auf der Festlegung einer globalen Serialisierungsreihenfolge durch die globale Freigabeordnung bei der Klasse COCSR, die sowohl für das strikte 2-PhasenSperrprotokoll als auch für ein optimistisches Verfahren gilt. Angenommen eine Transaktion hat an den sites A und B aufgrund von Konflikten unterschiedliche Serialisierungsreihenfolgen: T1A → T2A und T2B → T1B . Fall 1 (optimistisch): Da es einen Konflikt zwischen T1A und T2A gibt, kann nur eine der beiden Subtransaktionen abgeschlossen werden. Wir nehmen oBdA an, dass es sich dabei um T1A handelt. T2A würde durch das Protokoll abgebrochen werden. 2PC stellt nun global sicher, dass nur T1 abgeschlossen werden kann. Da T2 also global nicht abgeschlossen wird, kann auch T2B lokal nicht abgeschlossen werden. So kann auch keine andere Serialisierungsreihenfolge an site B entstehen. Fall 2 (striktes 2-Phasen-Sperren): Da alle Sperren bis Commit gehalten werden, legt die lokale Ordnung einer Seite die globale fest (oBA T1 → T2 ). Wenn nun durch eine andere lokale Ordnung T2 → T1 verlangt wird, entsteht eine Deadlock-Situation, die mit dem 2-Phasen-Commit-Protokoll nicht vereinbar ist. 5.5.2 Verteilte Transaktionen in TransForm In TransForm können in einer Webseite durchaus mehrere Formulare definiert sein, die in unterschiedlichen Transaktionen auf unterschiedliche Web-Services zugreifen. Normalerweise sind diese Transaktionen unabhängig voneinander. Manchmal ist es allerdings erwünscht, dass eine Transaktion nur abgeschlossen wird, wenn das auch eine andere tut. Beispielsweise wenn über ein Formular ein Flug gebucht wird, während der Benutzer über ein anderes Formular eine passende Zugverbindung reserviert, die er nur benötigt, wenn 98 5.5 Verteilte Transaktionen Web-Service A Koordinator repare) ready commit(p Phase 1 commit(p commit() repare) ready commit() Phase 2 done Web-Service B done t Abbildung 5.10: 2-Phasen-Commit-Protokoll in TransForm. die Flugbuchung erfolgreich ist. Oder eine Webseite zeigt einerseits Börsenkurse an und bietet andererseits die Möglichkeit, Aktien zu kaufen. Dann sollte sichergestellt sein, dass beim Kauf die angezeigten Kurse noch aktuell sind. In beiden Fällen handelt es sich um verteilte Transaktionen über mehrere Formulare. Eine site in unserer bisherigen Terminologie entspricht dabei einem TransForm-Dienst, der eine lokale Transaktion ausführt. Die Rolle des Koordinators, der das 2-Phasen-CommitProtokoll überwacht, kann dabei vom Formularmanager in Form des JavaScript-basierten Controllers übernommen werden. Dazu müssen wir folgende Änderungen an der Schnittstelle des Web-Service bzw. des Schedulers vornehmen: Die commit-Methode erhält als zusätzlichen Parameter ein prepare-Flag. Wenn dieses Flag gesetzt ist, führt der Scheduler kein normales Commit durch, sondern lediglich die Vorbereitung eines solchen. Dazu führen wir einen neuen Transaktionszustand prepared ein, den eine Transaktion zugewiesen bekommt, die mit dem prepare-Flag erfolgreich committed ist. Der Commit erfolgt dabei nach den gleichen Regeln wie bisher, es werden allerdings noch keine Effekte der Transaktion in die Datenbank übertragen, und die Datenzugriffe bleiben in den Metadaten. Erst mit dem endgültigen Commit in der zweiten Phase wird die Materialisierung nachgeholt. Der ganze Ablauf ist in Abbildung 5.10 dargestellt. Nach erfolgreichem prepare-Commit muss sichergestellt sein, dass die endgültige Freigabe auch durchgeführt werden kann. Bei Einsatz des sperrbasierten Schedulers sind dazu keine weiteren Anpassungen nötig, da alle Sperren noch in den Metadaten vermerkt sind und somit weiter gehalten werden. Bei unserem optimistischen Scheduler müssen wir die kill and commit-Strategie anpas- 99 Kapitel 5 Scheduler sen. Konflikte mit präparierten Transaktionen führen automatisch zum Transaktionsabbruch. Da wir natürlich nicht die präparierten Transaktionen abbrechen dürfen, müssen wir in der Validierung den Transaktionszustand zusätzlich prüfen. Dabei bricht sich die validierende Transaktion selbst ab, sobald eine der in Konflikt stehenden parallelen Transaktionen in dem Zustand prepared ist. Bei unserem Hybrid-Protokoll können wir die angepasste Strategie für die Validierung der optimistischen Transaktionen genauso anwenden. Wir müssen hier jedoch zusätzlich bei der Sperranforderung auf präparierte optimistische Transaktionen Rücksicht nehmen. Sperren werden also nur noch gewährt, wenn keine Konflikte mit solchen präparierten Transaktionen auftreten. 100 Kapitel 6 Formulare Ein Formular ist ein standardisiertes Mittel zur Erfassung von Daten, das klassischerweise in Papierform vorliegt. In der Regel geben Formulare Textfelder wie zum Beispiel „Nachname“ oder Auswahlfelder wie beispielsweise „angestellt/selbstständig“ vor. So können alle relevanten Daten vollständig erfasst und die bei formlosen Schriftstücken auftretenden Mehrdeutigkeiten vermieden werden. Diese Eigenschaften sind natürlich auch für die elektronische Datenerfassung erwünscht, weshalb Formulare auch in elektronischer Form z. B. als Web-Formulare in HTML oder als Widgets in Bibliotheken für Benutzeroberflächen vorliegen. Etwas weiter gefasst kann aber auch beispielsweise eine Wikipedia-Editierseite als Formular aufgefasst werden, da Texte im Rahmen einer schablonenartigen Vorlage frei eingegeben werden können. TransForm stellt auf der Clientseite Formulare als Gegenstück zu den Web-Services zur Verfügung. Im Anlehnung an obigen Formularbegriff bilden sie dabei das standardisierte Mittel zur Erfassung bzw. Verarbeitung von Daten über einen TransForm-Dienst und erleichtern den Umgang mit der für eine maschinelle Verarbeitung entworfenen Schnittstelle des Web-Service. TransForm-Formulare sind dabei zunächst abstrakte Objekte, deren Eigenschaften und Verhalten von einem Modell festlegt werden, das für die korrekte Nutzung eines TransForm-Dienstes sorgt. Sie sind dabei nicht an eine bestimmte Plattform gebunden und lassen sich in Browsern beispielsweise über clientseitige Skriptsprachen wie Javascript implementieren. Prinzipiell ist sogar eine native Unterstützung der Formulare seitens der Browser neben den normalen HTML-Formularen denkbar. Da das aber zumindest in absehbarer Zeit nicht zu erwarten ist, wollen wir im Folgenden die Umsetzung in Browsern mittels JavaScript und HTML schildern. 6.1 Der Formular-Manager Wir betrachten also den TransForm-Datenzugriff aus Client-Perspektive. Zentrales Element sind spezielle Formulare, die ähnlich den bekannten HTML-Formularen mittels Tags im Quelltext von Webseiten definiert sind. Diese Ähnlichkeiten sind beabsichtigt, da so die Umstellung auf TransForm-Formulare leichter fällt. Als Gegenstück zu TransForm-Diensten 101 Kapitel 6 Formulare lassen sie, sozusagen als Sicht eines MVC-Musters, Benutzer über Visualisierungen Datenobjekte bearbeiten, die in der Tag-Definition angegebenen sind. Alle Datenzugriffe, die von den Elementen eines Formulars ausgelöst werden, sind dabei in eine Transaktion gekapselt. Verantwortlich dafür ist ein Controller in Form eines JavaScript-Programms, das im onload-Event der Webseite aufgerufen wird. Dieses Programm liest zuerst alle TransForm-Tags der Seite ein und erzeugt verschiedene JavaScript-Objekte. Die Aufrufparameter dieser Objekte liest es dabei aus den Tag-Definitionen aus. Anschließend rendert der Controller bzw. die erzeugten Objekte verschiedene Widgets wie beispielsweise Ein/Ausgabeelemente. Dazu wird jeweils eine visuelle Repräsentierung erzeugt und Javascript-Funktionen für Events hinterlegt, die Benutzer-Interaktionen in Dienstaufrufe übersetzen. Das Formularmodell aus Kapitel 3 lässt sich direkt in Javascript-Objekte umsetzen. In diesem Modell besteht ein Formular aus einem Top-Level-Objekt, Methoden für die Kommunikation mit dem Dienst sowie Formularelementen, die jeweils mit einem Datenobjekt verknüpft sind. Neben diesen sieht der Controller auch noch für die Authentifikation und die Koordination verteilter Transaktionen Objekte vor: tfForm: Der Controller erzeugt für jedes gefundene Formular ein tfForm-Objekt, das die formularweit definierten Variablen verwaltet, Methoden für die Transaktionskontrolle bereitstellt und für jedes Formularelement ein eigenes Objekt erzeugt. tfInput: Die unterschiedlichen Elemente der Formulare werden von tfInput-Objekten bzw. entsprechend abgeleiteten Objekten verwaltet und visualisiert. Diese Objekte enthalten Kommunikationsmethoden für den Datenzugriff über den Web-Service. tfAuth: Die Authentifikation von Anwendern und Verwaltung von Sessions wird von tfAuthObjekten übernommen. Sie übernehmen die clientseitigen Aufgaben des Authentifikationmechanismus aus Abschnitt 3.2.4 und erzeugen bei Bedarf einen Login-Bereich auf der Seite. tfCoord: Falls eine verteilte Transaktion über mehrere Formulare definiert ist, übernimmt ein tfCoord-Objekt die Rolle des Koordinators in einem 2-Phasen-Commit-Protokoll und stellt die Einhaltung der Regeln aus Abschnitt 5.5 sicher. 6.1.1 Formulare Das Top-Level-Objekt eines Formulars, sowie ein Teil der Methoden wird also durch ein tfForm-Objekt implementiert. Es enthält Variablen für die globalen Parameter wie die URL des Dienstes oder das verwendete Schedulingprotokoll, die für die Kontaktaufnahme mit dem Dienst bekannt sein müssen. Weiterhin enthält es Variablen, in denen die zur Laufzeit ermittelten Parameter wie Identifizierer von Transaktionen (tid), Sessions (sid) und Usern (uid) gespeichert werden, die für die Transaktionsdurchführung benötigt werden. 102 FormState 6.1 Der Formular-Manager commit commit() start init begin() aktiv abort() abort Abbildung 6.1: Zustände von Formularen. Neben diesen Variablen implementiert es Methoden für die Kommunikation mit dem Dienst. Lese- und Schreiboperationen sind für jedes seiner Eingabeelemente in dessen tfInput-Objekt definiert. Es bleiben die Transaktionskontrolloperationen Begin, Abort und Commit, die den Zustand der Transaktion beeinflussen, wie es in Abbildung 6.1 dargestellt ist. Im Startzustand wird die Definition aus den Tags gelesen und das Objekt erzeugt. Nachdem diese Initialisierung erfolgreich abgeschlossen ist, geht das Formular in den Zustand init über, von dem aus über die begin()-Methode der Zustand aktiv erreicht werden kann, in dem das Formular bearbeitet werden kann. Von dort geht das Formular je nach Terminierungsart entweder in den Zustand commit oder abort über, in denen dem Benutzer der Status signalisiert wird. Anschließend kann das Formular wieder in den Status init übergehen, in dem eine neue Transaktion gestartet werden kann. begin(session) fordert die Transaktions-ID an. Wenn session akzeptiert wird und tid geliefert wird, geht es in Zustand aktiv über. Ansonsten bleibt es in Zustand init. In diesem Fall muss begin() mit neuer Session-ID erneut aufgerufen werden. abort(tid) Diese Methode kann nur im Zustand aktiv aufgerufen werden. Sie bewirkt serverseitig den Abbruch der Transaktion. Das Formular wechselt in den Zustand abort. commit(tid) Auch diese Methode kann nur im aktiven Zustand aufgerufen werden. Sie fordert den Transaktionsabschluss an und bewirkt einen Übergang zu Zustand commit, wenn die Transaktion abgeschlossen wurde. Andernfalls geht sie in den Zustand abort über. Im Gegensatz zu den Datenzugriffsoperationen, die immer mit einem sichtbaren Element verbunden sind, können Kontrolloperationen implizit, beispielsweise mit dem Laden oder Verlassen der Webseite, oder explizit über entsprechende Buttons ausgelöst werden. 6.1.2 Eingabeelemente Als Container für verschiedene Formularfelder enthält ein Formular-Objekt für jedes dieser Eingabefelder ein Unterobjekt. Im einfachsten Fall handelt es sich dabei um normale Ein/Ausgabefelder. Es können aber auch Auswahlboxen, Schieberegler oder auf bestimm- 103 FormElementState Kapitel 6 Formulare aktiv start lesen schreiben passiv konflikt Abbildung 6.2: Zustände von Formularelementen. te Eingabedaten spezialisierte Elemente enthalten sein. In Abschnitt 6.2 werden wir eine Auswahl solcher Formularelemente vorstellen, die über den üblichen Formularbegriff von HTML-Formularen hinausgehen. Zustandsübergänge Ein Formularelement kann dabei die in Abbildung 6.2 dargestellten Zustände annehmen: Startzustand: Dieser Zustand wird erreicht, sobald das Element visuell repräsentiert und das tfInput-Objekt initialisiert ist. lesen: In diesem Zustand wird der Wert von xpath über den Webservice gelesen. Normalerweise geht es in aktiv über, außer bei einem Konflikt. Dann geht das Element in den Zustand konflikt über und das Formularobjekt bewirkt den Transaktionsabbruch. aktiv: In diesem Zustand bleibt das Element solange es von einem Benutzer bearbeitet wird. Es bewirkt dann einen Übergang in den Zustand schreiben. schreiben: In diesem Zustand wird überprüft, ob ein Serverzugriff nötig ist. Wenn nicht, geht es sofort in den Zustand passiv über. Ansonsten kann es, je nach Signal des WebService, eventuell auch in den Zustand konflikt übergehen. passiv: Hier wird gewartet, bis der Benutzer das Element bearbeitet. Dann wird in den Zustand lesen übergegangen. Endzustand: Sobald ein Konflikt signalisiert wird, hat das Element seinen Endzustand erreicht. Das Formularobjekt muss eine neue Transaktion starten, damit das Element wieder im Startzustand neu initialisiert wird. Bei der Aktivierung muss dabei beachtet werden, dass ein Ausgangswert des Formulars eventuell schon in der Tag-Definition enthalten sein kann. Dann geht das Formularelement direkt vom Startzustand in den Zustand aktiv über. Wenn ein Schedulerprotokoll es ausschließt, dass der eingelesene Wert sich in der Datenbank ändert, kann direkt von passiv in aktiv übergegangen werden, ohne den Web-Service 104 6.1 Der Formular-Manager über read() zu kontaktieren. Eventuelle Konflikte, die einen Transaktionsabbruch bewirken, können in diesem Fall natürlich nicht direkt ermittelt werden. Das tfInput-Objekt Das tfInput-Objekt eines Eingabeelements muss neben den beiden Kommunikationsmethoden read() und write() folgende Variablen beinhalten: value / oldvalue: Hier wird der aktuelle Inhalt des Formulars und der Inhalt vor der Bearbeitung gespeichert. So kann ermittelt werden, ob der Benutzer überhaupt etwas verändert hat, wenn das Element den Bearbeitungsfokus verliert. type: Der Typ ist über einen regulären Ausdruck festgelegt. Es gibt vordefinierte Typen wie beispielsweise Integer, String oder Datum. Der Typ kann entweder in der Formulardefinition angegeben werden oder über einen Zugriff auf den Web-Service ermittelt werden. Ein Schreibzugriff wird nur ausgelöst, wenn der Typ bzw. dessen regulärer Ausdruck erfüllt ist. xpath: Enthält das Datenobjekt, auf das zugegriffen wird. visual: Legt die Visualisierung fest, beispielsweise über Schieberegler oder Textfelder. Visualisierung von unterschiedlichen Formularelementen Für die konkrete Umsetzung dieser Visualisierungen der Formularelemente in Browsern gibt es verschiedene Möglichkeiten. Oft können direkt entsprechende HTML-Elemente wie Eingabefelder oder Auswahlboxen dazu eingesetzt werden. Sie sind gut in das DOM-Modell der Webseite integriert und unterstützen die nötigen Events, über die Methoden des tfInput-Objekts aufgerufen werden können. Manche Visualisierungen wie Schieberegler haben keine direkten Entsprechungen als HTML-Formularelemente. Sie müssen aus anderen HTML-Elementen mit Hilfe von JavaScript zusammengesetzt werden. 6.1.3 Formular-Definition Der Übersichtlichkeit halber beschränken wir uns bei der Beschreibung der Tag-Syntax auf diejenigen Tags, die für den elementaren Ablauf einer Formularbearbeitung notwendig sind. Wir verwenden für TransForm-Tags den eigenen Namensraum tf. Unsere Tags sind so grundsätzlich als nicht-HTML-Tags gekennzeichnet und unterscheiden sich auch automatisch von eventuell gleichnamigen HTML-Elementen. <tf:form service=’url’ protocol=’prot’>...</tf:form> Diesem Tag kommt die entscheidende Bedeutung bei der Formulardefinition zu, da es genau wie ein HTML-Form-Tag alle weiteren Formularbestandteile wie Eingabefelder oder Buttons zwischen seinem öffnenden und schließenden Tag enthält. Es kann an beliebiger Stelle im Dokument platziert werden und neben TransForm-Tags auch 105 Kapitel 6 Formulare HTML-Tags für das Layout des Formulars enthalten. Da es einem tfForm-Objekt entspricht lassen sich in den Attributen auch dessen globale Parameter und Variablen festlegen. Neben den obligatorischen Attributen service und protocol kann es auch Attribute enthalten, mit denen eventuell schon serverseitig erzeugte globale Variablen dem Formular übergeben werden. service: Dieses Attribut enthält die URL des Web-Service. protocol: Dieses Attribut legt das Scheduling-Protokoll fest, das zum Einsatz kommen soll. Sollte es vom Web-Service nicht unterstützt werden, kann keine Transaktion durchgeführt werden. auth: Es enthält die ID des Login-Tags, das zur Authentifikation verwendet werden soll oder „none“, falls der Dienst anonym verwendet werden soll. id: Wenn die ID nicht explizit als Attribut angegeben ist, wird sie als Hashwert berechnet. Sie dient im Wesentlichen der Identifizierung des Cookies. tid: Über dieses Attribut kann die ID einer aktiven Transaktion an ein Formular weitergegeben werden. session: Über dieses Attribut kann dem Formular eine Session-ID übergeben werden. distributed: Dieses Attribut enthält die ID eines <tf:coord>-Tags, wenn das Formular Teil einer verteilten Transaktion sein soll. <tf:input xpath=’expression’ /> Dieses Tag erzeugt ein Eingabeelement. Das einzige obligatorische Attribut ist xpath, über das festgelegt wird, auf welches Datenobjekt zugegriffen werden soll. Folgende optionale Attribute können in der Tagdefinition enthalten sein: value: Über dieses Attribut kann der Ausgangswert spezifiziert werden, der dann nicht explizit über einen Lesezugriff ausgelesen werden muss. type: Dieses Attribut ordnet dem Formularelement einen Typ zu, dem der Wert genügen muss, damit er an den Web-Service zum Schreiben übermittelt wird. visual: Dieses Attribut legt die visuelle Gestaltung des Elements fest. Wenn kein Attributwert festgelegt ist, wird das Formularelement als HTML-Eingabeelement dargestellt. Weitere Möglichkeiten sind beispielsweise slider für einen Schieberegler. In Abhängigkeit von der Visualisierung sind weitere Parameter möglich. Ein Schieberegler benötigt beispielsweise Minimal- und Maximalwerte. style: Über dieses Attribut können CSS-Formatierungen angegeben werden. Diese werden an die tatsächlich erzeugten Elemente weitergereicht. <tf:begin/> Dieses Tag definiert die Regeln für den Transaktionsstart. Dieser kann automatisch erfolgen. Es kann aber auch explizit ein Button bereitgestellt werden, über den der Transaktionsstart vom Benutzer ausgelöst werden muss. Dieses Tag muss nicht verpflichtend in einem <tf:form>-Tag enthalten sein. Es wird dann automatisch zu Be- 106 6.1 Der Formular-Manager ginn und nach jedem Commit eine neue Transaktion gestartet. Folgende Attribute können in der Tagdefinition enthalten sein: label: Dieses Attribut legt die Beschriftung des Buttons fest. type: Dieses Attribut legt fest, ob ein Button erzeugt wird (type=’button’) oder nicht (type=’hidden’). autostart: Dieses Attribut legt fest, ob automatisch ein Transaktionsstart durchgeführt werden soll. <tf:abort/> Über dieses Tag lassen sich Regeln für die Handhabung von Transaktionsabbrüchen festlegen. Auch dieses Tag ist nicht verpflichtend. Eventuell erzeugt es einen Button, über den die aktuelle Transaktion explizit abgebrochen werden kann. label: Dieses Attribut legt die Beschriftung des Buttons fest. type: Dieses Attribut legt fest, ob ein Button erzeugt wird (type=’button’) oder nicht (type=’hidden’). onconf: Hier kann die Behandlung von Konflikten festgelegt werden. abort ist der Defaultwert und bewirkt den Abbruch der Transaktion. ignore überlässt die Entscheidung dem Benutzer und ist deshalb nur sinnvoll in Kombination mit einem expliziten Button. restart: Über dieses Attribut kann festgelegt werden, ob im Falle eines Abbruchs sofort eine neue Transaktion gestartet wird. <tf:commit/> Dieses Tag muss verpflichtend in jeder Formulardefinition enthalten sein. Es erzeugt immer einen Button, über den der Transaktionsabschluss anfordert wird. label: Dieses Attribut legt die Beschriftung des Buttons fest. type: Dieses Attribut legt die Art des Buttons fest. Der bisher einzig erlaube Wert ist ’button’. restart: Dieses Attribut legt das Verhalten nach einem erfolgreichen Transaktionsabschluss fest. true erzeugt automatisch eine neue Transaktion. Der Inhalt bzw. das Aussehen von Buttons kann wie bei HTML-Buttons auch im Elementinhalt festgelegt werden. Ein eventuelles label-Attribut wird dadurch allerdings überschrieben. Neben solchen Formatierungsinformationen können aber auch noch <tf:message>-Tags enthalten sein, in denen für Rückgabe-Codes des Web-Service Nachrichten hinterlegt werden können, die dem Benutzer angezeigt werden. <tf:message status=’statuscode’> Nachrichtentext </tf:message> Über das status-Attribut wird der Rückgabewert angegeben, für den die Nachricht Nachrichtentext angezeigt werden soll. Es kann auch eine Wildcard in Form des Sterns 107 Kapitel 6 Formulare ’*’ im status-Attribut hinterlegt sein, das dann für alle Rückgabecodes gilt. Im Normalfall sind mehrere solche Tags hintereinander definiert, von denen dann das erste mit passendem status-Attribut dargestellt wird. <tf:messages> </tf:messages> Dieses Tag definiert ein allgemeines Nachrichtenfeld für ein Formular, über das Benutzern Ergebnisse von Transaktionskontrolloperationen mitgeteilt werden, wenn keine entsprechenden <tf:message>-Tags definiert sind. <login id=’id’ service=’url’ /> Dieses Tag dient der Authentifizierung und entspricht einem tfAuth-Objekt. Es greift zur Benutzerauthentifizierung auf den Dienst an der im service-Attribut angegebenen URL zu. Die id ist nur notwendig, wenn mehrerer solcher Tags in einer Seite definiert sind. Dann kann über diese ID eine Formular mit dem tfAuth-Objekt verbunden werden. <tf:coord id=’id’/> Mit diesem Tag lassen sich verschiedene Formulare einer Seite zu einer verteilten Transaktionen zusammenfassen. Er definiert einen Button, mit dem das globale Commit des 2PC-Protokolls eingeleitet wird. Es bezieht sich auf diejenigen Formulare, die in ihrem Attribut distributed die id des Tags angegeben haben und kann an beliebiger Stelle im Dokument auftreten. Es entspricht dabei einem tfCoord-Objekt. 6.1.4 Implementierung Das größte Problem bei der Implementierung ist die Handhabung der TransForm-Tags in den unterschiedlichen Browsern. Diese kann sogar je nach verwendeter DTD der Webseite innerhalb eines Browsers unterschiedlich ausfallen. Da es sich um keine Standard-Tags handelt, sollten die Tags ignoriert und nicht dargestellt werden, was auch in allen Browsern so umgesetzt wird. Allerdings gibt es erhebliche Unterschiede bei der Integration in das DOM-Modell der Seite. Eigentlich sollten die Tags als generische Elemente oder Knoten zur Verfügung gestellt werden und zumindest deren Methoden korrekt umsetzen. Das ist aber leider nicht immer der Fall. Auch treten immer wieder Fehler der DOM-Implementierungen der Browser zutage. So ignoriert Mozilla beispielsweise TransForm-Tags, die als direkte Geschwister definiert sind, fügt sie aber korrekt in das DOM-Modell ein, wenn zwischen zwei TransForm-Tags HTML-Tags eingefügt werden. Der Internet Explorer kommt beispielsweise mit der Schachtelung der Tags nicht zurecht und behandelt schließende Tags als eigenständige Knoten im DOM-Modell. Man kann sich aber behelfen, indem man TransForm-Tags nicht wie bisher vorgesehen als <tf:tagname> schreibt, sondern durch ein HTML-Element ersetzt, das von Browsern nicht 108 6.2 Von Formularen zu Webanwendungen dargestellt wird, wie es beispielsweise bei <span> oder <div> der Fall ist. Der Name der TransForm-Tags wird dann in ein Attribut ausgelagert: <div type=’tagname’>. Alle weiteren Attribute der TransForm-Tags bleiben unverändert. Obwohl auch diese Vorgehensweise dem Standard widerspricht, gibt es hier kaum Probleme bei den verschiedenen Browsern. Im Gegensatz dazu machen die HTTP-Anfragen wesentlich weniger Probleme und sind mittlerweile browserübergreifend sehr gut unterstützt. 6.2 Von Formularen zu Webanwendungen Will man TransForm nicht nur für den Datenzugriff verwenden, sondern komplette Anwendungen ermöglichen, muss der bisher vorgestellte Formularbegriff um zusätzliche Konzepte erweitert werden. Wir wollen nun zunächst einige dieser Konzepte und entsprechende Tags zur Umsetzung vorstellen und anschließend als Anwendungsbeispiel ein Frontend für das in Abschnitt 4.3 vorgestellte Reservierungs-Backend entwickeln. 6.2.1 Erweiterter Formularbegriff Wir brauchen neben dem Datenzugriff eine Möglichkeit, die Anwendung zu strukturieren und in Teilbereiche zu zerlegen. Dazu müssen Teile der Seite dynamisch verändert werden, also Seitenbereiche dynamisch nachgeladen werden können. Im einfachsten Fall wird direkt HTML ausgeliefert und kann über das DOM-Modell in die Seite integriert werden. Das ausgelieferte HTML kann weitere TransForm-Tags mit Formularen oder Formularelementen enthalten, die über den Controller initialisiert werden. Wenn der Web-Service nicht HTML sondern XML ausliefert, muss im Formular noch eine Umwandlung in HTML erfolgen. Das kann beispielsweise über XSL-Templates erreicht werden. Der dynamische Bereich der Webseite ist dabei über ein Tag definiert und wird über eine read-Operation auf einen XPath-Ausdruck nachgeladen. Web2.0 Dienste Durch solche dynamisch erzeugten Seitenbereiche mit nachgeladenen TransForm-Tags können ganze Formulardefinitionen bzw. Anwendungen erstellt und mit einem Tag in eine Webseite integriert werden. Dazu sind die Tags <tf:taglet> und </tf:formlet> vorgesehen. <tf:formlet> Formlets sind Formulare, die ihren Inhalt erst über den Webservice laden, auf den sie zugreifen. Dazu muss dieser in der Antwort der Begin-Operation den Seiteninhalt einschließen. Die Parameter sind die gleichen wie bei <tf:form>-Tags. Als Elementinhalt kann ein XSL-Template hinterlegt sein, wenn der Dienst XML ausliefert. Sie sind also immer mit einem Datendienst verknüpft und definieren eine Transaktion. 109 Kapitel 6 Formulare <tf:taglet> Taglets stehen im Gegensatz zu Formlets auf der Ebene von Formularelementen und sind deshalb mit XPath-Ausdrücken verknüpft. Sie ermitteln den Seiteninhalt über Lesezugriffe auf die XPath-Ausdrücke und werden dazu benutzt, Teile einer Formulardefinition dynamisch zu laden. Sie greifen dabei auf die URL des Formulars zu, in dem sie definiert sind. Sie sind insbesondere in Kombination mit Ankern für Anwendungen interessant. Anker Über Anker lassen sich XPath-Ausdrücke in Abhängigkeiten von anderen Formularelementen definieren. So kann beispielsweise der XPath-Ausdruck eines <tf:taglet>-Tags von einem Anker abhängig sein. Jedesmal, wenn sich der Anker und somit der XPath-Ausdruck ändert, wird der Lesezugriff auf diesen XPath-Ausdruck wiederholt und die Seite aktualisiert. Ein Anker ist eine Variable, die den Zugriff auf einen XPath-Ausdruck unter dem Variablennamen innerhalb der Webseite anbietet. Anker sind dabei immer XPath-Ausdrücke, die als Präfix anderer XPath-Ausrücke verwendet werden und deren Name für den Ausdruck steht: Ankername/weiter/gehender/xpath/ausdruck Der aktuelle Wert eines über einen Anker definierten XPath-Ausdrucks kann über ${ankername} ermittelt und in anderen Ausdrücken verwendet werden. Werte abgeleiteter XPathAusdrücke können nach dem gleichen Muster zur Verfügung gestellt werden: ${Ankername/weiter/gehender/xpath/ausdruck} Auswahlboxen & Menüstrukturen Für das Belegen eines Ankers mit einem konkreten XPath-Ausdruck stehen Auswahlboxen und Menüs zur Verfügung. Dazu wird beispielsweise über ein <tf:menu>-Tag ein Menü als Ankerpunkt definiert. Der Name eines solchen Ankers wird dabei durch einen TagParameter festgelegt: <tf:menu anchor=”name” >. Menüeinträge werden über <tf:item>Tags festgelegt, die einen XPath-Ausdruck als Attribut enthalten. Wenn der Benutzer einen Menüeintrag auswählt, wird der Anker mit dem hinterlegten XPath-Ausdruck belegt. Menüeinträge können verschachtelt sein. Der Controller stellt Menüs über HTML-Listen dar. Eventuell enthaltene CSS-Informationen werden an die erzeugten Listen weitergereicht. Ein Tag <tf:select xpath=”xpath” anchor=”anker” label=”beschriftung”> definiert eine Auswahlbox, die über den XPath-Ausdruck xpath eine Liste von XML-Elementen ermittelt und diese dem Benutzer zur Auswahl anbietet. Wenn der Benutzer einen Eintrag ausgewählt hat, wird der Anker anker mit dem entsprechenden XPath-Ausdruck belegt. Da dieses Tag im Wesentlichen einer HTML-Auswahlbox entspricht, benutzt der Controller auch für die Darstellung eine HTML-Auswahlbox. Über das label-Attribut lässt sich die Beschriftung 110 6.2 Von Formularen zu Webanwendungen der Einträge festlegen. Da natürlich für jeden Eintrag eine andere Beschriftung verwendet werden sollte, können Abhängigkeiten vom jeweiligen Anker eines Eintrags über Platzhalter in Form von ${Anker/xpath} erzeugt werden. Anker/xpath steht dabei für einen von dem Anker abhängigen XPath-Ausdruck, dessen Wert anstelle des Platzhalters eingesetzt wird. Anker sind erst definiert, wenn der Benutzer eine Auswahl getroffen hat. Bis dahin sind alle davon abhängigen Elemente undefiniert. Ein <tf:undef>-Tag enthält ein HTMLFragment, das nur dargestellt wird, wenn ein Anker noch nicht definiert ist. Es kann deshalb dazu verwendet werden, Benutzer auf den Anker aufmerksam zu machen. 6.2.2 Kinoreservierung als Anwendungsbeispiel Wir wollen zur Veranschaulichung diese neu vorgestellten Tags in einer Beispielanwendung verwenden. Als Grundlage dient dabei das Platzreservierungs-Backend aus Abschnitt 4.3, für das wir nun ein Frontend zusammenstellen wollen. Die Anwendung benötigt zunächst ein Menü, über das eine Vorstellung ausgewählt werden kann. Dafür definieren wir ein <tf:menu>-Tag mit den Anker vorstAnker und für jede Vorstellung ein <tf:item>-Tag. <tf:menu anchor="vorstAnker"> <tf:item xpath="/kino/vorstellung[id=’234’]">Night On Earth (20h)</tf:item> <tf:item xpath="/kino/vorstellung[id=’235’]">Star Wars (20:30h)</tf:item> ... </tf:menu> Wenn ein Menüeintrag ausgewählt wird, ist der Anker vorstAnker mit dem XPath-Ausdruck des entsprechenden Eintrags belegt. Alternativ hätten wir die Auswahl der Vorstellungen auch über den Dienst auslesen und den Anker über ein <tf:select>-Tag definieren können. Die Liste der verschiedenen Vorstellungen wäre dabei über den Ausdruck /kino/vorstellung ermittelt worden, der eine Liste von Vorstellung-Elementen aus Abbildung 4.6 ohne deren Kindelemente zurückliefert. Der Anker vorstAnker steht dabei für das jeweilige XML-Element der Vorstellung, dessen Attribute dann in Abhängigkeit davon ausgelesen werden können. Die Beschriftung im labelAttribut wird dann in Abhängigkeit des Filmtitels (${vorstAnker/@film}) und der Uhrzeit (${vorstAnker/@uhrzeit}) definiert. <tf: select xpath="/kino/vorstellung/" anchor="vorstAnker" label="${vorstAnker/@film} um ${vorstAnker/@uhrzeit} Uhr" /> Egal ob der Anker über ein Menü oder über eine Auswahlbox definiert wird, ist er zunächst noch undefiniert. Über ein undef-Tag legen wir deshalb ein HTML-Fragment fest, das angezeigt wird, wenn noch keine Vorstellung ausgewählt ist: 111 Kapitel 6 Formulare Abbildung 6.3: Ein Screenshot des Kino-Reservierungs-Systems. <tf:undef anchor="vorstAnker"> <div>Bitte w&auml;hlen Sie eine Vorstellung aus</div> </tf:undef> Wenn der Benutzer eine Vorstellung ausgewählt hat, ist der Anker aktiv und zeigt auf das entsprechende XML-Element der Vorstellung. Um die Übersicht des Saals anzuzeigen, muss zunächst die HTML-Tabelle über einen XPath-Ausdruck /kino/saal[id=’saalid’] angefordert werden. Die saalid können wir über den Anker bestimmen: ${vorstAnker/@saal} <tf: taglet xpath="/kino/saal[id=’${vorstAnker/@saal}’]" /> Das <tf:taglet>-Tag setzt die saalid in den XPath-Ausdruck ein und bindet die zurückgelieferte HTML-Tabelle (siehe Abschnitt 4.3) als Kind im DOM-Baum ein und wiederholt diese Prozedur, wenn sich der Anker ändern sollte, weil der Benutzer eine andere Vorstellung ausgewählt hat. Diese HTML-Tabelle enthält wiederum <tf:checkbox>-Tags, die über einen von dem Anker vorstAnker abhängigen XPath-Ausdruck vorstAnker/platz[id=’platzid’]/reserviert ausgeliefert werden. Da dieser Anker jetzt auf eine Vorstellung zeigt, deuten diese Ausdrücke auf Plätze dieser Vorstellung (siehe Abbildung 4.6). Diese <tf:checkbox>-Tags werden durch HTML-Checkboxen dargestellt und lesen zunächst über obigen Ausdruck den Reservierungsstatus des Platzes aus. Der Web-Service liefert je nach Reservierungsstatus entweder true oder false aus. Abbildung 6.3 zeigt unser Anwendungsfrontend. Ein Belegungsplan für eine Kinovorstellung ist dort neben dem Menü auf der linken Seite zu sehen. Reservierte Plätze sind über inaktive Checkboxen dargestellt, während bei verfügbaren Plätzen die Möglichkeit besteht, einen Haken zu setzen. Ein solcher gesetzter Haken führt zu einem Schreibzugriff auf den XPath-Ausdruck, über den ein Platz für den angemeldeten Benutzer vorgemerkt werden kann. Obwohl in der Abbildung der Anmeldestatus nicht zu sehen ist, muss für den Zugriff 112 6.2 Von Formularen zu Webanwendungen auf den Dienst eine Benutzersession aktiv sein, über die der Dienst die Reservierung einem Benutzer zuordnen kann. Wir müssen das <tf:taglet>-Tag noch in ein Formular einschließen und einen Button für den Transaktionsabschluss sowie Benachrichtigungsfelder für die Benutzer definieren. <tf:form service="tf.net/kino" protocol="reservierung"> <tf: taglet xpath="/kino/saal[id=’${vorstAnker/@saal}’]" /> <tf:commit type="button" label="Reservieren"> <tf:message status="ok">Die Reservierung war erfolgreich.</tf:message> <tf:message status="∗">Es gab ein Problem bei der Reservierung</tf:message> </tf:commit> </tf:form> Ein Klick auf den Button mit der Aufschrift „reservieren“ fordert den Transaktionsabschluss an, dessen Rückgabestatus dem Benutzer über die enthaltenen <tf:message>-Tags mitgeteilt wird. Sollte der Commit erfolgreich sein, wird die Nachricht mit dem status-Attribut „ok“ angezeigt. Ansonsten wird die zweite Nachricht angezeigt. 113 Kapitel 7 Evaluierung Eines der wichtigsten Evaluierungskriterien eines Systems ist üblicherweise eine Auswertung der Performance in Relation zu vergleichbaren Systemen. Leider ist das in Ermangelung direkt vergleichbarer Konkurrenten nicht möglich. Systeme wie beispielsweise JPernLite [YK99] scheiden aufgrund einer völlig anderen Systemarchitektur aus. Da wir Performance-Einbußen bewusst in Kauf genommen haben, um TransForm in einer Standard-Web-Infrastruktur möglich zu machen, bietet sich allerdings der Vergleich zu Web-Anwendungen an, die den herkömmlichen Formularverarbeitungsmechanismus in der gleichen Infrastruktur einsetzen. Da hier entweder keine oder eine sehr eingeschränkte Nebenläufigkeitskontrolle zum Einsatz kommt, ist dieser Vergleich natürlich nicht ganz fair. In Abschnitt 7.1 ermitteln wir so den Overhead, den TransForm-Formulare im Vergleich zu HTML-Formularen mit sich bringen. Die grundsätzliche Korrektheit unseres Systems wurde in Kapitel 3 gezeigt. Um das System einem Praxistest unterziehen zu können, haben wir einen Prototypen implementiert, der alle dort für die Korrektheit und die Garantie der ACID-Eigenschaften geforderten Konzepte umsetzt. Fehlersituationen wie Netzwerkausfälle oder Abstürze von Komponenten konnten so simuliert und deren Behandlung und Wiederherstellungsstrategien getestet werden. Studierendenarbeiten Die generelle Eignung unseres Konzepts für die Webanwendungsentwicklung kann aber nur nachgewiesen werden, indem sich das System in der Praxis bewährt. Um diese Praxistauglichkeit zu evaluieren, wurden jeweils unterschiedliche Teilaspekte unseres Konzepts in Studierendenarbeiten untersucht und in unterschiedlichen Komponenten implementiert. Die Diplomarbeit [And07] diente als Proof-of-Concept für TransForm. Dazu wurde eine datenbankgestützte kommerzielle Web-Anwendung als TransForm-Anwendung reimplementiert. Sowohl die Datenbank als auch die Anwendungslogik wurden in einen WebService gekapselt und Formularelemente für alle Web-Service-Zugriffe bereitgestellt. Beispielsweise wurden in Anlehnung an die Taglets aus dem letzten Kapitel Formularelemente implementiert, die XML-Fragmente über Templates in darstellbares HTML wandeln und 114 7.1 Performance in die Seite einbinden. Transaktionen erstrecken sich über eine komplette Anwendungssitzung. In [Mar07] wurde das Dateisystem-basierte Backend aus Abschnitt 4.4 als Web-Service für den Zugriff auf MP3-Dateien umgesetzt. Hier wurde eine relationale Datenbank als Cache für die in den MP3-Tags enthaltenen Metadaten eingesetzt, um Anfragen auf diesen Metadaten zu ermöglichen. Auch hier wurden für den Zugriff auf den Service spezielle Formularelemente entwickelt, beispielsweise für die Navigation in der Interpret-AlbumSong-Hierarchie. Für das Abspielen der MP3-Dateien im Browser wurde eine Flash-basierte Lösung gefunden. In der Studienarbeit [Sor07] wurde das generische relationale Backend aus Kapitel 4.2 implementiert. In einem Studierendenprojekt wurden die verteilten Aspekte von TransForm untersucht. Dazu wurde ein Wett-System entwickelt, bei dem auf bestimmte Ereignisse über einen ersten TransForm-Dienst Wetten abgegeben werden können. Quoten werden über das Web von Internet-Wettanbietern ermittelt und über einen zweiten TransForm-Service zur Verfügung gestellt. Die verteilten Transaktionen stellen nun sicher, dass die Quoten bei Tippabgabe noch aktuell sind. Es wurden auch hier maßgeschneiderte Formularelemente entwickelt. Evaluierung unterschiedlicher Komponenten Ein Quervergleich der Performance-Eigenschaften verschiedener Komponenten erscheint uns weder bei Schedulern noch bei Backends sinnvoll. Da unsere bisherigen Backends alle für unterschiedliche Einsatzzwecke entworfen wurden, ist ein direkter Vergleich nicht möglich. Die grundsätzlichen Performance-Eigenschaften unserer Schedulingprotokolle sind in der Literatur untersucht [ACL87, Tho98]. Es ist bekannt, welche Scheduler für welche Situationen geeignet sind. 7.1 Performance Die Performance von Webanwendungen hängt im Wesentlichen davon ab wie schnell Anfragen verarbeitet werden, da diese für alle Clients zentral verarbeitet werden. Die Rechenzeit im Browser ist normalerweise vernachlässigbar, da dieser nur einen Client bedient und für die Gesamtperformance keine Rolle spielt. Browser warten die meiste Zeit und nehmen nur ab und an Kontakt zu einem Webserver auf, um eine neue Seite anzufordern. Die Zeitspanne vom Absenden der Anfrage bis zum Eintreffen der Antwort ist also ein wesentlicher Faktor und bestimmt die Reaktivität einer Webanwendung. Neben nicht beeinflussbaren Parametern wie Hardwareausstattung oder Netzwerkauslastung ist die Reaktivität eng mit der Belastung des Webservers verknüpft. Je höher die Belastung desto langsamer ist die durchschnittliche Antwortzeit. Im Allgemeinen hängt die Belastung eines Webservers von zwei Faktoren ab. 115 Kapitel 7 Evaluierung 1. Anzahl der gleichzeitigen Anfragen: Ein Webserver kann nur eine gewisse Anzahl von Anfragen gleichzeitig beantworten. Wenn mehr angefordert wird, kommt es zu Verzögerungen und eventuell zu Verbindungsabbrüchen. 2. Komplexität der Anfragen: Je komplexer die Abarbeitung einer Anfrage ist, desto mehr Serverzeit wird benötigt. Am einfachsten sind statische Webseiten. Neben Datenbankzugriffen und anderen I/O-Zugriffen wird diese Serverzeit auch durch Berechnungen beeinflusst. Wir müssen deshalb die Auswirkungen der TransForm-Architektur auf die Belastung des Webservers im Vergleich zu klassischen Webanwendungen untersuchen. Vergleich von TransForm-basierten und herkömmlichen Webanwendungen Im Vergleich zu TransForm-Anwendungen kommen herkömmliche Webanwendung mit wesentlich weniger Serverzugriffen aus. Sie nehmen erst Kontakt zum Server auf, wenn die Formularbearbeitung abgeschlossen werden soll und übergeben dazu dem Webserver alle neuen Werte auf einen Schlag. Bei TransForm-Anwendungen erfordert jeder einzelne Schritt der Formularverarbeitung separate Anfragen. Wenn man das Commit mit dem Absenden des Formular vergleicht, wird zumindest eine zusätzliche Anfrage für Begin benötigt, in der eventuell die Initialwerte der Formularfelder ermittelt werden. Je nach Aktivität des Benutzers fallen weitere Anfragen für Lese- bzw. Schreibzugriffe an. Standardanwendungen Um diese beiden Szenarien miteinander vergleichen zu können, haben wir zwei Standardanwendungen für unsere Auswertung definiert. Beide Anwendungen sind reduziert auf die Formularverarbeitung und enthalten keine Menüstrukturen oder Ähnliches. Die Zugriffe belasten also im Wesentlichen die Datenbank, da keine intensiven Berechnungen durchgeführt werden. Auch ist die Größe der Rückgabe minimal gehalten und auf die Formulardefinitionen reduziert. Die Anwendung für die herkömmliche Formularverarbeitung besteht aus zwei Anfragen. Die erste liest die Ausgangswerte aus der Datenbank (GET) und erzeugt eine HTML-Seite mit den Formulardefinitionen, während die zweite Anfrage (POST) die übertragenen Formularinhalte überprüft, gegebenenfalls in die Datenbank schreibt und eine Webseite mit den Ergebnissen ausliefert. Die erzeugten Seiten enthalten neben den Formulardefinitionen lediglich ein minimales HTML-Gerüst. Die zweite Anwendung für die TransForm-Formularverarbeitung besteht aus einer Webseite mit den Formularen. Unser Ablauf sieht neben dem obligatorischen Begin, in dem keine Ausgangswerte ausgelesen werden, und Commit noch für jedes Formularelement einen Lese- und einen Schreibzugriff vor. Die Anzahl der Anfragen hängt also von der Anzahl der Formularelemente ab. 116 7.1 Performance Subjektivität der Performance-Beurteilung Obwohl TransForm mit seinem Verarbeitungsmechanismus eine höhere Serverlast erzeugt als der herkömmliche Verarbeitungsmechanismus, kann der Eindruck einer höheren Performance entstehen. Dieser Effekt tritt vor allem bei einer geringen Serverauslastung ein, wenn also alle Anfragen direkt beantwortet werden können und hat im Wesentlichen zwei Gründe. Die „gefühlte“ Performance im Browser wird vor allem über die Reaktivität beeinflusst und TransForm-Anfragen können ihrer geringen Komplexität wegen schnell beantwortet werden. Aber auch die Tatsache, dass Anfragen im Hintergrund durchgeführt werden ohne den Browser zu blockieren trägt zu diesem Effekt bei. Allerdings wird eine Serverlast, bei der die Anfrageausführung merklich verzögert ist, schon mit weniger Formularverarbeitungen erreicht als bei der herkömmlichen Variante. 7.1.1 Test Setup Wir wollen die durchschnittlichen Antwortzeiten des Webservers für beide Standard-Anwendungen in Abhängigkeit von zwei Parametern messen. 1. Anzahl der Formularelemente: Je mehr Formularfelder zu verarbeiten sind, desto größer ist der erwartete Overhead der TransForm-Architektur. 2. Anzahl der gleichzeitigen Zugriffe: Je mehr Zugriffe gleichzeitig also parallel von verschiedenen Benutzern erfolgen, desto höher ist die Serverlast. Wir erwarten einen schnelleren Anstieg der Serverlast bei TransForm. Dabei wollen wir messen, wieviele Anfragen der Webserver unter den verschiedenen Szenarien in der Minute bewältigt, bzw. wieviele Formulare durch diese Anfragen verarbeitet werden. Dazu haben wir beide Standardanwendungen als PHP-Skript implementiert: 1. WASubmitForm.php: Dieses Skript erzeugt zunächst eine Seite mit einem Formular und liest die Initialwerte der einzelnen Formularfelder aus der Datenbank. Die Anzahl der Formularfelder kann über die HTTP-Variable formulare festgelegt werden. Der Absendemechanismus des Formulars zeigt auf dasselbe Skript und übergibt dabei alle Formularwerte als POST-Variablen. Wenn dem Skript-Aufruf Werte von Formularfeldern als Parameter übergeben werden, werden diese zunächst in die Datenbank übertragen. Anschließend wird das Formular mit den neuen Werten dem Benutzer wieder angezeigt. 2. WATransForm.php: Bei diesem Skript handelt es sich um einen TransForm-Service, der speziell für die Testläufe angepasst wurde. Als Backend kommt dabei das allgemeine relationale Backend aus Kapitel 4.2 zum Einsatz, allerdings mit der Einschränkung auf die einfache Sicht der Datenbank und einer Konflikterkennung auf Basis 117 Kapitel 7 Evaluierung von ID-Attributen in den XPath-Anfragen. Als Scheduler wird das optimistische Protokoll mit einer kleinen Anpassung verwendet. Eine nicht erfolgreich validierende Transaktion bricht sich selbst ab und nicht die in Konflikt stehenden Transaktionen. So können wir nach Versuchsende erkennen, ob alle Transaktionen zu Ende gebracht wurden (Transaktions-Status Abort/Commit) oder nicht (Running). Es spielt dabei keine Rolle, ob eine Transaktion erfolgreich abgeschlossen wird oder nicht. Es muss nur sichergestellt sein, dass alle Transaktionen abgeschlossen wurden. Lasttest-Software Alle Tests wurden mit dem Open-Source-Tool OpenSTA1 durchgeführt, das aus einer kommerziellen Test-Architektur für Lasttests von HTTP-Servern hervorgegangen ist. Testszenarien lassen sich mittels Skripten erstellen, die durch eine beliebige Anzahl von virtuellen Benutzern ausgeführt werden. Skripte werden in einer speziellen Sprache geschrieben, die neben HTTP-Anfragen als Primitiven Variablen und Kontrollstrukturen bereitstellt. Zur Skripterstellung kann ein Aufnahmemechanismus verwendet werden. Dazu wird OpenSTA als Proxy des Browsers eingerichtet, dessen HTTP-Verkehr dann protokolliert und in Primitiven der Skriptsprache gespeichert wird. OpenSTA misst im Wesentlichen die Antwortzeiten und Rückgabecodes. Für die Auswertung der während der Testläufe gesammelten Daten werden verschiedene Statistiken als Graphen zur Verfügung gestellt, anhand derer wir während der Auswertung die Aussagekraft einer Messung beurteilen konnten. Die eigentlichen Messdaten bekommt man in Form einer Liste aller Anfragen, die unter anderem Dauer, Zeitpunkt und Rückgabewert enthält. Für die Durchführung der Testläufe haben wir OpenSTA-Skripte erstellt, die jeweils eines der beiden PHP-Skripte aufrufen. Die Anzahl der bearbeiteten Formularfelder lässt sich dabei als Parameter der Skriptabläufe festlegen. Für die Simulation von Formularfeldbearbeitungen werden zufällige Werte erzeugt. WATransForm-Skript: Die Anzahl der Formularelemente ist der einzige Parameter des Skripts. Nachdem es die Startseite erzeugt hat, fordert es nach einer Sekunde Verzögerung den Transaktionsbeginn an. Anschließend wird für jedes Formularelement wieder mit einer Sekunde Verzögerung jeweils ein Lese- und ein Schreibzugriff erzeugt. Anschließend wird über Commit der Transaktionsabschluss angefordert. 1sec 1sec 1sec 1sec Start-Seite −−→ Begin −−→ (Read −−→ Write −−→){#Elem. Wdh.} Commit Da es in der Skriptsprache von OpenSTA nicht möglich ist, die Transaktions-ID aus der HTTP-Antwort zu extrahieren, erzeugen wir diese mit Hilfe einer Zeitmarke und der Nummer des virtuellen Benutzers clientseitig und übergeben sie in der Begin-Operation dem Dienst. 1 Die Dokumentation und die Möglichkeit zum Download der Software ist auf der Projekt-Webseite zu finden unter http://www.opensta.org/ 118 7.1 Performance WASubmitForm-Skript: Neben der Anzahl der Formulare wird hier auch die Wartezeit zwischen den beiden Aufrufen als Skript-Parameter festgelegt. Delay GET(# Formularelemente) −−−−→ POST(# Formularelemente, Werte) 7.1.2 Testreihen Es wurden für beide Anwendungsszenarien jeweils drei Testreihen mit unterschiedlich vielen Formularelementen durchgeführt. WATransForm-Testreihen In je einer Testreihe wurde die Formularverarbeitung mit einem Formularfeld, mit 10 Formularfeldern sowie mit 100 Formularfeldern gemessen. In jeder Testreihe wurden Testläufe mit unterschiedlich vielen virtuellen Benutzern gemacht, angefangen mit nur einem Benutzer bis zu so vielen, wie das System verarbeiten konnte. Dabei wurden in jedem Testlauf 5 Iterationen des WATransForm-Tests mit je einer Sekunde Verzögerung durchgeführt. WASubmitForm-Testreihen Jeder WATransForm-Testreihe wurde eine WASubmitForm-Testreihe mit entsprechend vielen Formularen gegenübergestellt. Bei einem und 10 Formularfeldern wurde die Verzögerung zwischen den beiden Anfragen so gewählt, dass die Laufzeit der Testreihe der WATransForm-Testreihe entspricht. Das bedeutet 4 Sekunden Verzögerung bei einem Formularelement sowie 22 Sekunden Verzögerung bei 10 Formularelementen. Da auch hier jeweils 5 Iterationen in jedem Testlauf durchgeführt wurden, werden in jedem Testlauf genauso viele Formulare verarbeitet wie in dem entsprechenden WATransForm-Testlauf. Für die Messungen mit 100 Formularelementen wurde die Verzögerung zwischen den beiden Anfragen auf eine Sekunde reduziert, da bei den der Laufzeit von WATransForm entsprechenden 202 Sekunden Verzögerung die erzeugte Last zu gering ist und eine entsprechende Erhöhung der Anzahl der virtuellen Benutzer zu Instabilitäten in OpenSTA führte. Die Anzahl der Iterationen in der Messreihe wurde soweit erhöht, dass die Anzahl der Anfragen genauso groß ist wie bei der WATransForm-Testreihe. Eine Testreihe entspricht deshalb etwa hundertfach mehr Formularverarbeitungen als bei WATransForm. Abbildung 7.1 zeigt exemplarisch die Werte einer Messreihe mit drei Testdurchläufen. Die einzelnen Testläufe einer Testreihe unterscheiden sich durch die Anzahl der virtuellen Benutzer, die das Testskript jeweils gleichzeitig ausführen und eine steigende Last erzeugen. Die erste Spalte enthält die Anzahl der virtuellen Benutzer, die zweite Spalte gibt die durchschnittliche Dauer aller HTTP-Anfragen des Testlaufs an. Spalte 3 enthält die Anzahl der Anfragen, während die Dauer sowie die Anzahl der aufgetretenen Fehler des Testlaufs in den Spalten 4 und 5 gezeigt werden. 119 Kapitel 7 Evaluierung virtuelle Benutzer 1 5 10 Latenzzeit 235 270 550 Anfragen 200 1000 2000 Dauer 238 232 269 Fehler 0 0 0 Abbildung 7.1: Die Ergebnisse von Messreihen. Testumgebung Die Tests wurden auf zwei verschiedenen Rechnern durchgeführt. Als Client wurde OpenSTA auf einem PC mit Pentium IV 2,8 GHz und 1 Gb Hauptspeicher installiert. Als Betriebssystem kam Windows XP zum Einsatz, was für OpenSTA zwingend erforderlich ist. Als Server kam ein Linux-PC mit Pentium D 3GHz Prozessor und 1Gb Hauptspeicher zum Einsatz. Auf diesem Rechner lief sowohl ein Apache-Webserver mit PHP als auch ein PostgreSQLDatenbankserver. Der Server ist in der Hauptsache über I/O belastet, die CPU hatte während aller Tests Reserven und war nie bei 100%. 7.1.3 Ergebnisse der Latenzmessungen Da wir sowohl die durchschnittliche Dauer der einzelnen Anfragen als auch die Laufzeit der Testreihe und die dabei erzeugten Anfragen gemessen haben, können Latenzmessungen und Lastmessungen unterschieden werden. Wir haben jeweils die durchschnittlichen Latenzzeiten der beiden Anwendungsszenarien für die gleiche Anzahl an Formularelementen in einem Schaubild gegenübergestellt. In diesen Diagrammen (Abbildungen 7.2, 7.3 und 7.4) ist die durchschnittliche HTTPAnfragedauer in Abhängigkeit von der Anzahl der virtuellen Benutzer aufgetragen. Wir erwarten bei wenigen Benutzern eine niedrigere Latenzzeit für WATransForm, da der Webserver noch alle Anfragen problemlos beantworten kann und somit die geringere Komplexität der Anfragen zum Tragen kommen sollte. Mit steigender Belastung des Webservers sollte sich die höhere Zahl der generierten Anfragen allerdings bemerkbar machen. Testreihen mit einem Formularfeld Abbildung 7.2 zeigt die Messergebnisse der Messreihen mit einem Formularfeld. Es ist deutlich zu erkennen, dass die Latenzzeit der HTTP-Anfragen bei beiden Szenarien mit der Anzahl der virtuellen Benutzer ansteigt, da immer mehr Anfragen erzeugt werden und der Webserver die Anfragen nicht mehr direkt beantworten kann. WATransForm führt bei jeder Testreihe 25 Anfragen durch, währen WASubmitForm lediglich 10 Anfragen erzeugt. Obwohl man erwarten würde, dass die größere Anzahl von Anfragen bei WATransForm mit steigender Anzahl von Benutzern zu einer höheren Latenz führt, haben unsere Messungen gerade das Gegenteil ergeben. 120 7.1 Performance 1 Formular 25000 WATransForm WASubmitForm 4s Delay Durchschnittliche Latenz-Zeit 20000 15000 10000 5000 0 0 100 200 300 Virtuelle Benutzer 400 500 Abbildung 7.2: Die durchschnittliche HTTP-Anfragedauer bei Formularen mit einem Formularfeld. Die Erklärung liegt in der durchschnittlich höheren Komplexität der Anfragen bei WASubmitForm. Die Datenbankzugriffe sind bei beiden Szenarien vergleichbar, allerdings erzeugt WASubmitForm eine größere Ausgabe. Einen wesentlich größeren Einfluss besitzt hier allerdings die Startseite. Da diese bei WATransForm eine statische Seite ist, die ohne PHP-Interpreter ausgeliefert werden kann, erzeugt der Webserver bei wiederholten Anfragen einen Rückgabestatus 304 (not modified), der besagt, dass die Seite nicht verändert wurde und deshalb auch nicht ausgeliefert wird. Da hier jede fünfte Seite davon betroffen ist, wirkt sich das natürlich auf die durchschnittlichen Antwortzeiten aus. Je höher die Latenzzeiten mit der steigenden Anzahl von Benutzern werden, desto stärker wirkt sich dieser Effekt aus. Allerdings sind hier bei einem Formularfeld die Unterschiede gering. Testreihen mit 10 Formularfeldern Abbildung 7.3 zeigt Ergebnisse der Testreihen mit 10 Formularfeldern. Auch hier steigt die durchschnittliche Latenzzeit mit der Anzahl der virtuellen Benutzer. Allerdings ist hier die durchschnittliche Anfragedauer bei WATransForm höher, da hier schon 23 Anfragen für eine Formularverarbeitung notwendig sind. Bei WASubmitForm erhöht sich zwar die Komplexität der Anfragen, weil jetzt 10 Eingabefelder erzeugt, ausge- 121 Kapitel 7 Evaluierung 10 Formulare 30000 WATransForm WASubmitForm 22s Delay Durchschnittliche Latenz-Zeit 25000 20000 15000 10000 5000 0 0 50 100 150 200 250 300 Virtuelle Benutzer 350 400 450 500 Abbildung 7.3: Die durchschnittliche HTTP-Anfragedauer bei Formularen mit 10 Formularfeldern. lesen und geschrieben werden. Aber es sind weiterhin nur zwei HTTP-Anfragen für die Verarbeitung eines Formulars nötig. Da in dieser Testreihe der Abstand zwischen diesen beiden Anfragen 22 Sekunden betrug, wird der Webserver hier mit weniger Anfragen belastet. Die Anfragedichte ist also geringer. Bei WATransForm ließen sich keine Tests mit mehr als 100 virtuellen Benutzern durchführen, da diese konstant zum Absturz von OpenSTA führten. WASubmitForm konnte mit bis zu 500 virtuellen Benutzern gemessen werden. Testreihen mit 100 Formularfeldern Abbildung 7.4 zeigt Ergebnisse der Testreihen mit 100 Formularfeldern. Beide Testreihen erzeugen die gleiche Anzahl von Anfragen und haben die gleiche Laufzeit. Die Komplexität der Anfragen ist bei WASubmitForm im Vergleich zu WATransForm wesentlich höher, weil jetzt 100 Eingabefelder erzeugt, ausgelesen und geschrieben werden müssen. Das macht sich natürlich in der Latenzzeit bemerkbar. In der Abbildung ist deutlich zu sehen, dass die Anfragedauer bei WASubmitform deutlich schneller ansteigt. Interessanterweise ließen sich hier die teureren WASubmit-Tests mit mehr Benutzern durchführen als die WATransForm-Tests, bevor es zu einem Absturz von OpenSTA kam. 122 7.1 Performance 100 Formulare 25000 WATransForm WASubmitForm 1s Delay Durchschnittliche Latenz-Zeit 20000 15000 10000 5000 0 0 50 100 Virtuelle Benutzer 150 200 Abbildung 7.4: Die durchschnittliche HTTP-Anfragedauer bei Formularen mit 100 Formularfeldern. 7.1.4 Ergebnisse der Lastmessungen Abbildung 7.5 zeigt für die Testreihen mit einem Formularelement und mit 100 Formularelementen die Anzahl von Anfragen, die der Webserver pro Minute beantworten konnte. Die steigende Anzahl von virtuellen Benutzern zieht auch eine steigende Anzahl von Anfragen nach sich. Es ist deutlich zu erkennen, dass bei wenigen virtuellen Benutzern der Webserver nicht ausgelastet ist, da sich eine steigenden Anzahl von Anfragen noch auf die Anzahl der bewältigten Anfragen auswirkt. Ab einer bestimmten Anzahl von Benutzern ist die Anzahl der Anfragen aber höher als der Webserver beantworten kann. Dann ist sein Limit erreicht und die Anzahl der beantworteten Anfragen bleibt konstant oder nimmt sogar leicht ab. Wann das passiert, hängt von der Anfragefrequenz sowie der Komplexität der Anfragen ab. Bei den beiden WATransForm-Testreihen ist die Anzahl der bewältigten Anfragen am höchsten. Der Unterschied zwischen den beiden erklärt sich aus den wesentlich größeren Metadatentabellen die bei 100 Formularfeldern verwaltet werden sowie aus dem geringeren Anteil der statischen Startseiten. WASubmitForm liegt bei einem Formularelement nur wenig darunter. Der Unterschied lässt sich wie bei der Latenzmessung für ein Formularfeld aus den fehlenden statischen 123 Kapitel 7 Evaluierung Anfragen pro Minute 3500 WATransForm 100 Felder WASubmitForm 100 Felder WATransForm 1 Feld WASubmitForm 1 Feld 3000 Anfragen pro Minute 2500 2000 1500 1000 500 0 0 50 100 Virtuelle Benutzer 150 200 Abbildung 7.5: Die Anzahl der bewältigten Anfragen in der Minute. Webseiten erklären. Wie es zu erwarten war, bewältigt der Webserver bei WASubmitForm mit 100 Formularfeldern am wenigsten Anfragen in der Minute, da hier die Datenbank am intensivsten genutzt und die größte Antwort erzeugt wird. Anzahl der verarbeiteten Formulare Die Anzahl der bewältigten Anfragen pro Minute sagt zwar etwas über die Kosten der einzelnen Anfragen aus, allerdings interessieren wir uns eher für die Kosten einer kompletten Formularverarbeitung. Bei WATransForm entsprechen bei 100 Formularelementen 203 Anfragen einer Formularverarbeitung und bei einem Formularelement 5 Anfragen. Bei WASubmitForm sind in beiden Fällen 2 Anfragen für die Verarbeitung eines Formulars nötig. Abbildung 7.6 zeigt die Umrechnung in die Anzahl der verarbeitenden Formulare der Messungen aus Abbildung 7.5. So entsprechen den 500 bewältigten Anfragen von WASubmitForm bei 100 Formularfeldern immerhin 250 verarbeitete Formulare, während den 2200 Anfragen von WATransForm mit 100 Formularfeldern nur noch etwa 10 verarbeitete Formularen entsprechen. Der TransForm-Overhead liegt hier etwa bei dem Faktor 25. Bei den Messreihen mit einem Formularfeld ist der Unterschied geringer. Bei WATransForm ergeben sich aus 2700 Anfragen etwas mehr als 500 verarbeitete Formulare. Bei 124 7.1 Performance Formulare pro Minute 1000 WATransForm 100 Felder WASubmitForm 100 Felder, 1s Delay WATransForm 1 Feld WASubmitForm 1 Feld, 4s Delay Formulare pro Minute 800 600 400 200 0 0 50 100 Virtuelle Benutzer 150 200 Abbildung 7.6: Die Anzahl der verarbeiteten Formulare. WASubmitForm können immerhin gut 800 Formulare in der Minute verarbeitet werden. WATransForm verarbeitet bei einem Formularfeld etwa doppelt so viele Formulare wie WASubmitForm bei 100 Formularfeldern. 125 Kapitel 8 Fazit 8.1 Zusammenfassung Wir haben mit TransForm ein Framework geschaffen, mit dem Webanwendungen Formulare in Transaktionen verarbeiten können. Dazu haben wir die direkte Verbindung zur Datenbank durch einen Webservice ersetzt, der Aufträge für die Datenverarbeitung entgegennimmt und an die Datenbank weiterleitet. Er nimmt dabei sowohl die Rolle eines Transaktionsservers als auch die eines Wrappers für die Datenbank ein, da er Datenzugriffe in die Anfragesprache der Datenbank übersetzt und einzelne Datenzugriffe in Transaktionen zusammenfasst. Auf der anderen Seite haben wir auch HTML-Formulare durch spezielle TransFormFormulare ersetzt, die für die Präsentation und Bearbeitung der Daten im Browser verantwortlich sind und ähnlich wie normale HTML-Formulare über Tags im Markup einer Webseite definiert werden. Sie übergeben nicht mehr am Ende des Bearbeitungsprozesses alle Formularinhalte zur weiteren Verarbeitung dem Webserver, sondern leiten jeden einzelnen Bearbeitungsschritt zur direkten Verarbeitung an den Web-Service weiter. Diskussion der gesteckten Ziele Wir hatten schon bei der Konzeption unseres Systems konkrete Ziel im Hinterkopf, die wir auch alle erreichen konnten: 1. ACID-Garantien: Um die ACID-Eigenschaften für unsere Transaktionen garantieren zu können, haben wir ein an die Gegebenheiten des WWW angepasstes Transaktionsmodell entwickelt, das zusammen mit unserem Datenmodell alle Mittel bereitstellt, die Scheduler für die Gewährleistung der ACID-Eigenschaften benötigen. 2. Standard-Infrastruktur: Alle Komponenten lassen sich mit standardisierten und verbreiteten Technologien realisieren. Es wird lediglich ein skriptfähiger Webserver mit Zugriff auf die persistenten Daten und ein Browser mit Javascriptunterstützung benötigt. 3. Integration: Da jedes System, mit dem Webanwendungen entwickelt werden, HTMLSeiten erzeugen und ausliefern muss, gelingt spätestens hier die Integration von 126 8.2 Vergleich mit verwandten Arbeiten TransForm, da das tagbasierte Programmierinterface der Formulare sich nahtlos in HTML-Seiten einfügt. 4. Formulare als zentrales Element von TransForm-Anwendungen: Formulare bilden das zentrale clientseitige Konzept von TransForm. Dazu haben wir den Formularbegriff im Vergleich zu HTML-Formularen wesentlich erweitert. Wir haben in Kapitel 6 gezeigt, wie sich sogar Webanwendungen aus solchen erweiterten Formularelementen erstellen lassen. 5. Zugriff auf unterschiedliche Datenbanksysteme: Durch das abstrahierte Datenmodell lassen sich die unterschiedlichsten Datenbanksysteme als Backends in ein TransFormSystem integrieren. Neben diesen Primärzielen halten wir noch weitere Aspekte von TransForm für beachtenswert. Modulares Konzept TransForm ist ein modulares System, das aus unterschiedlichen Komponenten besteht, für die lediglich ein grundlegendes Modell sowie die Schnittstellen fest vorgegeben sind. So können Komponenten ausgetauscht und an unterschiedliche Gegebenheiten angepasst werden. Ein Anwendungsentwickler kann entweder fertige Komponenten übernehmen oder speziell an die eigenen Bedürfnisse angepasste Komponenten selbst entwickeln. Architekturstil TransForm-Anwendungen unterscheiden sich deutlich von herkömmlichen Webanwendungen, egal ob TransForm lediglich für den Datenzugriff eingesetzt wird oder ob eine komplette Anwendungen aus TransForm-Formularen zusammengestellt wird. Man kann bei TransForm also von einem eigenen Architekturstil für Webanwendungen sprechen. 8.2 Vergleich mit verwandten Arbeiten Obwohl eine ganze Reihe von Ansätzen für die Verarbeitung von Formularen oder von Transaktionen im Web existieren, ist keine dieser Arbeiten direkt mit TransForm vergleichbar. Für die Unterstützung von Transaktionen wird üblicherweise auf zusätzliche Komponenten zurückgegriffen [YK99, PA00]. Andere Ansätze ersetzen die klassischen ACIDEigenschaften durch abgeschwächte Korrektheitskriterien [YEH00] oder kümmern sich ausschließlich um Recoveryaspekte [SW06]. Entfernt verwandt ist auch die im Entstehen begriffene Transaktionsunterstützung nativer XML-Datenbanken [DHP04]. Allerdings liegt hier der Schwerpunkt auf den Schwierigkeiten, die sich aus dem semistrukturierten Datenmodell ergeben, und nicht auf den Schwierigkeiten, die sich aus der Systemarchitektur ergeben, wie es bei webbasierten Systemen der Fall ist. 127 Kapitel 8 Fazit Am ehesten gibt es noch Überschneidungen bei der Formularverarbeitung, wo zumindest in Teilbereichen Ähnlichkeiten zu einigen Arbeiten gegeben sind. Von der grundlegenden Idee in Bezug auf die Formulare gibt es einige Gemeinsamkeiten mit XForms [W3C00], das auch eine Erweiterung des Formularbegriffs darstellt. Allerdings ist dort keinerlei Transaktionsunterstützung vorgesehen. Auch XForms hält sich an das MVC-Architekturmuster und unterscheidet bei Formularen zwischen Modell, Darstellung und Steuerung. Die Elemente des Modells werden mit unterschiedlichen Widget-Typen verknüpft, die weitere Angaben über die Darstellung enthalten. Eine weitere Gemeinsamkeit besteht in der Unterstützung durch Webbrowser, die für XForms bisher kaum vorhanden ist, obwohl es sich um einen Standard des W3C handelt. Als Bestandteil des XHTML-2.0Standards dürfte sich die Unterstützung aber bald verbessern. Es gibt auch für XForms JavaScript-Implementierungen, die XForms genauso clientseitig in (X)HTML umwandeln wie wir das mit TransForm-Tags machen. Web Dynamic Forms [GL97] ist in gewisser Weise auch mit TransForm verwandt, obwohl es ganz andere Ziele verfolgt. Ein komplett neues Formularmodell wird eingeführt, das zu HTML-Formularen nicht in Beziehung steht, sondern über Java-Applets realisiert wird. Komplexe Interaktionsmuster beispielsweise zwischen einzelnen Formularfeldern lassen sich dabei in Java programmieren. In Gegensatz zu TransForm wird für die eigentliche Verarbeitung der Formulare der klassische Mechanismus eingesetzt. Auch sind Transaktionen hier kein unterstütztes Konzept. Die formularorientierte Analyse [DW04] ist eine Methode für die Modellierung von Anwendungen, bei der die Kommunikation zwischen Client und Server ausschließlich über Formulare erfolgt. Als Ansatz aus der Softwaretechnik steht hier allerdings die Anwendungsmodellierung im Vordergrund. Datenzugriff und Transaktionen können zwar als Seiteneffekt von Zustandsübergängen modelliert werden, für deren Realisierung wird allerdings im Endeffekt auf die üblichen Schnittstellen zurückgegriffen. Auch mit der serviceorientierten Architektur gibt es einige Gemeinsamkeiten. Ähnlich der Idee von TransForm sieht SOA eine Kapselung der persistenten Daten in einem WebService vor. SOA sieht allerdings eine Kopplung und Zusammenarbeit einzelner Dienste vor, während in TransForm jedes Formular genau auf einen Dienst zugreift und eventuell mehrere Formulare innerhalb einer Webseite über ein 2-Phasen-Commit-Protokoll synchronisiert werden. Deshalb kommt ein TransForm-System auch ohne komplexe Protokolle wie SOAP, WSDL oder UDDI aus, die in der SOA üblicherweise zum Einsatz kommen. 8.3 Beitrag Der größte Beitrag von TransForm liegt nicht darin, dass Formulare mittels ACID-Transaktionen im WWW verarbeitet werden können, sondern darin, wie dieses Ziel erreicht wurde. Diese grundlegenden Ideen wurden in [IL06] publiziert. 128 8.4 Ausblick Der wichtigste Aspekt ist dabei die Loslösung von SQL. Durch den Verzicht auf SQL und den Einsatz einer deklarativen Objektspezifikation wurde die Grundlage für zwei wesentliche Aspekte unseres Systems geschaffen. Wir können einerseits zueinander in Konflikt stehende Datenzugriffe erkennen, was eine entscheidende Grundlage für die Realisierung eines eigenen Transaktionsservers darstellt. Andererseits können diese mit einem Formularelement verknüpften Datenobjekte sowohl für Lese- als auch für Schreibzugriffe automatisch in Statements der nativen Anfragesprache übersetzt werden. Ein weiterer Beitrag von TransForm ist die Aufteilung der Transaktionsverarbeitung auf drei Modelle, die im Zusammenspiel die ACID-Eigenschaften gewährleisten: Das Transaktionsmodell bildet einzelne Transaktionsschritte auf HTTP-Anfragen ab, die mit Hilfe des Formularmodells den Transaktionszustand in jedem Schritt ermitteln können. Das Datenmodell stellt eine einheitliche Sprache für die Deklaration des Datenzugriffs in Formularen sowie für den Zugriff auf unterschiedliche Datenbanken zur Verfügung. Als wesentliche Unterscheidungsmerkmale, durch die sich TransForm von anderen Systemen abgrenzt, ergeben sich einerseits die geringen Anforderungen an die Infrastruktur sowie andererseits die Möglichkeit zur Integration in andere Frameworks für die Entwicklung von Webanwendungen. 8.4 Ausblick Wir haben mit TransForm einen neuen Weg für die Umsetzung von Transaktionen im Web eingeschlagen, der sich in einigen Punkten entscheidend von bisherigen Ansätzen absetzt. Auch wenn wir von unserem Konzept überzeugt sind, und es sich auch anhand einiger Implementierungen in Studierendenarbeiten generell als praxistauglich erwiesen hat, muss sich erst noch herausstellen, ob es über das akademische Umfeld hinaus Verbreitung finden kann. Immerhin erzeugt es doch eine größere Last für den Webserver als herkömmliche Webanwendungen. Der Bedarf für eine Transaktionsunterstützung muss groß genug sein, diesen Overhead in Kauf zu nehmen. 129 Abbildungsverzeichnis 1.1 1.2 1.3 1.4 Die Verarbeitung von Formularen in unterschiedlichen Prozessen des Webservers. Der Formularverarbeitungsmechanismus von TransForm. . . . . . . . . . . . . . Ein erstes Beispiel einer Webseite mit TransForm-Formularen. . . . . . . . . . . Die Darstellung der TransForm-Beispielseite im Browser. . . . . . . . . . . . . . 2.1 2.2 Der grundlegende HTTP-Anfrage-Antwort-Zyklus. . . . . . . . . . . . . . . . . . Der skript- und seitenbasierte Ansatz (links) sowie der sessionbasierte Ansatz (rechts). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 4.1 4.2 4.3 4.4 4.5 4.6 Architektur der Datenverarbeitung in TransForm als Kombination aus clientseitigem Ansatz (links) und serverseitigem Ansatz (rechts). . . . . . . . . . . . . . Die Architektur von TransForm in Bezug auf Web-Anwendungen. . . . . . . . . Die Schichten eines TransForm-Systems. . . . . . . . . . . . . . . . . . . . . . . Modelle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausführung von Transaktionsschritten in Transaktionen der Datenbank. . . . . Die Phasen eines Transaktionsschrittes. . . . . . . . . . . . . . . . . . . . . . . Fehlersituationen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Authentifikationsmechanismus von TransForm. . . . . . . . . . . . . . . . . 2 Ebenen von Transaktionen: Transaktionen und Transaktionsschritte. . . . . . Fehlersituationen während der Ausführung eines Schrittes. . . . . . . . . . . . Die serverseitigen Komponenten von TransForm. . . . . . . . . . . . . . . . . . Das XML-basierte Rückgabeformat. . . . . . . . . . . . . . . . . . . . . . . . . . 2 5 6 7 13 14 29 30 31 33 37 38 40 41 43 44 45 51 55 59 60 61 67 68 4.7 Die Beispieldatenbank Mondial. . . . . . . . . . . . . . . . . . . . . . . . . . . Die XML-Sicht der Mondial-Beispieldatenbank. . . . . . . . . . . . . . . . . . . Ein Ausschnitt des XML-Modells der Beispieldatenbank in Baumdarstellung. . . Die um referentielle Joins erweiterte XML-Sicht der Beispieldatenbank. . . . . . Die um Kreuzprodukt-Elemente erweiterte XML-Sicht der Beispieldatenbank. . Ein Ausschnitt aus der XML-Sicht des Reservierungssystems für Kinovorstellungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Übersichtsplan eines Kinosaals als HTML-Tabelle. . . . . . . . . . . . . . . . 5.1 5.2 5.3 5.4 Der Zusammenhang zwischen den betrachteten Schedulingklassen. . . Verhinderte Phänomene der einzelnen Recovery-Klassen. . . . . . . . . . Der Rahmen für TransForm-Scheduling-Algorithmen. . . . . . . . . . . . Das optimistische TransForm-Schedulingverfahren FOCC. . . . . . . . . 78 79 82 86 130 . . . . . . . . . . . . . . . . 71 73 Abbildungsverzeichnis 5.5 5.6 Die Realisierung von Sperren in TransForm. . . . . . Die Wachstumsphase vor dem Sperrpunkt und die fungsphase des 2-Phasen-Sperrverfahrens. . . . . . . 5.7 Varianten des 2-Phasen-Sperrprotokolls. . . . . . . . 5.8 Das TransForm-Sperrverfahren. . . . . . . . . . . . . 5.9 Das hybride Scheduling-Verfahren für TransForm. . . 5.10 2-Phasen-Commit-Protokoll in TransForm. . . . . . . . . . . . . . . . . . . . . . anschließende Schrump. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 89 90 93 96 99 6.1 6.2 6.3 Zustände von Formularen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Zustände von Formularelementen. . . . . . . . . . . . . . . . . . . . . . . . . . 104 Ein Screenshot des Kino-Reservierungs-Systems. . . . . . . . . . . . . . . . . . 112 7.1 7.2 Die Ergebnisse von Messreihen. . . . . . . . . . . . . . . . . . . . . . . . . . . . Die durchschnittliche HTTP-Anfragedauer bei Formularen mit einem Formularfeld. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die durchschnittliche HTTP-Anfragedauer bei Formularen mit 10 Formularfeldern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die durchschnittliche HTTP-Anfragedauer bei Formularen mit 100 Formularfeldern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Anzahl der bewältigten Anfragen in der Minute. . . . . . . . . . . . . . . . Die Anzahl der verarbeiteten Formulare. . . . . . . . . . . . . . . . . . . . . . . 7.3 7.4 7.5 7.6 120 121 122 123 124 125 131 Literaturverzeichnis [AA90] Divyakant Agrawal and Amr El Abbadi. Locks with constrained sharing. In Proceedings of the Ninth ACM SIGACT-SIGMOD-SIGART Symposium on Principles of Database Systems, April 2-4, 1990, Nashville, Tennessee, pages 85–93. ACM Press, 1990. [AA95] D. Agrawal and A. El Abbadi. Constrained shared locks for increasing concurrency in databases. J. Comput. Syst. Sci., 51(1):53–63, 1995. [AAL94] D. Agrawal, A. El Abbadi, and A.E. Lang. The performance of protocols based on locks with ordered sharing. IEEE Transactions on Knowledge and Data Engineering, 06(5):805–818, 1994. [ABBC99] David L. Atkins, Thomas Ball, Glenn Bruns, and Kenneth Cox. Mawl: A domain-specific language for form-based services. IEEE Trans. Softw. Eng., 25(3):334–346, 1999. [ACL87] Rakesh Agrawal, Michael J. Carey, and Miron Livny. Concurrency control performance modeling: alternatives and implications. ACM Trans. Database Syst., 12(4):609–654, 1987. [ACM87] Rakesh Agrawal, Michael J. Carey, and Lawrence McVoy. The performance of alternative strategies for dealing with deadlocks in database management systems. IEEE Trans. Softw. Eng., 13(12):1348–1363, 1987. [ACM94] Juan M. Andrade, Mark T. Carges, and M. Randal MacBlane. The tuxedo system: An open on-line transaction processing environment. IEEE Data Eng. Bull., 17(1):34–39, 1994. [ALO00] Atul Adya, Barbara Liskov, and Patrick E. O’Neil. Generalized isolation level definitions. In International conference on Data Engineering ICDE, pages 67–78, 2000. [And07] Nils Andre. Anwendungsstudie TransForm. Diplomarbeit, Albert-LudwigsUniversität Freiburg i. Brsg., 2007. [Ber90] Philip A. Bernstein. 33(11):75–86, 1990. [BG80] Philip A. Bernstein and Nathan Goodman. Timestamp-based algorithms for concurrency control in distributed database systems. In Sixth International 132 Transaction processing monitors. Commun. ACM, Literaturverzeichnis Conference on Very Large Data Bases, October 1-3, 1980, Montreal, Quebec, Canada, Proceedings, pages 285–300. IEEE Computer Society, 1980. [BGRS91] Yuri Breitbart, Dimitrios Georgakopoulos, Marek Rusinkiewicz, and Abraham Silberschatz. On rigorous transaction scheduling. IEEE Transactions on Software Engineering, 17(9):954–960, 1991. [BHM90] Philip A. Bernstein, Meichun Hsu, and Bruce Mann. Implementing recoverable requests using queues. In SIGMOD ’90: Proceedings of the 1990 ACM SIGMOD international conference on Management of data, pages 112–122, New York, NY, USA, 1990. ACM Press. [BL94] T. Berners-Lee. Universal Resource Identifiers in WWW: A Unifying Syntax for the Expression of Names and Addresses of Objects on the Network as used in the World-Wide Web. RFC 1630 (Informational), June 1994. [BL96] Tim Berners-Lee. WWW: Past, present, and future. Computer, 29(10):69–77, 1996. [BLCGP92] T. Berners-Lee, R. Cailliau, J-F. Groff, and B. Pollermann. World-Wide Web: An information infrastructure for high-energy physics. Proceedings of the Workshop on Software Engineering, Artificial Intelligence and Expert Systems for High Energy and Nuclear Physics, January 1992. [BMRS00] Claus Brabrand, Anders Møller, Mikkel Ricky, and Michael I. Schwartzbach. Powerforms: Declarative client-side form field validation. World Wide Web, 3(4):205–214, 2000. [BMS02] Claus Brabrand, Anders Møller, and Michael I. Schwartzbach. The <bigwig> project. ACM Trans. Inter. Tech., 2(2):79–114, 2002. [BN84] Andrew D. Birrell and Bruce Jay Nelson. Implementing remote procedure calls. ACM Trans. Comput. Syst., 2(1):39–59, 1984. [BN97] Philip A. Bernstein and Eric Newcomer. Principles of Transaction Processing: For the Systems Professional. Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 1997. [BSW79] Philip A. Bernstein, David W. Shipman, and Wing S. Wong. Formal Aspects of Serializability in Database Concurrency Control. IEEE Transactions on Software Engeneering, 5(3):203–216, 1979. [Cas81] Marco Antonio Casanova. Concurrency Control Problem for Database Systems. Springer-Verlag New York, Inc., Secaucus, NJ, USA, 1981. [CFB00] Stefano Ceri, Piero Fraternali, and Aldo Bongio. Web Modeling Language (WebML): a modeling language for designing Web sites. In Proceedings of the 9th international World Wide Web conference on Computer networks : the 133 Literaturverzeichnis international journal of computer and telecommunications networking, pages 137–157, Amsterdam, The Netherlands, 2000. North-Holland Publishing Co. [CFI+ 00] Michael J. Carey, Daniela Florescu, Zachary G. Ives, Ying Lu, Jayavel Shanmugasundaram, Eugene J. Shekita, and Subbu N. Subramanian. XPERANTO: Publishing object-relational data as XML. In WebDB (Informal Proceedings), pages 105–110, 2000. [CMM95] Duncan G. Copeland, Richard O. Mason, and James L. McKenney. Sabre: The development of information-based competence and execution of informationbased competition. IEEE Annals of the History of Computing, 17(3):30–57, 1995. [CMS03] Aske Simon Christensen, Anders Møller, and Michael I. Schwartzbach. Extending java for high-level web service construction. ACM Trans. Program. Lang. Syst., 25(6):814–875, 2003. [DFF+ 98] A. Deutsch, M. F. Fernandez, D. Florescu, A. Y. Levy, and D. Suciu. “XML-QL: A Query Language for XML”. In WWW The Query Language Workshop (QL), Cambridge, MA, , 1998. [DFS99] Alin Deutsch, Mary F. Fernandez, and Dan Suciu. Storing Semistructured Data with STORED. In Alex Delis, Christos Faloutsos, and Shahram Ghandeharizadeh, editors, SIGMOD 1999, Proceedings ACM SIGMOD International Conference on Management of Data, June 1-3, 1999, Philadephia, Pennsylvania, USA, pages 431–442. ACM Press, 1999. [DHP04] Stijn Dekeyser, Jan Hidders, and Jan Paredaens. A transaction model for xml databases. World Wide Web, 7(1):29–57, 2004. [DN99] Fredj Dridi and Gustaf Neumann. How to implement web-based groupware systems based on webdav. In WETICE ’99: Proceedings of the 8th Workshop on Enabling Technologies on Infrastructure for Collaborative Enterprises, pages 114–119, Washington, DC, USA, 1999. IEEE Computer Society. [DTCO03] David DeHaan, David Toman, Mariano P. Consens, and M. Tamer Özsu. A comprehensive xquery to sql translation using dynamic interval encoding. In SIGMOD ’03: Proceedings of the 2003 ACM SIGMOD international conference on Management of data, pages 623–634, New York, NY, USA, 2003. ACM Press. [DW04] Dirk Draheim and Gerald Weber. Form-Oriented Analysis: A New Methodology to Model Form-Based Applications. Springer Verlag, 2004. [ECM99] ECMA. ECMA-262: ECMAScript Language Specification. European Computer Manufacturers Association, third edition, Dec 1999. 134 Literaturverzeichnis [EGLT76] K. P. Eswaran, J. N. Gray, R. A. Lorie, and I. L. Traiger. The Notions of Consistency and Predicate Locks in a Database System. Commun. ACM, 19(11):624– 633, 1976. [EJWG99] Jr. E. James Whitehead and Yaron Goland. Webdav: a network protocol for remote collaborative authoring on the web. In Proceedings of the Sixth European conference on Computer supported cooperative work, pages 291–310, Norwell, MA, USA, 1999. Kluwer Academic Publishers. [EMK+ 04] Andrew Eisenberg, Jim Melton, Krishna G. Kulkarni, Jan-Eike Michels, and Fred Zemke. SQL:2003 has been published. SIGMOD Record, 33(1):119–126, 2004. [FFK+ 98] Mary Fernandez, Daniela Florescu, Jaewoo Kang, Alon Levy, and Dan Suciu. Catching the boat with strudel: experiences with a web-site management system. In SIGMOD ’98: Proceedings of the 1998 ACM SIGMOD international conference on Management of data, pages 414–425, New York, NY, USA, 1998. ACM Press. [FGM+ 99] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, and T. Berners-Lee. Hypertext Transfer Protocol – HTTP/1.1. RFC 2616 (Draft Standard), jun 1999. Updated by RFC 2817. [Fie00] Roy Thomas Fielding. Architectural Styles and the Design of Network-based Software Architectures. Dissertation, University of California, Irvine, 2000. [FKS+ 02a] Mary Fernandez, Yana Kadiyska, Dan Suciu, Atsuyuki Morishima, and WangChiew Tan. Silkroute: A framework for publishing relational data in xml. ACM Trans. Database Syst., 27(4):438–493, 2002. [FKS+ 02b] J. E. Funderburk, G. Kiernan, J. Shanmugasundaram, E. Shekita, and C. Wei. Xtables: Bridging relational technology and xml. IBM Syst. J., 41(4):616–641, 2002. [FMS01] Mary F. Fernandez, Atsuyuki Morishima, and Dan Suciu. Efficient evaluation of XML middle-ware queries. In SIGMOD Conference, 2001. [FR85] Peter Franaszek and John T. Robinson. Limitations of concurrency in transaction processing. ACM Trans. Database Syst., 10(1):1–28, 1985. [Gar05] Jesse James Garrett. Ajax: A new approach to web applications, 2005. http: //www.adaptivepath.com/publications/essays/archives/000385.php. [GL97] Andreas Girgensohn and Alison Lee. Seamless integration of interactive forms into the web. Comput. Netw. ISDN Syst., 29(8-13):1531–1542, 1997. [GLPT94] J. N. Gray, R. A. Lorie, G. R. Putzolu, and I. L. Traiger. Granularity of locks and degrees of consistency in a shared data base. pages 181–208, 1994. 135 Literaturverzeichnis [GPS93] Franca Garzotto, Paolo Paolini, and Daniel Schwabe. HDM a model-based approach to hypertext application design. ACM Trans. Inf. Syst., 11(1):1–26, 1993. [Gra78] Jim Gray. Notes on Database Operating Systems. In R. Bayer, R. M. Graham, J. H. Saltzer, G. Seegmüller (Hrsg.), Operating Systems, An Advanced Course, volume 60 of Lecture Notes in Computer Science, pages 393–481, London, UK, 1978. Springer-Verlag. [Gra81] Jim Gray. The Transaction Concept: Virtues and Limitations (invited paper). In Very Large Data Bases, 7th International Conference, September 9-11, 1981, Cannes, France, Proceedings, pages 144–154. IEEE Computer Society, 1981. [He] Hao He. What is service-oriented architecture. http://webservices.xml. com/pub/a/ws/2003/09/30/soa.html. [Hä84] [IBM] Theo Härder. Observations on optimistic concurrency control schemes. Inf. Syst., 9(2):111–120, 1984. IBM. Handbücher für das Customer Information Control System (CICS). http: //www-306.ibm.com/software/htp/cics/library. [IBV98] Tomás Isakowitz, Michael Bieber, and Fabio Vitali. Web information systems. Commun. ACM, 41(7):78–80, 1998. [IL06] Matthias Ihle and Georg Lausen. TransForm: A Transaction Safe Web Application Model. In WEBIST (1), pages 164–171, 2006. [KK00] E. Kirda and C. Kerer. Myxml: An xml based template engine for the generation of flexible web content, 2000. Template System. [KKK02] Clemens Kerer, Engin Kirda, and Roman Kurmanowytsch. A generic contentmanagement tool for web databases. IEEE Internet Computing, 6(4):38–42, 2002. [KL02] Sascha Klopp and Udo W. Lipeck. Generierung und Anfragebearbeitung von hierarchischen XML-Sichten auf relationalen Datenbanken. In XML Technologien für das Semantic Web - XSW 2002, Proceedings zum Workshop, pages 105–118. GI, 2002. [KR81] H. T. Kung and John T. Robinson. On optimistic methods for concurrency control. ACM Trans. Database Syst., 6(2):213–226, 1981. [Lam78] Leslie Lamport. Time, clocks, and the ordering of events in a distributed system. Commun. ACM, 21(7):558–565, 1978. [Lau82] Georg Lausen. Concurrency control in database systems: A step towards the integration of optimistic methods and locking. In ACM 82: Proceedings of the ACM ’82 conference, pages 64–68, New York, NY, USA, 1982. ACM Press. 136 Literaturverzeichnis [LBK02] Philip M. Lewis, Arthur Bernstein, and Michael Kifer. Databases and Transaction Processing. Addison-Wesley, 2002. [LEK98] J. Lyon, K. Evans, and J. Klein. Transaction Internet Protocol. Technical Report Internet RFC 2371, 1998. http://www.ietf.org/rfc/rfc2372.txt? number=2372. [LSCI97] M. C. Little, S. K. Shrivastava, S. J. Caughey, and D. B. Ingham. Constructing reliable Web applications using atomic actions. Computer Networks and ISDN Systems, 29(8–13):1281–1290, 1997. [LSSW84] Georg Lausen, Eljas Soisalon-Soininen, and Peter Widmayer. Maximal concurrency by locking. In Proceedings of the Third ACM SIGACT-SIGMOD Symposium on Principles of Database Systems, April 2-4, 1984, Waterloo, Ontario, Canada, pages 38–44. ACM, 1984. [LSSW86] Georg Lausen, Eljas Soisalon-Soininen, and Peter Widmayer. locking. Information and Control, 70(2/3):193–215, 1986. Pre-analysis [LSSW90] Georg Lausen, Eljas Soisalon-Soininen, and Peter Widmayer. On the power of safe locking. Journal of Computer and System Science, 40(2):269–288, 1990. [Mar07] Thomas Marchwinski. Transaktionssicherer Zugriff auf eine MP3-basierte Musikdatenbank über das Web. Diplomarbeit, Albert-Ludwigs-Universität Freiburg i. Brsg., 2007. [NCS] The National Center for Supercomputing Applications NCSA. CGI: the common gateway interface, version 1.1. Verfügbar unter: http://hoohoo.ncsa. uiuc.edu/cgi/. [OBS99] Michael A. Olson, Keith Bostic, and Margo Seltzer. Berkeley db. In ATEC’99: Proceedings of the Annual Technical Conference on 1999 USENIX Annual Technical Conference, pages 43–43, Berkeley, CA, USA, 1999. USENIX Association. [PA00] Guy Pardon and Gustavo Alonso. Cheetah: A Lightweight Transaction Server for Plug-and-Play Internet Data Management. In VLDB ’00: Proceedings of the 26th International Conference on Very Large Data Bases, pages 210–219, San Francisco, CA, USA, 2000. Morgan Kaufmann Publishers Inc. [RS00] W. Retschitzegger and W. Schwinger. Towards modeling of dataweb applications - a requirements’ perspective, 2000. [RSL78] Daniel J. Rosenkrantz, Richard E. Stearns, and Philip M. Lewis. System level concurrency control for distributed database systems. ACM Trans. Database Syst., 3(2):178–198, 1978. [RSL99] Gustavo Rossi, Daniel Schwabe, and Fernando Lyardet. Web application models are more than conceptual models. In ER ’99: Proceedings of the Workshops 137 Literaturverzeichnis on Evolution and Change in Data Management, Reverse Engineering in Information Systems, and the World Wide Web and Conceptual Modeling, pages 239–253, London, UK, 1999. Springer-Verlag. [SGMS94] Kenneth Salem, Héctor García-Molina, and Jeannie Shands. Altruistic locking. ACM Trans. Database Syst., 19(1):117–165, 1994. [SH04] Bita Shadgar and Ian Holyer. Adapting databases and webdav protocol. In WWW ’04: Proceedings of the 13th international conference on World Wide Web, pages 612–620, New York, NY, USA, 2004. ACM Press. [She93] Mark Sherman. Architecture of the encina distributed transaction processing family. In SIGMOD ’93: Proceedings of the 1993 ACM SIGMOD international conference on Management of data, pages 460–463, New York, NY, USA, 1993. ACM Press. [Sor07] Philip Washington Sorst. Ein relationales Backend für TransForm. Studienarbeit, Albert-Ludwigs-Universität Freiburg i. Brsg., 2007. [SW06] German Shegalov and Gerhard Weikum. Eos2: unstoppable stateful php. In VLDB ’06: Proceedings of the 32nd international conference on Very large data bases, pages 1223–1226. VLDB Endowment, 2006. [TB96] Paul Thistlewaite and Steve Ball. Active forms. In Proceedings of the fifth international World Wide Web conference on Computer networks and ISDN systems, pages 1355–1364, Amsterdam, The Netherlands, 1996. Elsevier Science Publishers B. V. [Thi05] Peter Thiemann. An embedded domain-specific language for type-safe serverside web scripting. ACM Trans. Inter. Tech., 5(1):1–46, 2005. [Thi06] Peter Thiemann. WASH server pages. SCIENCE, 5(3945):277–293, 2006. [Tho79] Robert H. Thomas. A majority consensus approach to concurrency control for multiple copy databases. ACM Trans. Database Syst., 4(2):180–209, 1979. [Tho98] Alexander Thomasian. Concurrency control: methods, performance, and analysis. ACM Comput. Surv., 30(1):70–119, 1998. LECTURE NOTES IN COMPUTER [TIHW01] Igor Tatarinov, Zachary G. Ives, Alon Y. Halevy, and Daniel S. Weld. Updating xml. In SIGMOD ’01: Proceedings of the 2001 ACM SIGMOD international conference on Management of data, pages 413–424, New York, NY, USA, 2001. ACM. [W3C00] W3C. Xforms, 2000. http://www.xforms.org/. [Wei84] W. E. Weihl. Specification and implementation of atomic data types. Dissertation, Cambridge, MA, USA, 1984. 138 Literaturverzeichnis [WV01] Gerhard Weikum and Gottfried Vossen. Transactional information systems: theory, algorithms, and the practice of concurrency control and recovery. Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2001. [Yan84] Mihalis Yannakakis. Serializability by Locking. Journal of the ACM, 31(2):227– 244, 1984. [YASU01] M. Yoshikawa, T. Amagasa, T. Shimura, and S. Uemura. XRel: a path-based approach to storage and retrieval of xml documents using relational databases. ACM Trans. Inter. Tech., 1(1):110–141, 2001. [YEH00] Muhammad Younas, Barry Eaglestone, and Robert Holton. A formal treatment of the sacred protocol for multidatabase web transactions. In DEXA ’00: Proceedings of the 11th International Conference on Database and Expert Systems Applications, pages 899–908, London, UK, 2000. Springer-Verlag. [YK99] Jingshuang Yang and Gail E. Kaiser. JPernLite: Extensible Transaction Services for the WWW. IEEE Transactions on Knowledge and Data Engineering, 11(4):639–657, 1999. 139