Übungsaufgaben zu Datenbankkonzepten: Transaktionen, Integrität, Trigger, Stored Procedures und Index

https://bildung.social/@oerinformatik/

https://oer-informatik.de/datenbankkonzepte-uebungsaufgaben

Datenbankkonzepte, Transaktionen, ACID, referentielle Integrität, Trigger, Stored Procedures, Index, Datenbank-Dump, Kollation, MariaDB, Übungsaufgaben, Prüfungsvorbereitung

tl/dr; (Bearbeitungszeit insgesamt 154 min, mehrere Aufgaben): Vier umfangreiche Übungsaufgaben zu Datenbankkonzepten – Aufgaben eines DBMS, Transaktionen und ACID, Autocommit, verlorene Updates und Deadlocks, Integritätsarten, referentielle Integrität mit Fehlermeldungen und Löschreihenfolge, ON DELETE, Trigger, Stored Procedures und Index, dazu der Betrieb: Leistungsmerkmale, Sicherheitsmaßnahmen, Ursachen eines langsamen Servers, Ausführungspläne, Dump, Umzug mit Importreihenfolge, verwaiste Datensätze und Kollation. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 27.10.2026)

Diese Übungsaufgaben gehören zum Artikel Datenbankkonzepte: Transaktionen, ACID, Integrität, Trigger, Stored Procedures und Index. Sie setzen die Artikel Tabellen anlegen mit der SQL-DDL und Constraints in der SQL-DDL voraus.

Hinweise zur Bearbeitung: Als FIA, FISY, FIDP, FIDV, ISE oder IKD musst Du zur Teil-2-Prüfung Aufgaben auf Kernkompetenz-Ebene lösen können, das sind Aufgabe 2.1 und Aufgabe 2.2. Von FISY und IKD wird zusätzlich erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1 und Aufgabe 3.2) keine Probleme bereiten. Schreib Deine Lösung zuerst vollständig auf, bevor Du die Beispiellösung aufklappst. Die SQL-Anweisungen sind in MariaDB-Notation (Version 10.11, Speicherengine InnoDB, Standardeinstellungen) formuliert; andere korrekte Lösungen sind ebenfalls richtig. In den Datenmodellen sind Primärschlüssel unterstrichen und Fremdschlüssel mit # gekennzeichnet. Heute ist Montag, der 19.10.2026.

Aufgabe 2.1: Bestellungen zuverlässig speichern im Fahrrad-Onlineshop (Kernkompetenz)

(ca. 55 min Bearbeitungszeit)

Du bist Auszubildende*r bei der CSB-Rad GmbH in Bielefeld, die über ihren Onlineshop Fahrräder und Komponenten verkauft und Rahmen nach Maß fertigen lässt. Am 14.10.2026 ist der Shop-Server mitten in einer Bestellung abgestürzt; danach stand in der Datenbank eine Bestellung ohne Positionen. Geschäftsführer Cem Sarıkaya möchte deshalb, dass Du die Datenbankzugriffe des Shops überprüfst. Werkstattleiter Bastian Ludwig wünscht sich außerdem, dass der Lagerbestand automatisch stimmt, und Buchhalterin Natalia Wróbel klagt, dass die Liste der Bestellungen eines Zeitraums immer langsamer lädt.

Die MariaDB-Datenbank csbrad enthält unter anderem folgende Tabellen:

  • kunde (kunde_id, kundentyp, firma, vorname, nachname, email, ust_idnr, …)

  • adresse (adresse_id, #kunde_id, typ, strasse, hausnr, plz, ort, land)

  • artikel (artikel_id, artikelnr, bezeichnung, #kategorie_id, netto_preis, lagerbestand, mindestbestand, konfigurierbar, aktiv)

  • bestellung (bestellung_id, #kunde_id, bestellt_am, status, zahlungsart, #rechnungsadresse_id, #lieferadresse_id, gutscheincode)

  • bestellposition (#bestellung_id, pos_nr, #artikel_id, menge, einzelpreis_netto, rabatt_prozent, #konfiguration_id)

  • fertigungsauftrag (auftrag_id, #(bestellung_id, pos_nr), #partner_id, status, …)

  • rechnung (rechnung_id, rechnungsnr, #bestellung_id, rechnungsdatum, faellig_am, bezahlt_am, mahnstufe)

  • versand (versand_id, #bestellung_id, dienstleister, sendungsnr, …)

Für die Fremdschlüssel gilt: adresse.kunde_id und bestellposition.bestellung_id sind mit ON DELETE CASCADE angelegt, alle anderen Fremdschlüssel ohne ON DELETE-Angabe (also RESTRICT). bestellung.status kann die Werte offen, bezahlt, in_fertigung, versandt, geliefert, storniert und retoure haben. Für bestellposition.menge gilt CHECK (menge > 0). Konfigurierbare Artikel (Rahmen nach Maß, gleichschließende Schlösser, Lastenrad) werden einzeln gefertigt und haben keinen Lagerbestand.

Auszug aus der Tabelle artikel:

artikel_id artikelnr bezeichnung netto_preis lagerbestand mindestbestand konfigurierbar aktiv
4 RAH-IND-01 Rahmen nach Maß (Stahl, pulverbeschichtet) 840.34 0 0 TRUE TRUE
7 LIC-SET-01 Lichtset Nabendynamo StVZO 75.63 48 20 FALSE TRUE
8 BRE-HYD-01 Hydraulische Scheibenbremse (Paar) 133.61 9 10 FALSE TRUE
9 RAD-EB-01 E-Bike „Altstadt“ Nabenmotor (Auslauf) 1595.80 1 0 FALSE FALSE

Auszug aus den Tabellen bestellung und bestellposition:

bestellung_id kunde_id bestellt_am status zahlungsart rechnungsadresse_id lieferadresse_id
3 3 2026-09-02 22:55:00 versandt PayPal 3 4
6 6 2026-10-12 19:03:00 bezahlt Kreditkarte 8 8
7 7 2026-10-01 07:45:00 storniert Vorkasse 9 9
8 2 2026-10-16 16:20:00 offen Rechnung 2 2
bestellung_id pos_nr artikel_id menge einzelpreis_netto
6 1 4 1 840.34
7 1 9 1 1595.80
8 1 8 2 133.61

Zu Bestellung 6 gibt es eine Rechnung und einen Fertigungsauftrag (für Position 1), zu Bestellung 3 einen Versand und eine Rechnung, zu den Bestellungen 7 und 8 weder Rechnung noch Versand noch Fertigungsauftrag. Kunde 2 ist Hans-Jürgen Kühn. Ihm gehören außer Bestellung 8 auch die bereits gelieferte Bestellung 2 mit der noch nicht bezahlten Rechnung RE-2026-00412 (Mahnstufe 1). Die Rechnung zu Bestellung 6 hat die Nummer RE-2026-00499. Die Spalte bestellung.kunde_id ist NOT NULL.

a) Die Shop-Software speichert ihre Daten nicht selbst in Dateien, sondern über das Datenbankmanagementsystem (DBMS) MariaDB. Nenne vier Aufgaben eines DBMS, die über das reine Speichern und Abfragen von Daten hinausgehen. (4 Punkte)

Je Aufgabe 1 Punkt, zum Beispiel:

  • Integrität sichern: nur zulässige, widerspruchsfreie Daten speichern (Schlüssel, Wertebereiche, Fremdschlüssel prüfen)

  • Transaktionen verwalten: zusammengehörige Änderungen ganz oder gar nicht ausführen (COMMIT/ROLLBACK)

  • Mehrbenutzerbetrieb synchronisieren: gleichzeitige Zugriffe über Sperren steuern

  • Zugriffskontrolle: Benutzer, Rollen und Rechte verwalten

  • Datensicherung und Wiederherstellung nach Ausfällen (Transaktionsprotokoll, Backup)

  • Datenkatalog (Data Dictionary) mit der Beschreibung aller Tabellen und Spalten führen

  • Benutzersichten (Views) bereitstellen

  • Abfragen optimieren (Indizes, Ausführungsplan)

  • Trigger und Stored Procedures ausführen

b) Mira Engel (kunde_id 3) bestellt heute um 10:05 Uhr zwei Lichtsets zum Aktionspreis von 68,07 € netto je Stück und eine hydraulische Scheibenbremse (133,61 €). Sie zahlt per PayPal; Rechnungsadresse ist die Adresse 3, Lieferadresse die Adresse 4. Die Bestellung erhält die Nummer 9. Bisher verringert die Shop-Software den Lagerbestand selbst.

ba) Beschreibe die vier Eigenschaften Atomicity, Consistency, Isolation und Durability einer Datenbanktransaktion. Gib zu jeder Eigenschaft an, was sie für das Speichern von Bestellung 9 bedeutet. (8 Punkte)

Je Eigenschaft 2 Punkte (1 Punkt Beschreibung, 1 Punkt Bezug zur Bestellung):

Eigenschaft Beschreibung Bedeutung für Bestellung 9
Atomicity (Atomarität, Abgeschlossenheit) Eine Transaktion ist eine unteilbare Einheit: Sie wird ganz oder gar nicht ausgeführt. Tritt ein Fehler auf, werden alle bereits ausgeführten Änderungen zurückgenommen. Bestellkopf, beide Positionen und die Verringerung beider Lagerbestände werden zusammen gespeichert. Stürzt der Server nach dem Bestellkopf ab, gibt es danach weder Bestellung noch Positionen – also keine „Bestellung ohne Positionen“ wie am 14.10.
Consistency (Konsistenz) Die Transaktion überführt die Datenbank von einem konsistenten Zustand in einen anderen konsistenten Zustand. Alle Integritätsbedingungen gelten vor und nach der Transaktion; wird eine verletzt, wird die Transaktion nicht festgeschrieben. Alle Positionen verweisen auf vorhandene Artikel und auf die Bestellung, Mengen sind größer als 0, die Adressen gehören zur Kundin, und der Lagerbestand passt zu den bestellten Mengen.
Isolation (Isolation, Abgrenzung) Gleichzeitig laufende Transaktionen beeinflussen sich nicht gegenseitig; das Ergebnis ist so, als wären sie nacheinander ausgeführt worden. Umgesetzt z. B. durch Sperrverfahren. Bestellt eine andere Person gleichzeitig Lichtsets, werden beide Verringerungen berücksichtigt; keine Bestellung sieht halbfertige Daten der anderen.
Durability (Dauerhaftigkeit) Nach dem erfolgreichen Abschluss (COMMIT) sind die Änderungen dauerhaft gespeichert, auch bei einem späteren Software- oder Hardwarefehler. Umgesetzt durch ein Transaktionsprotokoll (Redo Log). Hat Mira die Bestellbestätigung erhalten, ist die Bestellung auch nach einem Serverabsturz eine Sekunde später noch vorhanden.

bb) Erstelle die SQL-Anweisungen, mit denen Bestellung 9 als eine Transaktion gespeichert wird. Dazu gehören der Bestellkopf, beide Bestellpositionen und die Verringerung des Lagerbestands der beiden Artikel. bestellt_am soll den Zeitpunkt der Bestellung enthalten, der Status ist offen. Gib außerdem an, mit welcher Anweisung die Shop-Software die Transaktion abbricht, wenn eine der Anweisungen fehlschlägt. (6 Punkte)

Bei einem Fehler sendet die Shop-Software statt COMMIT die Anweisung ROLLBACK;. Alle Änderungen seit START TRANSACTION werden dann zurückgenommen.

Bewertung: START TRANSACTION (oder BEGIN) und COMMIT 1 Punkt, Bestellkopf 1 Punkt, zwei Positionen 1 Punkt, Lagerbestände mit lagerbestand = lagerbestand - menge 2 Punkte (1 Punkt, wenn feste Werte wie SET lagerbestand = 46 geschrieben werden), ROLLBACK 1 Punkt. Statt der festen Zeit ist NOW() richtig. Die bestellung_id darf weggelassen werden (AUTO_INCREMENT); dann braucht die Software für die Positionen LAST_INSERT_ID().

Nach dem COMMIT hat das Lichtset noch 46 Stück, die Bremse 8 Stück – sie liegt (wie schon vorher) unter dem Mindestbestand von 10.

bc) Ein älteres Importskript des früheren Dienstleisters überträgt Telefonbestellungen in die Datenbank. Es arbeitet im Autocommit-Modus und bricht beim ersten Fehler ab. Heute um 11:30 Uhr hat es für Felix Berg folgende Anweisungen gesendet:

Einen Artikel mit der Nummer 12 gibt es nicht. Analysiere den Ablauf: Gib für jede Anweisung an, ob sie ausgeführt wird und ob ihre Änderung danach in der Datenbank gespeichert ist. Erläutere anschließend, welches Problem entsteht und welche ACID-Eigenschaft das Skript nicht nutzt. (5 Punkte)

Anweisung ausgeführt? Änderung danach gespeichert?
(1) Bestellkopf 10
(2) Position 1 (Lichtset)
(3) Position 2 (Artikel 12)
(4) Lagerbestand Lichtset
Anweisung ausgeführt? Änderung danach gespeichert?
(1) Bestellkopf 10 ja ja (sofort festgeschrieben)
(2) Position 1 (Lichtset) ja ja (sofort festgeschrieben)
(3) Position 2 (Artikel 12) nein – Fehler 1452 Cannot add or update a child row: a foreign key constraint fails (… CONSTRAINT fk_pos_art …) nein
(4) Lagerbestand Lichtset nein – das Skript bricht vorher ab nein (Lagerbestand des Lichtsets bleibt unverändert)

Tabelle 2 Punkte (je zwei richtige Zeilen 1 Punkt).

Erläuterung (3 Punkte): Im Autocommit-Modus ist jede Anweisung eine eigene Transaktion und wird sofort festgeschrieben. Die Bestellung 10 steht deshalb unvollständig in der Datenbank: mit einer Position, ohne die zweite, und der Lagerbestand des verkauften Lichtsets ist nicht verringert. Lager und Bestellungen passen nicht mehr zusammen; die Bestellung würde so bearbeitet und berechnet. Genutzt werden müsste die Atomarität (Atomicity): Alle vier Anweisungen gehören in eine Transaktion, die bei einem Fehler mit ROLLBACK vollständig zurückgenommen wird. Dann wäre der Zustand wie vor dem Import, und die Bestellung könnte nach Korrektur der Artikelnummer neu übertragen werden. (Auch eine Antwort, die auf die Konsistenz abstellt, ist richtig, wenn sie begründet, dass der Zustand danach widersprüchlich ist.)

c) Bei der Prüfung der Datenbank stößt Du auf verschiedene Integritätsbedingungen und Fehlermeldungen.

ca) Ordne die folgenden Regeln der Shop-Datenbank jeweils einer Integritätsart zu (Entitätsintegrität, Bereichsintegrität, referentielle Integrität, benutzerdefinierte Integrität). (4 Punkte)

