Kap. 9 IS-Anwendungsentwicklung 9.1 Aufgabenteilung Client oder Server? •Wieviel soll der Client machen? Präsentation ok. Anwendungsfunktionalität? •Was sind die Aufgaben des Servers? Datenverwaltung ok. Anwendungsfunktionalität? Server Client Data Presentation Anwendungs Funktionalität Data Management Anwendungsentwicklung - 1 ISK 2003 Beispiele: Relation Server z Client sendet SQL Queries oder Updates Stored-Procedures- Aufrufe z Server sendet Application Query Language Interface Communications Manager Tabellen als Menge von Ergebnis-Tupeln Einfache Werte z Programmatic Interface ... SQL Query Result Table Procedure Call Result Return Beispiele: Oracle Sybase DB2 Informix ...relationale DBMS Communications Manager Query Optimizer Index Manager Stored Procedure Transaction Manager Page Cache Manager Database Database ISK 2003 Anwendungsentwicklung - 2 Object Server z Client sendet Application Objekt IDs Methodenaufrufe z Query Language Interface Server liefert Angefordertes Objekt im Hauptspeicher des AP Ergebnis des Methodenaufrufs z Object Browser Programmatic Interface (Proxy) Object Manager Method Call Objects Beispiele: Objektorientierte DBMS wie Gemstone Ontos Versant Result Return Object Manager Query Optimizer Index Manager Transaction Manager Page Cache Manager Database Anwendungsentwicklung - 3 ISK 2003 Page Server z Client sendet z Seitennummer Server gibt Seite zurück Application Query Interface & Optimizer Object Browser Programmatic Interface Object Manager z Die eigentliche DBMS-Arbeit findet daher im Client statt. Im Server verbleibt “nur” die Transaktionsverwaltung (zwangsläufig auf der Seitenebene) und die Pufferverwaltung. Index Manager Transaction Manager Page Cache Manager Pages Transaction Manager z Beispiel: Page Cache Manager O2 Objectstore ISK 2003 Database Database Anwendungsentwicklung - 4 9.2 Kopplungsvarianten zwischen Programmiersprachen und Datenbanksprachen 1) Erweiterung der Programmiersprache um Datenbankkonstrukte: Persistente Programmiersprachen, Datenbankprogrammiersprachen (z.B. Pascal/R, ODMG) 2) Erweiterung der Datenbanksprache um Programmierkonstrukte: "4th Generation Languages" (4GLs, z.B. SQL99/PSM, PLSQL) 3) Einbettung der Datenbanksprache in die Programmiersprache: "Embedded SQL" (ESQL) und Call-Level-Interface (CLI, z.B. ODBC, JDBC) Kernproblem bei ESQL und CLI: Abbildung von Tupelmengen auf die Datentypen der Wirtsprogrammiersprache Realisierte Lösung: Abbildung von Tupeln bzw. Attributen auf die Datentypen der Programmiersprache -> Wirtsprogrammvariable (engl.: Host Variables) + Iteratoren (Schleifen) zur Verarbeitung von Tupelmengen: -> Cursor-Konzept Anwendungsentwicklung - 5 ISK 2003 Client/Server, mehr Detail Embedded SQL Appl. SQL Commands Call-level SQL Appl. Precompiler CLI Calls CLI Precompiler Call-level Interface Run-time Library Run-time Library Database Driver Stacks Client SQL FAP Stacks Server Tables Database Server Stored Procedures aus: Orfali et al., 1999 ISK 2003 Anwendungsentwicklung - 6 9.3 Anwendungsentwicklung - Client-seitig z z Embedded SQL (ESQL): Nach ISO SQL-92 definierte Einbettung von SQL in Programmiersprachen, z.B. Cobol, PL/1, Pascal, C, Java,... Statisches ESQL: Alle Informationen zur Compilierung vorhanden Dynamisches ESQL: SQL-Statements erst zur Laufzeit bekannt Call-Level Interface (CLI): Standardisierte Schnittstelle zur Kommunikation mit Datenbanken ohne Precompiler X/Open SAG CLI (SAG = SQL Access Group) ODBC, JDBC Anwendungsentwicklung - 7 ISK 2003 Wirtsprogrammvariable (Host Variables) Die Attribute eines Resultattupels einer SQL-Anfrage werden an speziell deklarierte Variable des Wirtsprogramms zugewiesen (INTO-Klausel). Beispiel: EXEC SQL SELECT PNr, Menge, Status INTO :pnr, :menge, :status FROM Bestellungen WHERE BestNr = 555; Analog können SQL-Anweisungen mittels solcher Variable mit Eingabeparametern versorgt werden: Beispiele: 1)EXEC SQL SELECT PNr, Menge, Status INTO :pnr, :menge, :status FROM Bestellungen WHERE BestNr = :bestnr; 2)EXEC SQL INSERT INTO Bestellungen (BestNr,Monat,Tag,KNr,PNr, Menge) VALUES (:bestnr, :monat, :tag, :knr, :pnr, :menge); Wirtsprogrammvariable dienen als "Übergabepuffer" zwischen DBS und Programm. Generell werden dabei die SQL-Datentypen auf die Datentypen der jeweiligen Wirtsprogrammiersprache abgebildet. ISK 2003 Anwendungsentwicklung - 8 Indikatorvariable zum Erkennen von Nullwerten Beispiel: EXEC SQL BEGIN DECLARE SECTION; int pnr; int vorrat; short vorrat_ind; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT Vorrat INTO :vorrat:vorrat_ind FROM Produkte WHERE PNr = :pnr; if (vorrat_ind == 0) { /* kein Nullwert */ ... } else { /* Nullwert */ ... }; Allgemein können Indikatorvariable folgende Werte haben: =0 die entsprechende Wirtsprogrammvariable hat einen regulären Wert =-1 die entsprechende Wirtsprogrammvariable hat einen Nullwert >0 die entsprechende Wirtsprogrammvariable enthält eine abgeschnittene Zeichenkette Anwendungsentwicklung - 9 ISK 2003 Verarbeitung von Tupelmengen mittels CursorKonzept Zweck: Verarbeitung von Tupelmengen in einer nichtmengenorientierten Wirtsprogrammiersprache. Notwendig für alle Anfragen mit mehr als einem Resultattupel. Beispiel: Ausgabe aller Bestellungen eines Kunden #define TRUE 1 #define FALSE 0 ... printf ("Bitte geben Sie eine Kundennummer ein. (0 = Programmende)\n"); scanf ("%d", &knr); EXEC SQL DECLARE Kundeniterator CURSOR FOR SELECT Monat, Tag, Bez, Menge FROM Bestellungen WHERE KNr = :knr ORDER BY Monat DESC, Tag DESC; /* Cursor-Deklaration immer ohne INTO-Klausel */ ISK 2003 Anwendungsentwicklung - 10 EXEC SQL OPEN Kundeniterator; /* An dieser Stelle werden die Eingabeparameter der SQL-Anweisung (:knr) ausgewertet,und gedanklich wird hier die Resultattupelmenge ermittet*/ found = TRUE; while (found) /* solange es noch Resultattupel gibt */ { EXEC SQL FETCH Kundeniterator INTO :monat, :tag, :bez, :menge; /* Hier werden die Wirtsprogrammvariable für die Resultattupel festgelegt. */ bez.arr[bez.len] = '\0'; if ((sqlca.sqlcode >= 0) && (sqlca.sqlcode != 1403)) printf ("%d.%d.: %d %s", tag, monat, menge, bez); else found = FALSE; }; /*while*/ EXEC SQL CLOSE Kundeniterator; /* Freigabe des Cursors und der damit verbundenen DBS-Ressourcen */ Anwendungsentwicklung - 11 ISK 2003 Fehlerbehandlung in ESQL 1)Explizites Testen von sqlca.sqlcode im Wirtsprogramm nach einer SQL-Anweisung: =0 Anweisung korrekt ausgeführt, keine besonderen Vorkommnisse <0 Fehler bei der Ausführung (siehe Fehlercodes im Manual) >0 Anweisung ausgeführt, Auftreten eines Sonderfalls, z.B. signalisiert der Wert 1403, dass keine (weiteren) Treffertupel existieren Zusatzinformation in den restlichen Komponenten von sqlca, z.B.: sqlca.sqlerrd[2] Anzahl der Tupel, die von einer Insert-, Update- oder Delete-Anweisung betroffen waren sqlca.sqlerrm.sqlerrmc Fehlermeldung als Ascii-Text (max. 70 Zeichen) sqlca.sqlerrm.sqlerrml Länge der Fehlermeldung 2)Deklaration von "Exception-Handling"-Strategien: EXEC SQL WHENEVER ( SQLERROR | NOT FOUND | SQLWARNING ) ( STOP | GOTO label | CONTINUE ) wobei SQLERROR einem SQLCODE < 0 entspricht, NOT FOUND dem SQLCODE 1403 und SQLWARNING einem SQLCODE > 0 (aber ungleich 1403). Der ESQL-Precompiler erzeugt automatisch nach jeder SQL-Anweisung einen entsprechenden Vergleich mit sqlca.sqlcode, und zwar jeweils aufgrund der textuell letzten WHENEVER-Anweisung vor der SQL-Anweisung. ISK 2003 Anwendungsentwicklung - 12 Embedded SQL - statisch ESQL/Csource program ESQL/C precompiler C-source program with SQL statements and ESQL/C calls C language preprocessor and compiler Executable Programm Beispiel: credit (int amount, int accountno) { EXEC SQL UPDATE account SET balance = balance + :amount WHERE account_number = :accountno; } z Zur Compilezeit hat der Precompiler u.a. folgende Aufgaben: z Syntax- und Semantikprüfung Typenprüfung Fehlerbehandlung Wenig flexibel, aber weniger Laufzeitfehler! Anwendungsentwicklung - 13 ISK 2003 Embedded SQL - dynamisch ESQL/Csource program ESQL/C precompiler C-source program with SQL statements and ESQL/C calls C language preprocessor and compiler Executable Programm Beispiel: credit( int amount, int accountno, char *table) { char dyn_stmt[120]; sprintf(dyn_stmt, "UPDATE %s SET balance = balance + :a WHERE account_number = :ano“, table); EXEC SQL PREPARE sql_stmt FROM :dyn_stmt; EXEC SQL EXECUTE sql_stmt USING :amount, :accountno; } z z ISK 2003 Der Precompiler kann weniger Überprüfungen durchführen, da das SQL Statement erst zur Laufzeit bekannt ist. Flexibler, aber mehr Laufzeitfehler möglich! Anwendungsentwicklung - 14 Call Level Interface, SQL99 CLI: #include "sqlcli.h" extern SQLHDBC hdbc; extern SQLHENV henv; /* Verbindung steht schon */ /* Umgebung */ API CLI Native Interface DBMS void credit ( SQLHSTMT hstmt, int amount, int accountno, char *table) { /* hstmt wird von aussen gegeben, damit Transaktionskontrolle ausserhalb dieser Prozedur. "credit" ist Baustein */ char update[120]; SQLINTEGER NameParamLength1; SQLINTEGER NameParamLength2; sprintf(update, "UPDATE %s SET balance = balance + ? WHERE account_number = ?", table); SQLPrepare(hstmt, update, SQL_NTS); SQLBindParameter(hstmt, 1, SQL_PARAM_MODE_IN, SQLCHAR, SQL_CHAR, NAME_LENGTH, 0 &amount, NAME_LENGTH, &NameParamLength1); SQLBindParameter(hstmt, 2, SQL_PARAM_MODE_IN, SQLCHAR, SQL_CHAR, NAME_LENGTH, 0 &accountno, NAME_LENGTH, &NameParamLength2); SQLExecute(hstmt); } ISK 2003 Anwendungsentwicklung - 15 Zusammenfassung Client-seitige AP z z z z z Jeder Anwender programmiert selbst und entwickelt ähnliche Bausteine. Besser wäre: Anwender benutzen Funktions-Bausteine! Bausteine ändern sich (Systemwechsel oder Firmenpolitik). Folge: alle Anwender müssen ihre Programmierung ändern bzw. Module aus gemeinsamer Bibliothek holen. Besser: Funktions-Bausteine in der Datenbank abgelegen. Damit können alle Clients darauf zugreifen. Also „Stored Procedures“ in die Datenbank ->9.4! Beachten: Dies ist unabhängig von Performance-Aspekten! ISK 2003 Anwendungsentwicklung - 16 9.4 Anwendungsentwicklung - Server-seitig z z z Stored Procedures: - Verwendung einer “Stored Procedure Language”, z.B. PL/SQL - Standard unter SQL-99 als “SQL/PSM” (= Persistent Stored Module) Trigger (ereignisgesteuerte Funktionen/Prozeduren) User Defined Types (UDTs, s. SQL-99) Client Client Application Select Insert Application Update Execute procedure Return results Stored Procedure Server Database Remote SQL Database Server Stored Procedure Anwendungsentwicklung - 17 ISK 2003 PSM aus SQL99 Erweiterung von SQL zur Programmiersprache: Wir finden die üblichen Konstrukte aus höheren Programmiersprachen... - compound statement - SQL variable declaration - if statement - case statement - loop statement - while statement - repeat statement - for statement - leave statement - return statement - call statement - assignment statement - signal / resignal statement ISK 2003 BEGIN … END; DECLARE var CHAR (6); IF subject (nachr) < > ‘urgent’ THEN … ELSE …; CASE subject (nachr) WHEN ‘SQL’ THEN … WHEN …; LOOP <SQL statement list> END LOOP; WHILE i < 100 DO … END WHILE; REPEAT … UNTIL i < 100 … END REPEAT; FOR result AS … DO … END FOR; LEAVE …; RETURN ‘urgent’; CALL procedure_x (1, 3, 5); SET x = ‘abc’; SIGNAL division_by_zero Anwendungsentwicklung - 18 Beispiel für SQL-Prozedur Beispiel in Oracle CREATE PROCEDURE debit ( amount NUMBER, accountno INT, result OUT INT) IS bal INT; BEGIN SELECT balance INTO bal FROM account WHERE account_number = accountno; IF bal > amount THEN UPDATE account SET balance = balance - amount WHERE account_number = accountno; result = 1; ELSE result = 0; END IF; END debit; Anwendungsentwicklung - 19 ISK 2003 9.5 Java und Datenbankprogrammierung Im Folgenden werden wir am Beispiel von SQLJ zeigen, wie man eine Funktion sowohl server- als auch client-seitig verwenden kann. Folgendes sind wichtige Tatsachen: z SQLJ ist entstanden auf Vorschlag von ORACLE, aber u.a. auch von IBM, Sybase, Informix unterstützt. Der Precompiler von ESQL wird bei SQLJ üblicherweise “Translator” genannt. SQLJ erzeugt JDBC, eine standardisierte Call-Schnittstelle z SQL-Anweisungen haben die allgemeine Form: z z #sql { SQL-Anweisung }; ISK 2003 Anwendungsentwicklung - 20 Debit als Java-Funktion (mit SQLJ) public static int debit (int amount, int accountno) throws SQLException { /* File connect.properties enthaelt alle noetigen Parameter */ Oracle.connect(Account.class, "connect.properties"); int bal; #sql{ SELECT balance INTO :bal FROM account WHERE account_number = :accountno }; /* Abbuchen falls moeglich... */ if (bal > amount) { #sql{ UPDATE account SET balance= balance - :amount WHERE account_number = :accountno }; #sql { COMMIT }; return 1; }else { return 0; } } Anwendungsentwicklung - 21 ISK 2003 SQLJ: client-seitig public static void main( String args[] ) { try { if (args.length != 2) { System.out.println("Usage: java Account <amount> <accountnum } else { int amount = Integer.parseInt(args[0]); int account = Integer.parseInt(args[1]); if ( debit(amount,account)==1) { System.out.println( "Abbuchung okay..."); }else { System.out.println( "Abbuchung konnte nicht ausgefuehrt werden..."); } } } catch( SQLException exception ) { System.err.println( "Error running the example: " + exception ); } } } Compilieren und aufrufen mit: sqlj -explain -ser2class -status Account.sqlj java Account ISK 2003 Anwendungsentwicklung - 22 SQLJ : server-seitig (I) alter java class "Account" compile; create or replace package AccountPack as FUNCTION debit(amount NUMBER, accountno NUMBER) RETURN NUMBER; end AccountPack; / create or replace package body AccountPack as FUNCTION debit(amount NUMBER, accountno NUMBER) RETURN NUMBER AS language java name 'Account.debit(int,int) return int'; end AccountPack; / In den Oracle-Server laden mit: jar cvf0 Account.jar *.class loadjava -thin -user iskXX/iskXXX@dblab3:1521:stud3 -resolve Account.jar Anwendungsentwicklung - 23 ISK 2003 SQLJ : server-seitig (II) Verwendung wie "gewöhnliche" Stored Procedure: DECLARE dummy NUMBER; BEGIN dummy := AccountPack.debit(300,1); END; / SELECT * from account; ISK 2003 Anwendungsentwicklung - 24 SQLJ-Cursor (I): “named iterators” #sql iterator MyNamedIterType ( int legiNr, String name); MyNamedIterType myIter1; Beispiel-Tabelle: iskdb (legiNr, name) #sql myIter1 = { SELECT name , legiNr FROM iskdb }; while (myIter1.next ()) { System.out.println ("Legi: "+ myIter1.legiNr() + " Name: " + myIter.name() ); } myIter1.close(); Benannte Iteratoren (named iterators): flexibler; Zuordnung über Namen kann vom SQLJ-Translator (= Preprocessor) geprüft werden Anwendungsentwicklung - 25 ISK 2003 SQLJ-Cursor (II): “positional iterators” #sql iterator MyPosIterType (int, String); MyPosIterType myIter2; int legiNr; String name; Beispiel-Tabelle: iskdb (legiNr, name) #sql myIter2 = { SELECT legiNr, name FROM iskdb }; while (true) { #sql { FETCH :myIter2 INTO :legiNr, :name }; if ( myIter2.endFetch() ) break; System.out.println ("Legi: "+ legiNr + " Name: " + name ); } myIter2.close(); Positionsiteratoren (positional iterators): Zuordnung allein über Position fehleranfälliger explizite FETCH-Anweisung nötig. ISK 2003 Anwendungsentwicklung - 26 Ausblick Java-Programmierung EJBs (siehe Vertiefung) z Standardisierte Laufzeitumgebung für in Java geschriebene Komponenten (Beans) Deklarative Bestimmung der Persistenzeigenschaften der Beans Standardfunktionalität schon durch Laufzeitumgebung implementiert Beispiele: Transaktionen, Persistenz, Object-Pooling,... Literatur: Seite des SQLJ-Konsortiums: www.sqlj.org “SQLJ Online Manual Oracle Version 8”, (lokal auf http://www.dbs.ethz.ch/~oracle/) NE U C. Türker: SQL:1999 & SQL:2003 - Objektrelationales SQL, SQLJ & SQL/XML, dpunkt-verlag, 2003. ISBN: 3-89864-219-4. [IH.03.8] G. Saake, K.-U. Sattler: “Datenbanken & Java. JDBC, SQLJ und ODMG”, dpunkt.verlag, 2000, (ISBN 3-932588-54-1) Anwendungsentwicklung - 27 ISK 2003 9.6 Verteilte Transaktionen Ziel dieses Unterkapitels: Einblick gewinnen, welche Probleme auftreten, wenn Transaktionsgarantien in Anwendungen gefordert werden, die mehrere Datenbanken umspannen und welche Lösungen es dazu gibt. Vorbereitung für Transaktionsverwaltung auf höherer Ebene und auf mehreren Ebenen (Kap. 11). Klienten, die Transaktionen über mehrere Datenbanken verlangen Generelles Szenario: DB1 ISK 2003 DB2 ... DBk Anwendungsentwicklung - 28 Korrektheit verteilter Transaktionen Bezeichnungen: Klienten definieren Transaktionen Ti = (ti1, ti2, ...tik) , die in Teilaufträge (= Subtransaktionen) tij an die betroffenen "KomponentenDatenbanken" zerlegt werden. Jede Subtransaktion ist eine Folge von Datenbankaktionen. Wir nehmen an, dass zwischen den Subtransaktionen einer Transaktion eine partielle Ordnung definiert ist, d.h. gewisse Subtransaktionen können und werden parallel ausgeführt. Zur Vereinfachung nehmen wir an, dass es pro Transaktion Ti nur eine Subtransaktion pro Komponentendatenbank gibt. Beispiel: t12= (R12(d),W12(d)) T1 = (t11, t12) mit t11= (R11(a), R11(b)) t22= (R22(d),W22(c)) T2 = (t21, t22) mit t21= (W21(a), W21(b)) DB1 DB2 Schedule: S1 = (R11(a),R11(b),W21(a),W21(b)) Serialisierungsordnung: T1 < T2 Schedule: S2 = (R22(d),R12(d),W22(c),W12(d)) Serialisierungsordnung: T2 < T1 Anwendungsentwicklung - 29 ISK 2003 Beobachtung: Der Ablauf im vorigen Beispiel ist nicht korrekt. Es gibt keinen seriellen Ablauf mit diesen Konfliktpaaren. ⇒ Wir müssen die Serialisierungsordnungen kennen und dafür sorgen, dass sie in allen Komponentendatenbanken gleich sind. Satz: Beim strikten 2PL stimmt die Serialisierungsreihenfolge mit der Commitreihenfolge überein. Beweisüberlegung: Eine Kante T1→T2 bedeutet beim S2PL, dass T2 die Ausführung erst dann beginnen und somit auch beenden kann, wenn T1 "committed" hat. Anwendung: Durch Vorgabe der gleichen Commit-Reihenfolge in allen KomponentenDatenbanken erzwingen wir die gleiche Serialisierungsreihenfolge und damit Korrektheit der (verteilten) Transaktionen Ti. Bedenken: Wir können Commits nicht erzwingen!! Integritätsverletzung einer Subtransaktion verhindert Commit, und führt dort auf ABORT lokale Deadlocks sind nicht vermeidbar, Systemabstürze kommen zu nicht geplanten Zeitpunkten,... ⇒ Wir brauchen atomares Commit für alle Komponenten-DB ⇒ ISK 2003 nächstes Unterkapitel Anwendungsentwicklung - 30 Atomarität verteilter Transaktionen Problem: Zusätzlich zu den Logging-Massnahmen der beteiligten Komponenten-Systeme ist ein verteiltes Protokoll notwendig, um das Commit oder Rollback der Transaktion in allen Systemen einheitlich durchzuführen. Es darf nicht passieren, dass ein System einen Commit-Logsatz für die Transaktion schreibt, während ein anderes System seinen Teil der Transaktion zurücksetzt. Zusätzlich müssen verschiedene Arten von Nachrichtenfehlern (verlorene Nachrichten, duplizierte Nachrichten) verkraftet werden. 2-Phasen-Commit-Protokoll (2PC) Grundprinzip: Eines der beteiligten Systeme wird zum Koordinator für den Ablauf des Commit einer Transaktion bestimmt. Es kann z.B. immer das System gewählt werden, von dem aus die Transaktion gestartet wurde. Die anderen Systeme werden als Agenten bezeichnet. Das Protokoll läuft dann in zwei Phasen ab: – Phase 1: Der Koordinator fragt alle Agenten, ob sie in der Lage sind, die Transaktion mit Commit zu beenden, und bittet die Agenten gleichzeitig, sich sowohl auf ein Commit als auch ein Rollback vorzubereiten (“Prepare”-Nachricht). Im positiven Fall gehen dann alle Agenten in den Zustand “prepared” über. – Phase 2: Aufgrund des Umfrageergebnisses trifft der Koordinator eine globale Entscheidung für die Transaktion und teilt diese allen Agenten mit. Nur wenn alle Agenten positiv geantwortet haben, kann der Koordinator eine CommitEntscheidung treffen. Andernfalls muss seine Entscheidung “Rollback” lauten. Anwendungsentwicklung - 31 ISK 2003 2 PC Hintergrundinformation In der Zeit zwischen dem Antworten eines Agenten und dem Erhalt der KoordinatorEntscheidung kann ein Agent keine eigenmächtige Entscheidung treffen. Insbesondere muss der Agent weiterhin alle Sperren für die Transaktion halten, da ein Rollback immer noch möglich ist. Da der Koordinator ausfallen kann oder die Nachricht mit seiner Entscheidung verloren gehen kann, können Agenten auf diese Weise in eine gewisse Blockierungssituation geraten, die sich sehr negativ auf die Leistung des betroffenen Systems auswirken kann. Man bezeichnet aus diesem Grund das 2PC auch als ein blockierendes Commit-Protokoll. (Man kann beweisen, dass es — unter Berücksichtigung aller möglichen Fehlerfälle — kein nichtblockierendes verteiltes Commit-Protokoll geben kann.) Bemerkung: • Das 2PC ist standardisiert (ISO/OSI, X/Open). Es wird von praktisch allen kommerziellen DBS unterstützt, wobei diese sowohl in die Koordinator- als auch in die Agentenrolle schlüpfen können. In vielen Systemumgebungen, insbesondere wenn verschiedene DBS zum Einsatz kommen, wird die Koordinatorrolle von einem TP-Monitor (Transaction Processing Monitor, -> Vertiefung) übernommen. ISK 2003 Anwendungsentwicklung - 32 Nachrichten und Zustände des 2PC im Erfolgsfall: Koordinator Agent 1 Agent 2 Schreibe Begin-Logsatz auf stabilen Speicher PREPARE-TO-COMMIT Undo/Redo auf stabilen Speicher OK Undo/Redo auf stabilen Speicher OK Schreibe Commit-Logsatz auf stabilen Speicher COMMIT EOT ACK EOT ACK Schreibe End-Logsatz auf stabilen Speicher Anwendungsentwicklung - 33 ISK 2003 Behandlung von Nachrichtenverlusten Falls bei einem Knoten eine — aufgrund des Protokolls — erwartete Nachricht nicht innerhalb einer bestimmten Frist eintrifft (sog. Timeout), wird angenommen, dass der Sender ausgefallen ist, und der Empfänger verhält sich wie bei einem Knotenausfall. Behandlung von Knotenausfällen Ausfallender Knoten Reaktion Koordinator Koordinator in Phase 1 (vor dem Schreiben des "Commit"-Logsatzes) Nach dem Restart: Wiederholung des Sendens der "Prepare"-Nachricht - Koordinator in Phase 2 (vor dem Schreiben des "End"-Logsatzes) Agent in Phase 1 (vor dem Schreiben des "Prepared"-Logsatzes) Agent in Phase 2 (vor dem EOT) ISK 2003 Reaktion des Agenten Falls noch nicht "prepared": Warten oder einseitiges Abort Falls bereits "prepared": Warten (Blockierung) oder ggf. andere Agenten fragen Nach dem Restart: - Vor dem EOT: Wiederholung des Sendens Warten (Blockierung) oder der "Commit"- oder ggf. andere Agenten fragen "Abort"-Nachricht - Nach dem EOT: Wiederholung des "Ack" bei wiederholtem Empfang der "Commit"- oder "Abort"-Nachricht Bei ausbleibendem Votum: Nach dem Restart: Wiederholung des Sendens Einseitiges Abort der "Prepare"-Nachricht Bei ausbleibendem "Ack": Nach dem Restart: Wiederholung des Sendens Warten auf Nachricht des Koordinators der "Commit"- oder (Wiederholte "Prepare"-Nachricht oder "Abort"-Nachricht (wiederholte) "Commit"/"Abort"-Nachricht) oder Nachfragen beim Koordinator Anwendungsentwicklung - 34 Anhang: Syntaxdiagramme für (E)SQL column_element CREATE TABLE ) ( table table_constraint , column_element ALTER TABLE table ADD table_constraint NULL DEFAULT column_element DROP TABLE column column_constraint value data_type table VARCHAR ( INTEGER ) ( INTEGER ) ( INTEGER ) BIT data_type INTEGER FLOAT , DECIMAL ( INTEGER ) INTEGER Anwendungsentwicklung - 35 ISK 2003 constraints NOT NULL UNIQUE column_constraint PRIMARY KEY referential_action REFERENCES ( table ( CHECK ) column search_condition ) , UNIQUE ( ) column PRIMARY KEY , table_constraint ( FOREIGN KEY ) column REFERENCES , table ( ) column referential_action CHECK referential_action ( search_condition ON UPDATE CASCADE ON DELETE SET NULL ) SET DEFAULT NO ACTION CREATE ASSERTION assertion CHECK ( search_condition ) query * ALL select_block SELECT expression DISTINCT , , FROM table correlation_var WHERE search_condition , GROUP BY HAVING search_condition column unordered_query select_block UNION INTERSECTION EXCEPT INTEGER ordered_query unordered_query DESC ORDER BY column ASC , data manipulation INSERT INTO ( table ) column , VALUES ( ) expression , ( unordered_query ) , NULL UPDATE table SET column = expression ( unordered_query WHERE DELETE FROM ISK 2003 table WHERE ) search_condition search_condition Anwendungsentwicklung - 38 expression expression column value * ( COUNT ) ALL column DISTINCT MAX ( ) expression MIN DISTINCT SUM ( ) expression AVG / + * Anwendungsentwicklung - 39 ISK 2003 search condition search_condition NOT expression BETWEEN NOT NOT AND expression expression _ expression string " LIKE " % column ( expression IS ) NULL NOT = <> expression ANY > expression >= ( unordered_query ALL , < OR <= AND expression value IN ( NOT EXISTS ISK 2003 ( ) ) unordered_query unordered_query ) Anwendungsentwicklung - 40 view, access rights WITH CHECK OPTION CREATE VIEW ( table ) column AS ordered_query , WITH GRANT OPTION GRANT access_right ON table TO PUBLIC user , GRANT OPTION FOR REVOKE access_right ON table FROM PUBLIC user , SELECT INSERT access_right UPDATE DELETE ALL PRIVILEGES Anwendungsentwicklung - 41 ISK 2003 embedded sql DECLARE cursor OPEN cursor FETCH cursor CURSOR FOR ordered_query : INTO variable , CLOSE cursor DELETE FROM table CURRENT OF WHERE cursor , NULL UPDATE table SET column = expression ( WHERE unordered_query CURRENT OF ) cursor