Regel Integritätsart
Zwei Artikel dürfen nicht dieselbe artikel_id haben; artikel_id ist nie leer.
bestellposition.menge muss größer als 0 sein.
Jede Bestellposition muss auf einen vorhandenen Artikel verweisen.
Kund*innen vom Typ haendler müssen eine USt-IdNr. haben, und nur aktive Artikel dürfen neu bestellt werden.

Je Zeile 1 Punkt:

Regel Integritätsart
Zwei Artikel dürfen nicht dieselbe artikel_id haben; artikel_id ist nie leer. Entitätsintegrität (PRIMARY KEY)
bestellposition.menge muss größer als 0 sein. Bereichs- bzw. Domänenintegrität (CHECK)
Jede Bestellposition muss auf einen vorhandenen Artikel verweisen. referentielle Integrität (FOREIGN KEY)
Kund*innen vom Typ haendler müssen eine USt-IdNr. haben, und nur aktive Artikel dürfen neu bestellt werden. benutzerdefinierte (semantische) Integrität – fachliche Regeln; die erste ließe sich als CHECK über zwei Spalten derselben Tabelle umsetzen, die zweite betrifft eine andere Tabelle und braucht einen Trigger oder Anwendungslogik

cb) Beschreibe, was referentielle Integrität am Beispiel der Tabellen artikel und bestellposition bedeutet, und erläutere damit die Ursache der Fehlermeldung bei Anweisung (3) aus Teilaufgabe bc). (4 Punkte)

Referentielle Integrität (2 Punkte): Zwischen artikel (1-Seite, Elterntabelle) und bestellposition (n-Seite, Kindtabelle mit dem Fremdschlüssel artikel_id) ist festgelegt, dass jeder Wert im Fremdschlüssel bestellposition.artikel_id als Primärschlüsselwert in artikel vorhanden sein muss. Das DBMS stellt so sicher, dass die Beziehungen zwischen den Datensätzen gültig bleiben: Eine Position kann nur für einen vorhandenen Artikel angelegt werden, und ein Artikel, auf den Positionen verweisen, kann nicht gelöscht (oder in seiner artikel_id geändert) werden.

Ursache der Fehlermeldung (2 Punkte): Anweisung (3) will eine Position mit artikel_id = 12 einfügen. In der Tabelle artikel gibt es keinen Datensatz mit dieser ID. Die neue Kindzeile hätte also keinen Elterndatensatz; MariaDB weist das INSERT deshalb mit Fehler 1452 („Cannot add or update a child row: a foreign key constraint fails“) ab. Die Anweisung ist syntaktisch richtig – der Fehler liegt in den Daten (falsche Artikelnummer am Telefon oder Artikel noch nicht angelegt).

cc) Nach einer Schulung sollen die Testdaten gelöscht werden: die Testkundin mit kunde_id = 99, ihre Rechnungsadresse 99 sowie ihre Bestellung 99 mit zwei Positionen (Rechnung, Versand und Fertigungsauftrag gibt es dazu nicht). Die Anweisung DELETE FROM kunde WHERE kunde_id = 99; liefert:

ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
(`csbrad`.`bestellung`, CONSTRAINT `fk_best_kunde` FOREIGN KEY (`kunde_id`) REFERENCES `kunde` (`kunde_id`))

Erläutere die Ursache dieser Fehlermeldung und gib an, in welcher Reihenfolge die Testdaten mit möglichst wenigen DELETE-Anweisungen gelöscht werden können. Begründe die Reihenfolge. (4 Punkte)

Ursache (2 Punkte): Die Kundin 99 ist Elterndatensatz der Bestellung 99, denn bestellung.kunde_id ist ein Fremdschlüssel auf kunde (Constraint fk_best_kunde, ohne ON DELETE-Regel, also RESTRICT). Würde die Kundin gelöscht, verwiese die Bestellung auf eine nicht mehr vorhandene Kundin; die referentielle Integrität wäre verletzt. Deshalb weist MariaDB das Löschen ab. Die DELETE-Anweisung selbst ist korrekt.

Reihenfolge (2 Punkte): zuerst die abhängigen Datensätze (Kinder), dann die Elterndatensätze:

Begründung: Die Bestellung verweist auf die Kundin und auf die Adresse 99 (rechnungsadresse_id, lieferadresse_id, beide RESTRICT). Sie muss deshalb vor Kundin und Adresse gelöscht werden. Ihre Positionen hängen über ON DELETE CASCADE an der Bestellung und verschwinden automatisch. Danach verweist nichts mehr auf die Kundin; beim Löschen der Kundin wird die Adresse per CASCADE mitgelöscht. Gleichwertig ist eine Lösung, die Positionen, Bestellung, Adresse und Kundin einzeln in dieser Reihenfolge löscht. Ein vorheriges DELETE FROM adresse WHERE kunde_id = 99; schlägt dagegen fehl, solange die Bestellung existiert.

cd) Cem Sarıkaya möchte wissen, wie sich die Fremdschlüssel bei echten Daten auswirken. Ermittle für die folgenden Anweisungen (jeweils einzeln auf dem oben abgebildeten Datenbestand ausgeführt), ob sie ausgeführt oder abgewiesen werden. Gib bei Ausführung an, was mit abhängigen Datensätzen passiert, bei Abweisung den Grund. (4 Punkte)

Anweisung ausgeführt oder abgewiesen? Folge bzw. Grund
DELETE FROM artikel WHERE artikel_id = 9;
DELETE FROM bestellung WHERE bestellung_id = 8;
DELETE FROM bestellung WHERE bestellung_id = 6;
DELETE FROM adresse WHERE adresse_id = 4;

Je Zeile 1 Punkt:

Anweisung ausgeführt oder abgewiesen? Folge bzw. Grund
DELETE FROM artikel WHERE artikel_id = 9; abgewiesen (1451) Position 1 der stornierten Bestellung 7 verweist auf den Artikel (fk_pos_art, RESTRICT). Der ausgelaufene Artikel bleibt als inaktiv gespeichert.
DELETE FROM bestellung WHERE bestellung_id = 8; ausgeführt Position 8/1 wird per ON DELETE CASCADE mitgelöscht; Rechnung, Versand oder Fertigungsauftrag, die das Löschen verhindern könnten, gibt es nicht.
DELETE FROM bestellung WHERE bestellung_id = 6; abgewiesen (1451) Die Rechnung RE-2026-00499 verweist auf die Bestellung (fk_re_best), und der Fertigungsauftrag verweist auf Position 6/1 (fk_fa_pos), die per CASCADE mitgelöscht werden müsste. Beide Fremdschlüssel haben RESTRICT.
DELETE FROM adresse WHERE adresse_id = 4; abgewiesen (1451) Bestellung 3 nutzt die Adresse als Lieferadresse (fk_best_ladr, RESTRICT).

Weil die Anweisung bei einem Fehler vollständig zurückgenommen wird, bleibt bei Bestellung 6 auch die Position erhalten.

ce) Hans-Jürgen Kühn hat die Löschung seines Kundenkontos verlangt. Ein Kollege schlägt vor, den Fremdschlüssel fk_best_kunde auf ON DELETE CASCADE umzustellen, damit DELETE FROM kunde WHERE kunde_id = 2; funktioniert. Begründe, ob Du diesem Vorschlag folgst. (3 Punkte)

Nein (1 Punkt für die Entscheidung, 2 Punkte für die Begründung). Mit CASCADE würden beim Löschen des Kunden auch alle seine Bestellungen (und darüber ihre Positionen) gelöscht – sofern nicht Rechnungen und Versanddaten das verhindern; bei Herrn Kühn verhindert die Rechnung zu Bestellung 2 das Löschen ohnehin. Bestellungen und Rechnungen sind aber Geschäftsunterlagen, die nach Handels- und Steuerrecht aufbewahrt werden müssen und für Umsatzauswertungen gebraucht werden; zudem ist Rechnung RE-2026-00412 noch offen (Mahnstufe 1). Eine automatische Löschweitergabe könnte versehentlich große Datenmengen vernichten. RESTRICT ist hier richtig. Dem Löschwunsch wird stattdessen nachgekommen, indem nicht mehr benötigte Daten (Newsletter, Telefonnummer, nicht mehr gebrauchte Adressen) gelöscht und die übrigen bis zum Ende der Aufbewahrungsfrist gesperrt und danach anonymisiert werden (Art. 17 Abs. 3 lit. b DSGVO erlaubt die Aufbewahrung zur Erfüllung rechtlicher Pflichten).

Eine begründete Entscheidung für CASCADE ist nicht vertretbar; eine begründete Entscheidung für SET NULL scheitert daran, dass bestellung.kunde_id NOT NULL ist (Teilpunkte für die Begründung möglich).

d) Bastian Ludwig möchte, dass der Lagerbestand auch dann stimmt, wenn Bestellungen über andere Wege als den Shop (Importskript, Händlerportal) in die Datenbank gelangen. Ihr entscheidet Euch für Trigger.

da) Beschreibe, was ein Trigger ist. (2 Punkte)

Ein Trigger ist eine besondere Art einer gespeicherten Prozedur, die zu einer Tabelle gehört und automatisch vom DBMS ausgeführt wird, wenn auf dieser Tabelle ein bestimmtes Ereignis eintritt (INSERT, UPDATE oder DELETE), wahlweise vor (BEFORE) oder nach (AFTER) der Änderung (1 Punkt). Er wird nicht von einer Anwendung aufgerufen und eignet sich, um Regeln zu prüfen, abgeleitete Werte nachzuführen oder Änderungen zu protokollieren (1 Punkt).

db) Erstelle einen Trigger trg_bestellposition_lager, der nach dem Einfügen einer Bestellposition den Lagerbestand des bestellten Artikels um die bestellte Menge verringert. Konfigurierbare Artikel haben keinen Lagerbestand und sollen nicht verändert werden. Ermittle außerdem, wie sich die Lagerbestände ändern, wenn Bestellung 9 aus Teilaufgabe b) mit einer zusätzlichen dritten Position (ein Rahmen nach Maß, Artikel 4) eingefügt wird und die Shop-Software den Bestand nicht mehr selbst ändert. (5 Punkte)

Bewertung: CREATE TRIGGER … AFTER INSERT ON bestellposition FOR EACH ROW 2 Punkte, UPDATE mit NEW.menge und NEW.artikel_id 1 Punkt, Bedingung für konfigurierbare Artikel 1 Punkt. Da der Rumpf nur aus einer Anweisung besteht, sind BEGIN … END und DELIMITER nicht zwingend. Auch ein BEFORE INSERT-Trigger ist richtig; AFTER hat den Vorteil, dass der Bestand nur geändert wird, wenn die Position tatsächlich gespeichert werden konnte.

Lagerbestände (1 Punkt): Der Trigger läuft für jede eingefügte Zeile einmal. Lichtset 48 → 46, Bremse 9 → 8, Rahmen nach Maß bleibt bei 0 (konfigurierbar). Da der Trigger in derselben Transaktion läuft wie das INSERT, werden die Bestandsänderungen bei einem ROLLBACK der Bestellung ebenfalls zurückgenommen.

dc) Wird eine Bestellung storniert, bleibt der Lagerbestand bisher zu niedrig. Erstelle einen Trigger trg_bestellung_storno, der beim Wechsel einer Bestellung in den Status storniert die Mengen aller Positionen nicht konfigurierbarer Artikel wieder dem Lagerbestand zurechnet. Ermittle den Lagerbestand der Bremse (Artikel 8, Ausgangsbestand 9 Stück), nachdem Bestellung 8 storniert und versehentlich ein zweites Mal mit status = 'storniert' gespeichert wurde. (5 Punkte)

Bewertung: AFTER UPDATE ON bestellung FOR EACH ROW 1 Punkt, Bedingung mit NEW.status und OLD.status 2 Punkte, Rückbuchung über die Positionen der Bestellung 1 Punkt. Eine Lösung mit Unterabfrage ist ebenso richtig:

Lagerbestand (1 Punkt): Beim ersten Speichern wechselt der Status von offen zu storniert; die 2 Bremsen werden zurückgebucht: 9 → 11. Beim zweiten Speichern ist OLD.status bereits storniert, die Bedingung ist falsch, der Bestand bleibt bei 11. Ohne die Prüfung von OLD.status würde doppelt zurückgebucht (13). Der Trigger ändert die Tabelle artikel, nicht die auslösende Tabelle bestellung – das ist in MariaDB erlaubt.

e) Natalia Wróbel ruft für den Monatsabschluss regelmäßig alle Bestellungen eines Zeitraums ab (… WHERE bestellt_am BETWEEN … AND …). Die Tabelle bestellung enthält inzwischen über 200.000 Zeilen.

ea) Beschreibe, wozu Spalten in Tabellen indiziert werden. (2 Punkte)

Ein Index ist eine zusätzliche, sortierte Zugriffsstruktur (in InnoDB ein B-Baum) über die Werte einer oder mehrerer Spalten – ähnlich dem Stichwortverzeichnis eines Buchs (1 Punkt). Er dient dazu, die Suche nach Datensätzen (WHERE), das Verknüpfen (JOIN) und das Sortieren (ORDER BY) zu beschleunigen, weil das DBMS nicht mehr jede Zeile der Tabelle lesen muss; das bringt vor allem bei großen Datenmengen deutliche Geschwindigkeitsvorteile (1 Punkt).

eb) Erstelle für die Tabelle bestellung einen Index idx_bestellung_bestellt_am auf die Spalte bestellt_am. (2 Punkte)

Gleichwertig: ALTER TABLE bestellung ADD INDEX idx_bestellung_bestellt_am (bestellt_am);

Bewertung: CREATE INDEX mit Namen 1 Punkt, ON bestellung (bestellt_am) 1 Punkt.

ec) Ein Kollege schlägt vor, „sicherheitshalber“ jede Spalte jeder Tabelle zu indizieren. Erläutere zwei Gründe, die dagegen sprechen, und nenne eine Spalte der Tabelle bestellung, für die sich kein eigener Index lohnt. (3 Punkte)

Je Grund 1 Punkt:

  • Jeder Index muss bei jedem INSERT, UPDATE und DELETE mitgepflegt werden. Schreibvorgänge – im Shop jede Bestellung – werden dadurch langsamer, und es werden mehr Sperren gehalten.

  • Jeder Index belegt zusätzlichen Speicherplatz (und Platz im Arbeitsspeicher-Puffer, Zeit bei der Datensicherung).

  • Viele Indizes nützen nichts, weil Abfragen sie nicht verwenden; für Primärschlüssel, UNIQUE-Spalten und Fremdschlüssel legt MariaDB ohnehin automatisch einen Index an.

Spalte ohne lohnenden eigenen Index (1 Punkt): zum Beispiel status oder zahlungsart (nur wenige verschiedene Werte, ein Index grenzt die Suche kaum ein), gutscheincode (wird kaum gesucht). Nicht richtig sind bestellung_id, kunde_id, rechnungsadresse_id, lieferadresse_id – sie haben bereits automatisch einen Index.

Aufgabe 2.2: Sofortbuchung ohne Doppelbuchung in einer Mitfahr-App (Kernkompetenz)

(ca. 46 min Bearbeitungszeit)

Du bist Auszubildende*r und arbeitest im FIA-Projektteam der Mitfahr-App RatzFahrt des Ratz und Rübe Berufskollegs in Bielefeld mit. Auszubildende bieten darin Fahrten zu den Berufsschultagen an oder suchen Mitfahrgelegenheiten. Bisher muss jede Mitfahranfrage von der Fahrerin oder dem Fahrer bestätigt werden. Projektleiter Thomas Becker wünscht sich eine Sofortbuchung: Ist sie für ein Angebot eingeschaltet, werden dessen freie Plätze ohne Rückfrage vergeben, solange welche frei sind. Oksana Melnyk aus dem Projektteam hat einen ersten Entwurf erstellt, die Datenschutzbeauftragte Andrea Wolf achtet darauf, dass Minderjährige nur mit Einwilligung der Erziehungsberechtigten mitfahren.

Die MariaDB-Datenbank ratzfahrt enthält unter anderem folgende Tabellen:

  • nutzer (nutzer_id, pseudonym, vorname, nachname, email_schule, geburtsdatum, #klasse_id, rolle, einwilligung_eltern, fuehrerschein, aktiv)

  • haltepunkt (haltepunkt_id, name, ort, plz, entfernung_km)

  • angebot (angebot_id, #fahrer_id, #fahrzeug_id, #haltepunkt_id, richtung, datum, abfahrt, freie_plaetze, kostenbeitrag_eur, status, sofortbuchung)

  • buchung (buchung_id, #angebot_id, #mitfahrer_id, #gesuch_id, status, angefragt_am, beantwortet_am)

angebot.status kann die Werte offen, voll, abgesagt und durchgefuehrt haben, buchung.status die Werte angefragt, bestaetigt, abgelehnt und storniert. Für buchung gilt UNIQUE (angebot_id, mitfahrer_id): Eine Person kann dasselbe Angebot nur einmal anfragen. Die Spalte sofortbuchung (BOOLEAN) ist neu; im Testsystem ist sie für die Angebote 3 und 4 eingeschaltet. einwilligung_eltern enthält das Datum der Einwilligung oder NULL. Der Kostenbeitrag darf höchstens 0,10 € je km Entfernung des Haltepunkts zur Schule betragen.

Auszüge aus dem Testdatenbestand:

nutzer_id vorname nachname geburtsdatum einwilligung_eltern
1 Ben Richter 2008-01-17 NULL
2 Aylin Kaya 2009-06-02 2026-09-03
3 Oksana Melnyk 2003-04-28 NULL
4 Lukas Hofmann 2006-10-09 NULL
7 Marie Schulz 2004-08-14 NULL
8 Lina Hartwig 2008-11-23 NULL
angebot_id fahrer_id haltepunkt_id richtung datum abfahrt freie_plaetze kostenbeitrag_eur status sofortbuchung
3 6 3 zur Schule 2026-10-19 07:10:00 0 1.50 voll TRUE
4 7 2 zur Schule 2026-10-20 06:50:00 3 1.70 offen TRUE
5 9 4 zur Schule 2026-10-22 06:45:00 6 2.50 offen FALSE
buchung_id angebot_id mitfahrer_id status
5 4 2 angefragt
haltepunkt_id name ort entfernung_km
2 Park & Ride am Bahnhof Herford 17.9
4 Busbahnhof Bad Salzuflen 19.4

a) Oksanas erster Entwurf läuft im Backend der App. Für jede Sofortbuchung sendet er im Autocommit-Modus nacheinander:

In einem Lasttest hat Angebot 4 nur noch einen freien Platz. Oksana (Sitzung A) und Lukas (Sitzung B) buchen fast gleichzeitig; die Anweisungen kommen in dieser Reihenfolge bei MariaDB an:

Zeit Sitzung A (Oksana, nutzer 3) Sitzung B (Lukas, nutzer 4) gelesener Wert frei freie_plaetze in der Datenbank danach bestätigte neue Buchungen für Angebot 4
t1 Schritt 1 A:
t2 Schritt 1 B:
t3 Schritt 2 –
t4 Schritt 3 –
t5 Schritt 2 –
t6 Schritt 3 –

aa) Analysiere den Ablauf und fülle die Tabelle aus. (4 Punkte)

Zeit Sitzung A (Oksana, nutzer 3) Sitzung B (Lukas, nutzer 4) gelesener Wert frei freie_plaetze in der Datenbank danach bestätigte neue Buchungen für Angebot 4
t1 Schritt 1 A: 1 1 0
t2 Schritt 1 B: 1 1 0
t3 Schritt 2 (A bucht, da 1 > 0) – 1 1
t4 Schritt 3: SET freie_plaetze = 0 – 0 1
t5 Schritt 2 (B bucht, da 1 > 0) – 0 2
t6 Schritt 3: SET freie_plaetze = 0 – 0 2

Bewertung: gelesene Werte 1 Punkt, Spalte freie_plaetze 1 Punkt, Spalte Buchungen 1 Punkt, Ergebnis (2 Buchungen für 1 Platz, Bestand 0 statt −1 bzw. statt Ablehnung) 1 Punkt.

ab) Erläutere das Problem, das in diesem Ablauf auftritt, und nenne die ACID-Eigenschaft, die verletzt ist. (3 Punkte)

Problem (2 Punkte): Beide Sitzungen lesen den Wert 1, bevor die andere ihn verändert hat, und entscheiden auf Grundlage eines veralteten Werts. Sitzung B überschreibt in t6 den Wert von A mit einem selbst berechneten Wert, statt die Änderung von A zu berücksichtigen (Lost Update, verlorenes Update). Ergebnis: Für einen Platz gibt es zwei bestätigte Buchungen – das Angebot ist überbucht, eine Person steht morgen früh vergeblich am Haltepunkt. Die Datenbank zeigt 0 freie Plätze und erkennt den Fehler nicht.

ACID-Eigenschaft (1 Punkt): Isolation – die beiden gleichzeitig laufenden Vorgänge beeinflussen sich gegenseitig; nacheinander ausgeführt hätte B den Wert 0 gelesen und nicht gebucht. (Zusätzlich fehlt die Atomarität, weil die drei Schritte nicht in einer Transaktion stehen; als einzige Nennung reicht sie nicht.)

ac) Erstelle eine korrigierte Fassung für Oksanas Buchung (nutzer 3) als Transaktion, die eine Überbuchung zuverlässig verhindert. Erläutere kurz, warum Lukas’ gleichzeitige Buchung mit Deiner Lösung nicht mehr zum Zug kommt. (6 Punkte)

Lösung mit bedingtem UPDATE (4 Punkte):

Gleichwertig ist eine Lösung mit sperrendem Lesen:

Bewertung: Transaktion mit START TRANSACTION/COMMIT (und ROLLBACK im Fehlerfall) 1 Punkt, Sperre durch FOR UPDATE oder bedingtes UPDATE 2 Punkte, Rechnen in der Datenbank (freie_plaetze - 1) statt Zurückschreiben eines Werts 1 Punkt.

Erläuterung (2 Punkte): Das UPDATE (bzw. SELECT … FOR UPDATE) setzt eine Schreibsperre auf die Zeile von Angebot 4, die bis zum COMMIT gehalten wird. Lukas’ Sitzung muss an derselben Stelle warten. Nach Oksanas COMMIT liest sie den aktuellen, festgeschriebenen Wert 0: Das bedingte UPDATE ändert keine Zeile (ROW_COUNT() = 0), bzw. das SELECT … FOR UPDATE liefert 0 – das Backend bricht mit ROLLBACK ab und meldet „ausgebucht“. Die Transaktionen laufen dadurch an dieser Stelle nacheinander ab.

Eine Transaktion ohne Sperre (nur START TRANSACTION … COMMIT um den alten Entwurf) reicht nicht: Das einfache SELECT liest in MariaDB einen Schnappschuss, beide lesen weiterhin 1 (höchstens 3 Punkte).

ad) Nach der Korrektur meldet das Backend gelegentlich den Fehler ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction. Beobachtet wurde er, als Oksana ihre bestätigte Buchung 6 stornierte, während Marie Schulz gleichzeitig ihr Angebot 4 absagte:

Zeit Transaktion A (Oksana storniert) Transaktion B (Marie sagt ab)
t1 START TRANSACTION;
UPDATE buchung SET status = 'storniert' WHERE buchung_id = 6;
t2 START TRANSACTION;
UPDATE angebot SET status = 'abgesagt' WHERE angebot_id = 4;
t3 UPDATE angebot SET freie_plaetze = freie_plaetze + 1 WHERE angebot_id = 4;
t4 UPDATE buchung SET status = 'storniert' WHERE angebot_id = 4 AND status IN ('angefragt', 'bestaetigt');

Erläutere anhand des Ablaufs, was ein Deadlock ist, wie MariaDB darauf reagiert und wie sich das Problem vermeiden lässt. (4 Punkte)

Ablauf und Begriff (2 Punkte): In t1 sperrt A die Buchung 6, in t2 sperrt B das Angebot 4. In t3 will A das Angebot 4 ändern und wartet auf die Sperre von B. In t4 will B alle Buchungen zu Angebot 4 ändern, darunter Buchung 6, und wartet auf die Sperre von A. Beide Transaktionen warten gegenseitig auf eine Sperre, die die jeweils andere hält – keine kann jemals weiterarbeiten. Diese gegenseitige Blockade heißt Deadlock (Verklemmung).

Reaktion von MariaDB (1 Punkt): InnoDB erkennt den Zyklus, wählt eine Transaktion als „Opfer“, bricht sie mit Fehler 1213 ab und nimmt sie vollständig zurück. Die andere erhält die Sperre und läuft weiter. Das Backend muss den Fehler abfangen und die abgebrochene Transaktion wiederholen.

Vermeidung (1 Punkt), zum Beispiel: Alle Abläufe sperren die Tabellen bzw. Datensätze in derselben Reihenfolge (immer zuerst das Angebot, dann die Buchungen – A müsste also zuerst angebot ändern). Außerdem helfen kurze Transaktionen und eine automatische Wiederholung nach Fehler 1213.

b) Damit Web-App und die geplanten Apps für Android und iOS dieselbe Logik nutzen, soll die Sofortbuchung als Stored Procedure in der Datenbank liegen.

ba) Beschreibe, was man unter einer Stored Procedure versteht. (2 Punkte)

Eine Stored Procedure (gespeicherte Prozedur) ist eine benannte Folge von SQL-Anweisungen, die im Datenbankmanagementsystem gespeichert ist (1 Punkt). Clients rufen sie mit einem einzigen Befehl (CALL name(…)) auf; sie kann Parameter übernehmen und zurückgeben, Variablen, Verzweigungen, Schleifen und Fehlerbehandlung enthalten und so ganze Abläufe einschließlich Transaktionen auf dem Datenbankserver ausführen (1 Punkt).

bb) Nenne drei Vorteile, die die Stored Procedure für RatzFahrt gegenüber Oksanas bisheriger Lösung im Backend hat. (3 Punkte)

Je Vorteil 1 Punkt, zum Beispiel:

  • Die Buchungslogik liegt an einer Stelle; Web-App, Android- und iOS-App verhalten sich gleich und können die Prüfungen (Einwilligung, eigenes Angebot, freie Plätze) nicht „vergessen“.

  • Transaktion und Sperre sind fest eingebaut; ein Fehler im App-Code kann keine Überbuchung mehr verursachen.

  • Weniger Netzwerkverkehr: ein Aufruf statt mehrerer Einzelanweisungen; die Sperre wird nur kurz gehalten.

  • Sicherheit und Datenschutz: Das App-Konto erhält nur das Recht EXECUTE auf die Prozedur, aber keine direkten Schreibrechte auf buchung und angebot und keinen Lesezugriff auf Geburtsdaten; Parameter werden nicht als SQL-Text zusammengesetzt (Schutz vor SQL-Injection).

Oksanas Entwurf der Prozedur (Zeilen mit (1) bis (3) sind noch leer):

bc) Ergänze die Anweisungen für die Zeilen (1), (2) und (3). (3 Punkte)

Je Zeile 1 Punkt:

Der Handler muss nach den Variablen deklariert werden (MariaDB verlangt die Reihenfolge Variablen – Handler – Anweisungen). EXIT beendet die Prozedur nach dem Handler; CONTINUE wäre falsch, weil die Prozedur sonst nach dem Fehler weiterliefe und am Ende COMMIT ausführen würde. Wer den Fehler zusätzlich an das Backend weitergeben möchte, ergänzt RESIGNAL; (dann wird p_ergebnis allerdings nicht zurückgegeben). Das COMMIT in (3) beendet die Transaktion auch in den Zweigen ohne Buchung und gibt die Sperre auf das Angebot frei.

bd) Die vollständige Prozedur wird auf dem oben abgebildeten Testdatenbestand angelegt. Danach werden die folgenden Aufrufe nacheinander ausgeführt. Ermittle jeweils den Wert von @e und die Anzahl freier Plätze des aufgerufenen Angebots nach dem Aufruf. (5 Punkte)

Nr. Aufruf @e freie_plaetze danach
1 CALL sofortbuchung(4, 3, @e);
2 CALL sofortbuchung(4, 8, @e);
3 CALL sofortbuchung(4, 7, @e);
4 CALL sofortbuchung(4, 2, @e);
5 CALL sofortbuchung(3, 1, @e);

Je Zeile 1 Punkt:

Nr. Aufruf @e freie_plaetze danach
1 CALL sofortbuchung(4, 3, @e); bestaetigt – Oksana (23) bucht; neue Buchung 6 2
2 CALL sofortbuchung(4, 8, @e); Einwilligung fehlt – Lina ist 17, einwilligung_eltern ist NULL 2
3 CALL sofortbuchung(4, 7, @e); eigenes Angebot – Marie ist die Fahrerin 2
4 CALL sofortbuchung(4, 2, @e); Fehler: nichts gebucht – Aylin (17) hat eine Einwilligung, die Plätze werden auf 1 verringert, das INSERT verletzt aber UNIQUE (angebot_id, mitfahrer_id), weil es schon Buchung 5 (angefragt) gibt. Der Handler nimmt mit ROLLBACK auch die Verringerung zurück. 2
5 CALL sofortbuchung(3, 1, @e); nicht sofort buchbar – Angebot 3 hat den Status voll (die Prüfung auf offen kommt vor der Prüfung der Plätze) 0

Aufruf 4 zeigt die Atomarität: Ohne Transaktion und Handler wäre ein Platz „verschwunden“, ohne dass jemand gebucht hat.

be) Notiere den Aufruf, mit dem Lukas Hofmann (nutzer 4) im Anschluss an die Aufrufe aus bd) Angebot 4 sofort bucht, und die Anweisung, mit der das Backend das Ergebnis abfragt. Gib das Ergebnis an. (2 Punkte)

(1 Punkt) Ergebnis (1 Punkt): bestaetigt; Lukas (20) erhält eine neue Buchung, Angebot 4 hat danach noch 1 freien Platz und bleibt offen. Aus Java würde die Prozedur über ein CallableStatement ({call sofortbuchung(?, ?, ?)}) mit registriertem OUT-Parameter aufgerufen.

c) Andrea Wolf hat festgestellt, dass Angebote mit zu hohem Kostenbeitrag gespeichert werden können (zum Beispiel Angebot 5). Die Obergrenze von 0,10 € je km soll künftig die Datenbank selbst durchsetzen.

ca) Erstelle einen Trigger trg_angebot_kosten, der das Speichern eines neuen Angebots mit einer Fehlermeldung abweist, wenn der Kostenbeitrag über 0,10 € je km der Entfernung des Haltepunkts liegt. Gib an, was beim Einfügen eines neuen Angebots von Niklas Fischer ab Bad Salzuflen (Haltepunkt 4) mit einem Kostenbeitrag von 2,00 € passiert. (5 Punkte)

Bewertung: BEFORE INSERT ON angebot FOR EACH ROW 1 Punkt, Entfernung des Haltepunkts über NEW.haltepunkt_id ermitteln 1 Punkt, Vergleich mit NEW.kostenbeitrag_eur 1 Punkt, Abweisen mit SIGNAL 1 Punkt. Statt der Variablen ist eine Unterabfrage im IF richtig. Ein AFTER-Trigger mit SIGNAL würde das INSERT zwar auch zurücknehmen; BEFORE ist aber der übliche Zeitpunkt für Prüfungen.

Ergebnis (1 Punkt): Höchstbetrag ab Bad Salzuflen: 19,4 km · 0,10 €/km = 1,94 €. 2,00 € liegen darüber; der Trigger löst den Fehler ERROR 1644 (45000): Kostenbeitrag über 0,10 EUR je km aus, das Angebot wird nicht gespeichert. Mit 1,90 € würde es gespeichert.

cb) Erläutere, warum sich diese Regel nicht mit einem CHECK-Constraint in der Tabelle angebot umsetzen lässt, und warum Angebot 5 nach dem Anlegen des Triggers weiterhin mit 2,50 € gespeichert ist. Nenne, was zusätzlich nötig ist, damit die Regel lückenlos gilt. (3 Punkte)

  • Ein CHECK-Constraint kann nur Werte der eigenen Zeile prüfen. Die Entfernung steht aber in der Tabelle haltepunkt; Unterabfragen sind in CHECK nicht erlaubt (1 Punkt).

  • Ein Trigger wird nur durch künftige Ereignisse ausgelöst. Angebot 5 wurde vor dem Anlegen des Triggers gespeichert und wird nicht nachträglich geprüft (1 Punkt).

  • Zusätzlich nötig (1 Punkt): ein entsprechender BEFORE UPDATE-Trigger, damit ein Angebot nicht nachträglich auf einen zu hohen Betrag geändert werden kann (auch ein Wechsel des Haltepunkts), und eine einmalige Bereinigung des Bestands, z. B. UPDATE angebot a JOIN haltepunkt h ON h.haltepunkt_id = a.haltepunkt_id SET a.kostenbeitrag_eur = ROUND(h.entfernung_km * 0.10, 2) WHERE a.kostenbeitrag_eur > h.entfernung_km * 0.10; (Angebot 5 → 1,94 €) nach Rücksprache mit Niklas Fischer.

cc) Jonas Wolff, ein Mitschüler aus dem Projektteam, möchte das Setzen des Status voll aus der Prozedur in einen Trigger verlagern, damit es bei jeder Änderung der freien Plätze greift. Sein Trigger lässt sich anlegen, doch danach schlägt jede Sofortbuchung fehl:

ERROR 1442 (HY000): Can't update table 'angebot' in stored function/trigger
because it is already used by statement which invoked this stored function/trigger

Erläutere den Fehler und korrigiere den Trigger. (4 Punkte)

Erläuterung (2 Punkte): Der Trigger wird durch ein UPDATE auf angebot ausgelöst und versucht selbst, dieselbe Tabelle angebot mit UPDATE zu ändern. Das ist in MariaDB verboten, weil die auslösende Anweisung die Tabelle gerade bearbeitet (und der Trigger sich sonst selbst immer wieder auslösen könnte). Der Fehler bricht die auslösende Anweisung ab – in der Prozedur greift der Handler, deshalb scheitert jede Sofortbuchung.

Korrektur (2 Punkte): Werte der gerade geänderten Zeile werden in einem BEFORE-Trigger über NEW gesetzt:

Bewertung: BEFORE UPDATE 1 Punkt, SET NEW.status = 'voll' mit Bedingung 1 Punkt. Die Bedingung NEW.status = 'offen' verhindert, dass ein abgesagtes Angebot ohne freie Plätze wieder als voll erscheint. Sinnvolle Ergänzung: Wird ein Platz durch Stornierung wieder frei, ELSEIF NEW.freie_plaetze > 0 AND OLD.status = 'voll' AND NEW.status = 'voll' THEN SET NEW.status = 'offen';. Die zweite UPDATE-Anweisung in der Prozedur kann danach entfallen.

d) Zum Abschluss sollst Du für das Projekthandbuch die Transaktionseigenschaften an RatzFahrt verdeutlichen.

da) Ordne jeder Aussage die ACID-Eigenschaft zu, die sie beschreibt. (4 Punkte)

Aussage ACID-Eigenschaft
Hat Lukas die Bestätigung seiner Sofortbuchung erhalten, ist die Buchung auch nach einem Neustart des Datenbankservers noch vorhanden.
Schlägt das Speichern der Buchung fehl, wird auch die Verringerung der freien Plätze zurückgenommen.
Zwei gleichzeitige Sofortbuchungen führen zum selben Ergebnis, als wären sie nacheinander ausgeführt worden.
Nach jeder Buchung gilt: freie_plaetze ist nie negativ, jede Buchung verweist auf ein vorhandenes Angebot, und es gibt nie mehr bestätigte Buchungen als Sitzplätze.

Je Zeile 1 Punkt: Durability (Dauerhaftigkeit) – Atomicity (Atomarität) – Isolation – Consistency (Konsistenz).

db) Während eines Lasttests fällt der Datenbankserver aus. Erläutere, was nach dem Neustart mit einer Sofortbuchung geschehen ist, deren Prozedur (1) unmittelbar vor und (2) unmittelbar nach dem COMMIT unterbrochen wurde, und wie MariaDB das sicherstellt. (3 Punkte)

    1. Vor dem COMMIT: Die Transaktion war nicht abgeschlossen. Beim Neustart nimmt InnoDB alle ihre Änderungen zurück (Atomarität; mit Hilfe des Undo Log). Weder die Buchung noch die Verringerung der Plätze sind vorhanden; die App hat keine Bestätigung erhalten, die Person muss erneut buchen (1 Punkt).
    1. Nach dem COMMIT: Die Transaktion war bestätigt. Buchung und verringerte Platzzahl sind nach dem Neustart vorhanden, auch wenn sie im Moment des Absturzes noch nicht in die eigentlichen Datendateien geschrieben waren (Dauerhaftigkeit; 1 Punkt).
  • Umsetzung (1 Punkt): MariaDB schreibt jede Änderung zuerst in ein Transaktionsprotokoll (Redo Log) und gilt ein COMMIT erst als erfolgreich, wenn dieser Eintrag auf dem Datenträger steht (Standard innodb_flush_log_at_trx_commit = 1). Beim Neustart werden bestätigte Transaktionen aus dem Protokoll wiederhergestellt und unbestätigte zurückgenommen (Crash Recovery).

Aufgabe 3.1: Den Datenbankserver einer Freizeit-App betreiben (Profilkompetenz)

(ca. 31 min Bearbeitungszeit)

Du bist Auszubildende*r bei der Let’s Meet GmbH in Bielefeld und unterstützt Yusuf Demir, den Leiter der Entwicklung, bei der Betreuung des Datenbankservers db01. Auf dem Linux-Server im Serverschrank eines Rechenzentrums läuft MariaDB mit der Datenbank letsmeet (rund 41.800 Konten, im Schnitt 3.100 neue Aktivitäten im Monat). Der Server ist nur aus dem internen Netz erreichbar, der App-Server nutzt einen eigenen Datenbankbenutzer. Gesichert wird jede Nacht vollständig, dazu läuft das Binärlog. Clara Neumann, die Geschäftsführerin, möchte vor dem geplanten Umzug zu einem Cloud-Anbieter wissen, wie gut die Datenbank aufgestellt ist.

a) Für den Umzug vergleicht Yusuf Demir mehrere relationale Datenbanksysteme. Erläutere die beiden Leistungsmerkmale „Indexierung“ und „Sperrmechanismen (Locking)“ und beschreibe jeweils, warum das Merkmal für Let’s Meet wichtig ist. (6 Punkte)

Je Merkmal 2 Punkte für die Erläuterung und 1 Punkt für den Bezug zur Situation:

  • Indexierung: Ein Index ist eine zusätzliche, sortierte Zugriffsstruktur (meist B-Baum) über eine oder mehrere Spalten. Das DBMS findet damit Datensätze, ohne die ganze Tabelle zu lesen; Suchen, Verknüpfen und Sortieren werden bei großen Tabellen deutlich schneller. Leistungsfähige Systeme bieten mehrere Indexarten (z. B. zusammengesetzte, Volltext- oder räumliche Indizes) und einen Optimierer, der sie gut nutzt. Bezug: Die App sucht ständig in Tabellen mit Zehntausenden Konten und Hunderttausenden Aktivitäten (Anmeldung per E-Mail, Suche nach Aktivitäten in der Nähe und nach Datum).

  • Sperrmechanismen: Sperren verhindern Konflikte, wenn mehrere Benutzer*innen gleichzeitig dieselben Daten ändern (z. B. verlorene Updates). Leistungsfähige Systeme sperren feingranular nur die betroffenen Zeilen (row-level locking) statt ganzer Tabellen; so können viele Transaktionen parallel laufen, ohne aufeinander zu warten. Bezug: Viele Nutzende melden sich gleichzeitig zu Aktivitäten an (Wartelisten, begrenzte Plätze); eine Tabellensperre auf teilnahme würde bei jedem Klick alle anderen Anmeldungen blockieren.

b) Für die Datenbank gelten die folgenden Sicherheitsanforderungen. Ergänze zu den vier weiteren Anforderungen jeweils eine geeignete Maßnahme mit Bezug zu Let’s Meet. (8 Punkte)

Anforderung Maßnahme
Die Vorgaben der DSGVO müssen eingehalten werden. Die Datenschutzbeauftragte prüft jede neue Verarbeitung; Löschfristen werden umgesetzt.
Unberechtigter Zugriff auf die Datenbank muss verhindert werden. …
Änderungen an Konten und Sperren müssen nachvollziehbar sein. …
Die Daten müssen auch bei einem Serverausfall verfügbar sein. …
Gestohlene Sicherungsdateien dürfen nicht lesbar sein. …

Je Anforderung 2 Punkte (konkrete, passende Maßnahme mit Bezug), zum Beispiel:

Anforderung Maßnahme
Unberechtigter Zugriff auf die Datenbank muss verhindert werden. Benutzerverwaltung mit eigenen Konten je Person und Anwendung, Rechte nach dem Minimalprinzip (GRANT nur auf benötigte Tabellen bzw. Views), keine gemeinsam genutzten Konten, Server nur intern erreichbar (Firewall), verschlüsselte Verbindungen (TLS), starke Passwörter bzw. Zwei-Faktor-Anmeldung für die Administration
Änderungen an Konten und Sperren müssen nachvollziehbar sein. Protokollierung einrichten: Audit-Plugin für Anmeldungen und Änderungen, Binärlog aufbewahren, zusätzlich eine Protokolltabelle per Trigger (wer hat wann welches Konto gesperrt); Protokolle schreibgeschützt und getrennt vom Datenbankserver speichern
Die Daten müssen auch bei einem Serverausfall verfügbar sein. Replikation auf einen zweiten Datenbankserver (am besten am zweiten Standort des Rechenzentrums) oder ein Datenbankcluster, automatische Umschaltung; redundante Hardware (RAID, zwei Netzteile); Überwachung mit Alarm
Gestohlene Sicherungsdateien dürfen nicht lesbar sein. Sicherungen verschlüsseln (z. B. Dump vor dem Speichern verschlüsseln, verschlüsseltes Sicherungsziel), Schlüssel getrennt aufbewahren; Datendateien mit encryption at rest verschlüsseln

c) Am Montagmorgen melden das Support-Team und viele Nutzende, dass die App „hängt“. Yusuf Demir hat um 9:20 Uhr die folgenden Informationen gesammelt:

Überwachung db01 (Montag, 9:20 Uhr)
  CPU-Auslastung            96 %
  Arbeitsspeicher           belegt 61 von 64 GiB, Swap aktiv
  Datenträger /var/lib/mysql   93 % belegt (Vorwoche: 71 %)
  Verbindungen              487 von max. 500
  Slow-Query-Log            1.912 Einträge seit 8:00 Uhr, häufigste Abfrage:
     SELECT aktivitaet_id, titel, beginn FROM aktivitaet
     WHERE status = 'geplant' AND beginn BETWEEN ? AND ?  ORDER BY beginn;
     (Dauer jeweils 2,1 bis 3,4 s)
  Sicherung                 nächtliche Vollsicherung läuft noch (Start 2:00 Uhr)

Erläutere drei mögliche Gründe für das verzögerte Reaktionsverhalten, die sich aus diesen Informationen ergeben, und nenne zu jedem Grund eine Gegenmaßnahme. (6 Punkte)

Je Grund 1 Punkt für die Erläuterung mit Bezug auf die Daten und 1 Punkt für eine passende Gegenmaßnahme, zum Beispiel:

  • Langsame Abfrage ohne passenden Index: Die häufigste Abfrage im Slow-Query-Log filtert nach status und beginn und sortiert nach beginn. Ohne Index liest MariaDB jedes Mal die ganze Tabelle aktivitaet; bei Hunderten gleichzeitigen Aufrufen steigt die CPU-Last. Gegenmaßnahme: Abfrage mit EXPLAIN prüfen und einen Index auf (status, beginn) anlegen (siehe d).

  • Datensicherung während der Arbeitszeit: Die nächtliche Vollsicherung läuft seit 2:00 Uhr und ist noch nicht fertig. Sie liest den gesamten Datenbestand und belastet Datenträger und CPU. Gegenmaßnahme: Sicherung auf einem Replikat ausführen, inkrementell sichern oder Dauer überwachen und rechtzeitig vor Arbeitsbeginn beenden.

  • Zu viele Verbindungen: 487 von 500 möglichen Verbindungen sind belegt; neue Anfragen müssen warten oder werden abgewiesen. Ursache können die langsamen Abfragen selbst sein (Verbindungen bleiben länger offen) oder ein App-Server, der Verbindungen nicht schließt. Gegenmaßnahme: Verbindungs-Pooling im App-Server, Ursache mit SHOW PROCESSLIST suchen, Last auf Replikate verteilen.

  • Arbeitsspeicher und Datenträger am Limit: Der Speicher ist fast voll und es wird ausgelagert (Swap); der Datenträger ist innerhalb einer Woche von 71 % auf 93 % gewachsen (z. B. durch wachsende Protokolle oder Sicherungsdateien). Gegenmaßnahme: Puffergrößen prüfen, RAM erweitern, Ursache des Wachstums suchen (Binärlogs aufräumen, Sicherungen auslagern), Speicher erweitern.

d) Yusuf Demir lässt sich für die häufigste Abfrage den Ausführungsplan anzeigen (Ausgabe gekürzt):

EXPLAIN SELECT aktivitaet_id, titel, beginn FROM aktivitaet
        WHERE status = 'geplant' AND beginn BETWEEN '2026-10-26' AND '2026-11-01' ORDER BY beginn;

+------------+------+---------------+------+--------+-----------------------------+
| table      | type | possible_keys | key  | rows   | Extra                       |
+------------+------+---------------+------+--------+-----------------------------+
| aktivitaet | ALL  | NULL          | NULL | 168240 | Using where; Using filesort |
+------------+------+---------------+------+--------+-----------------------------+

da) Erläutere, was der Ausführungsplan über die Abfrage aussagt. (2 Punkte)

Je Aussage 1 Punkt: type ALL und key NULL bedeuten, dass kein Index genutzt wird und MariaDB die ganze Tabelle liest (full table scan, rund 168.000 Zeilen), obwohl nur die Aktivitäten einer Woche gebraucht werden. Using filesort zeigt, dass das Ergebnis anschließend zusätzlich sortiert werden muss.

db) Erstelle die SQL-Anweisung, mit der ein passender Index idx_akt_status_beginn angelegt wird, und begründe die Reihenfolge der Spalten. (3 Punkte)

2 Punkte für die Anweisung, 1 Punkt für die Begründung:

Zuerst die Spalte, die auf Gleichheit geprüft wird (status = 'geplant'), dann die Spalte mit dem Bereich und der Sortierung (beginn). So findet MariaDB im Index direkt alle geplanten Aktivitäten im Zeitraum und kann sie in Indexreihenfolge liefern; der Plan zeigt danach type range mit wenigen Hundert Zeilen und kein filesort mehr. Ein Index nur auf beginn ist als Alternative ebenfalls richtig.

e) Für die Wiederherstellungstests soll zusätzlich jede Nacht ein Dump der Datenbank letsmeet erstellt werden.

ea) Nenne vier Inhalte, die ein Dump der Datenbank enthalten kann. (2 Punkte)

Je zwei Inhalte 1 Punkt: Tabellenstruktur (CREATE TABLE mit Datentypen, Schlüsseln, Constraints, Indizes), Daten aller Tabellen (INSERT), Beziehungen (Fremdschlüssel), Views, Trigger, Stored Procedures und Ereignisse, Benutzerkonten und ihre Rechte.

eb) Erstelle den Befehl, mit dem auf db01 ein in sich konsistenter Dump der Datenbank letsmeet mit allen Triggern und Stored Procedures in die Datei letsmeet.sql geschrieben wird, ohne den Betrieb anzuhalten, und den Befehl, mit dem der Dump auf dem Testserver in die leere Datenbank letsmeet_test eingespielt wird. (4 Punkte)

3 Punkte für den Dump (Programm, --single-transaction, Routinen/Trigger), 1 Punkt für das Einspielen:

--single-transaction liest alle InnoDB-Tabellen in einer einzigen Transaktion: Der Dump zeigt einen einheitlichen Stand, ohne Tabellen zu sperren. Trigger sind bei mariadb-dump standardmäßig enthalten, Stored Procedures nur mit --routines. Anmeldedaten werden in der Praxis über eine geschützte Optionsdatei übergeben (--defaults-extra-file) statt auf der Kommandozeile. mysqldump bzw. mysql sind ebenfalls richtig.

ec) Clara Neumann fragt: „Wenn wir jede Nacht einen Dump haben, ist doch alles gesichert, oder?“ Nimm Stellung. (3 Punkte)

1 Punkt je Argument, höchstens 3 Punkte:

  • Ein Dump ist eine Momentaufnahme. Fällt db01 um 16 Uhr aus, wären ohne weitere Maßnahmen alle Anmeldungen und Änderungen seit der letzten Nacht verloren. Deshalb wird zusätzlich das Binärlog gesichert, mit dem sich die Änderungen bis kurz vor dem Ausfall nachspielen lassen (Point-in-Time-Recovery).

  • Ein Dump hilft nicht gegen Ausfallzeit: Das Einspielen von Hunderttausenden Datensätzen dauert. Für hohe Verfügbarkeit ist ein Replikat nötig, auf das umgeschaltet werden kann.

  • Eine Sicherung ist erst nützlich, wenn die Wiederherstellung regelmäßig getestet wird und die Sicherung getrennt vom Server (eine Kopie außer Haus, vor Ransomware geschützt) aufbewahrt wird.

  • Fazit: Der Dump ist ein wichtiger Baustein, ersetzt aber weder Binärlog, Replikation noch Wiederherstellungstests.

Aufgabe 3.2: Die Barcamp-Datenbank auf einen neuen Server umziehen (Profilkompetenz)

(ca. 22 min Bearbeitungszeit)

Du gehörst zum Orga-Team des Barcamps „Lernen.Digital.Leben 2027“ am Ratz und Rübe Berufskolleg. Die Orga-Datenbank barcamp (MariaDB) mit den Tabellen veranstaltung, person, anmeldung, raum, slot, session, session_person, session_buchung, feedback und orga_aufgabe lief bisher auf einem Testrechner im IT-Labor. Sie soll auf einen Server der Schul-IT OWL umziehen. Für die Nacharbeit kommt eine neue Tabelle kurzlink hinzu, über die Teilnehmende per kurzem Code die Folien und Videos einer Session aufrufen. Dimitrios Papadopoulos (Gesamtleitung der Organisation) und Svenja Krämer (Schul-IT OWL) haben Dir die Vorbereitung übertragen.

Auszug aus dem Tabellenmodell der Datenbank barcamp (weitere Tabellen und Spalten sind für diese Aufgabe nicht nötig):

  • veranstaltung (veranstaltung_id, titel, datum, ort, …)

  • person (person_id, vorname, nachname, email, organisation, …)

  • anmeldung (anmeldung_id, #veranstaltung_id, #person_id, ticketart, angemeldet_am, …, badge_code)

  • raum (raum_id, bezeichnung, name, plaetze, …)

  • slot (slot_id, #veranstaltung_id, beginn, ende)

  • session (session_id, #veranstaltung_id, titel, format, status, #raum_id, #slot_id, …)

  • session_person (#session_id, #person_id, rolle)

  • session_buchung (#session_id, #anmeldung_id, gebucht_am)

Die Fremdschlüssel von anmeldung heißen fk_anm_veranstaltung und fk_anm_person, die von slot und session fk_slot_veranstaltung, fk_ses_veranstaltung, fk_ses_raum und fk_ses_slot. Die Fremdschlüssel auf session sowie fk_sb_anmeldung sind mit ON DELETE CASCADE angelegt, alle anderen ohne ON DELETE-Angabe (also RESTRICT).

a) Das erweiterte Tabellenmodell liegt in der 3. Normalform vor. Nenne sechs weitere Arbeitsschritte in sinnvoller Reihenfolge, bis die Datenbank auf dem neuen Server für das Orga-Team verfügbar ist. (6 Punkte)

1. MariaDB auf dem Server der Schul-IT OWL installieren und absichern.
2.
3.
4.
5.
6.
7.

Je sinnvollem Schritt in passender Reihenfolge 1 Punkt; viele Lösungen sind möglich, zum Beispiel:

  1. Datenbank barcamp mit Zeichensatz utf8mb4 und passender Kollation anlegen.

  2. Tabellen einschließlich der neuen Tabelle kurzlink mit Datentypen, Schlüsseln, Constraints und Indizes per SQL-DDL erstellen.

  3. Daten vom Testrechner übernehmen (Dump einspielen oder CSV-Import in der richtigen Tabellenreihenfolge).

  4. Implementierung testen: Primär- und Fremdschlüssel, Constraints, Anzahl der Datensätze, typische Abfragen; verwaiste Datensätze suchen.

  5. Benutzer und Rollen für Orga-Team, Check-in und Webseite anlegen, Rechte vergeben und testen.

  6. Datensicherung einrichten und eine Wiederherstellung testen; danach die Anwendungen auf den neuen Server umstellen und den alten Bestand stilllegen.

Auch richtig: Views anlegen, Verbindung über TLS einrichten, Überwachung einrichten, Daten vor der Übernahme bereinigen.

b) Svenja Krämer weist darauf hin, dass beim Umzug besonders auf die referentielle Integrität zu achten ist. Erläutere, was man unter referentieller Integrität versteht, am Beispiel der Tabellen person und anmeldung. (3 Punkte)

3 Punkte (Begriff 2 Punkte, Beispiel 1 Punkt): Referentielle Integrität bedeutet, dass Beziehungen zwischen Tabellen über Fremdschlüssel widerspruchsfrei bleiben: Ein Fremdschlüsselwert darf nur vorkommen, wenn es in der referenzierten Tabelle einen Datensatz mit diesem Primärschlüsselwert gibt (oder er ist NULL, sofern erlaubt). Das DBMS weist Einfügungen, Änderungen und Löschungen ab, die das verletzen würden. Beispiel: Jede Zeile in anmeldung verweist mit person_id auf eine Person. Eine Anmeldung mit person_id = 15 darf es nur geben, wenn in person die Person 15 existiert; eine Person mit Anmeldungen darf nicht einfach gelöscht werden (fk_anm_person ohne ON DELETE).

c) Die Daten sollen tabellenweise aus CSV-Dateien in die leeren Tabellen des neuen Servers importiert werden, ohne die Fremdschlüsselprüfung abzuschalten. Gib eine zulässige Reihenfolge für die Tabellen veranstaltung, person, anmeldung, raum, slot, session, session_person und session_buchung an und begründe sie. (4 Punkte)

2 Punkte für eine zulässige Reihenfolge, 2 Punkte für die Begründung. Zum Beispiel:

  1. veranstaltung, person, raum (verweisen auf keine andere Tabelle, Reihenfolge untereinander beliebig)

  2. slot (verweist auf veranstaltung)

  3. anmeldung (verweist auf veranstaltung und person)

  4. session (verweist auf veranstaltung, raum, slot)

  5. session_person (verweist auf session und person)

  6. session_buchung (verweist auf session und anmeldung)

Begründung: Eine Tabelle darf erst befüllt werden, wenn alle Tabellen, auf die ihre Fremdschlüssel verweisen, schon die passenden Datensätze enthalten. Also zuerst die Elterntabellen, dann die Kindtabellen. Würde zum Beispiel anmeldung vor person importiert, wiese MariaDB jede Zeile ab (Cannot add or update a child row: a foreign key constraint fails). Andere Reihenfolgen, die diese Regel einhalten, sind ebenfalls richtig.

d) Eine Kollegin hat den Import zuerst auf eigene Faust mit SET FOREIGN_KEY_CHECKS = 0; durchgeführt, „weil die Reihenfolge egal ist“. Dabei wurden auch Anmeldungen übernommen, die im alten Bestand gar nicht hätten existieren dürfen.

Stand der Datenbank auf dem neuen Server nach diesem Import: Die Tabelle person enthält die Personen mit person_id 1 bis 14. Die letzten Zeilen der Tabelle anmeldung:

anmeldung_id veranstaltung_id person_id ticketart badge_code
13 1 13 Referent BC27R013
14 1 14 Schueler BC27S014
15 1 15 Extern BC27E015
16 1 21 Schueler BC27S016

da) Erstelle eine SQL-Abfrage, die alle Anmeldungen mit anmeldung_id, person_id und badge_code anzeigt, deren Person in der Tabelle person nicht existiert. (4 Punkte)

1 Punkt für die Spaltenauswahl, 2 Punkte für die Verknüpfung (LEFT JOIN oder NOT EXISTS/NOT IN), 1 Punkt für die Bedingung:

Gleichwertig:

Ergebnis auf dem übernommenen Bestand (die Personen gehen nur bis person_id 14):

anmeldung_id person_id badge_code
15 15 BC27E015
16 21 BC27S016

db) Erläutere, warum das Abschalten der Fremdschlüsselprüfung riskant ist und wann es vertretbar sein kann. (2 Punkte)

Je Aspekt 1 Punkt: Ohne Prüfung übernimmt MariaDB auch Fremdschlüsselwerte ohne passenden Elterndatensatz; beim Wiedereinschalten werden die vorhandenen Daten nicht nachträglich geprüft. Verwaiste Datensätze bleiben unbemerkt und führen später zu Fehlern (z. B. ein Badge ohne Namen beim Check-in, falsche Teilnehmerzahlen bei JOIN-Abfragen). Vertretbar ist das Abschalten nur kurzzeitig beim Einspielen eines vollständigen, in sich konsistenten Dumps (so macht es mariadb-dump selbst), wenn danach mit Abfragen wie in da) geprüft wird.

e) Die Codes der neuen Tabelle kurzlink bestehen aus sechs Zeichen, die zufällig aus Großbuchstaben, Kleinbuchstaben und Ziffern gewählt werden (z. B. Xk3Pq9). Die Datenbank wurde mit der Kollation utf8mb4_unicode_ci angelegt, die Tabelle übernimmt sie:

Beim Test wird der Code Xk3Pq9 für die Folien von Session 1 gespeichert. Das Speichern des zufällig erzeugten Codes xk3pq9 für das Video von Session 3 scheitert mit ERROR 1062 (23000): Duplicate entry 'xk3pq9' for key 'PRIMARY'.

ea) Erläutere, was „case sensitive“ bei Zeichenketten bedeutet, und erkläre damit die Ursache der Fehlermeldung. (3 Punkte)

1 Punkt für den Begriff, 2 Punkte für die Ursache: Ist eine Zeichenkette bzw. ein Vergleich case sensitive, wird zwischen Groß- und Kleinbuchstaben unterschieden; Xk3Pq9 und xk3pq9 sind dann verschiedene Werte. Die Kollation utf8mb4_unicode_ci ist aber case insensitive (ci): Beim Vergleich, also auch beim Prüfen des Primärschlüssels, gelten beide Codes als gleich. Der zweite Code verletzt damit die Eindeutigkeit des Primärschlüssels. Außerdem würde eine Suche nach xk3pq9 die Folien von Session 1 liefern – beim Aufruf eines Kurzlinks käme also der falsche Inhalt.

eb) Erstelle eine SQL-Anweisung, mit der die Spalte code so geändert wird, dass Groß- und Kleinschreibung unterschieden werden. (2 Punkte)

2 Punkte (1 Punkt ALTER TABLE … MODIFY, 1 Punkt binäre bzw. case-sensitive Kollation):

Danach lassen sich Xk3Pq9 und xk3pq9 beide speichern, und die Suche WHERE code = 'xk3pq9' findet nur den passenden Datensatz. Gleichwertig ist VARBINARY(8) oder eine …_cs-Kollation, sofern das DBMS sie anbietet. Der Primärschlüssel bleibt bei MODIFY erhalten.

Anlage: SQL-Kurzreferenz Datenbankkonzepte (MariaDB)

SQL-Kurzreferenz für Transaktionen, Prozeduren, Trigger und Indizes
Syntax Beschreibung
START TRANSACTION; · COMMIT; · ROLLBACK; Transaktion beginnen, festschreiben, zurücknehmen
SELECT … FOR UPDATE; Zeilen lesen und bis zum Ende der Transaktion für Änderungen sperren
SET TRANSACTION ISOLATION LEVEL READ COMMITTED \| REPEATABLE READ \| SERIALIZABLE; Isolationsstufe der nächsten Transaktion
CREATE [UNIQUE] INDEX name ON tabelle (spalte[, …]); · DROP INDEX name ON tabelle; Index anlegen bzw. entfernen
FOREIGN KEY (spalte) REFERENCES tabelle (spalte) [ON DELETE RESTRICT \| CASCADE \| SET NULL] Fremdschlüssel; ohne Angabe gilt RESTRICT
CREATE PROCEDURE name(IN p1 TYP, OUT p2 TYP) BEGIN … END Stored Procedure anlegen
CALL name(wert, @variable); · SELECT @variable; Prozedur aufrufen, OUT-Parameter abfragen
DECLARE v TYP; · SELECT spalte INTO v FROM …; · SET v = …; Variable deklarieren und belegen
IF bedingung THEN … ELSEIF … ELSE … END IF; Verzweigung
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN … END; Fehlerbehandlung in Prozeduren
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '…'; eigenen Fehler auslösen
CREATE TRIGGER name BEFORE \| AFTER INSERT \| UPDATE \| DELETE ON tabelle FOR EACH ROW anweisung Trigger anlegen; Zugriff auf NEW.spalte und OLD.spalte
DELIMITER // … DELIMITER ; Endezeichen im Kommandozeilen-Client umstellen
ROW_COUNT() Anzahl der von der letzten Anweisung geänderten Zeilen

Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zu Datenbankkonzepten: Transaktionen, Integrität, Trigger, Stored Procedures und Index” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/datenbankkonzepte-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/db-design/datenbankentwurf. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 27.10.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: