Zum Inhalt springen
sw
en

Tippe um zu suchen

Datenbanken & Data

Datenbank-Grundbegriffe fuer den IT-Support

ERM, Normalisierung, ACID-Transaktionen, JOINs und Locking verstaendlich erklaert - fuer IT-Support-Faelle im KMU-Alltag.

12 Min Lesezeit Anfänger Zuletzt aktualisiert:

Warum du als Support das ueberhaupt brauchst

Im Schweizer KMU-Alltag landet fast jedes Problem irgendwann bei einer Datenbank: Das ERP haengt, ein Report zeigt falsche Zahlen, ein Update dauert ewig, oder ein Nutzer meldet “die Anwendung ist eingefroren, seit ich auf Speichern geklickt habe”. Als Erstlinien- oder Zweitlinien-Support musst du keine Datenbanken designen koennen - aber du musst verstehen, was hinter der Fehlermeldung passiert, damit du entscheiden kannst: Selbst loesen, Applikationsteam einschalten oder DBA/Hersteller-Support eskalieren.

Dieser Artikel gibt dir das Fundament: Wie Daten in Tabellen organisiert sind, warum Normalisierung existiert, was eine Transaktion “ACID-sicher” macht, wie du SELECT/JOIN-Abfragen liest (nicht unbedingt selbst schreiben musst), und wie Deadlocks entstehen. Am Ende weisst du, wann ein Ticket “nur” ein Index-Problem ist und wann du wirklich einen Datenbankspezialisten brauchst.

Tabellen, Zeilen, Spalten: Das relationale Grundmodell

Fast jede Business-Anwendung (ERP, CRM, Ticketsystem, Buchhaltung) basiert auf einer relationalen Datenbank (SQL Server, PostgreSQL, MySQL/MariaDB, Oracle). Das Grundprinzip ist simpel:

  • Eine Tabelle (Table) speichert eine Art von “Dingen”, z. B. Kunden, Bestellungen, Artikel.
  • Eine Zeile (Row/Record) ist ein konkretes Ding, z. B. ein einzelner Kunde.
  • Eine Spalte (Column/Field) ist eine Eigenschaft, z. B. Kundenname, PLZ, Kreditlimit.
-- Beispieltabelle Kunden
CREATE TABLE Kunden (
    KundeID     INT IDENTITY(1,1) PRIMARY KEY,
    Firma       NVARCHAR(100) NOT NULL,
    PLZ         NVARCHAR(10),
    Ort         NVARCHAR(50),
    Kreditlimit DECIMAL(10,2) DEFAULT 0
);

Jede Zeile braucht eine eindeutige Kennung - das ist der Primaerschluessel (Primary Key, kurz PK). Ohne PK kann die Datenbank zwei identische Zeilen nicht unterscheiden, und viele Operationen (Updates, Replikation, Indizierung) werden unmoeglich oder extrem langsam.

Primaerschluessel: Kuenstlich vs. natuerlich

TypBeispielVorteilNachteil
Kuenstlicher Schluessel (Surrogate Key)KundeID INT IDENTITYAendert sich nie, kompakt, schnell fuer JoinsHat keine fachliche Bedeutung
Natuerlicher SchluesselAHV-Nummer, USt-ID, E-MailFachlich sprechendKann sich aendern (Namensaenderung, neue E-Mail), Datenschutz-Risiko bei AHV-Nummer
GUID/UUIDNEWID() in SQL ServerGlobal eindeutig, gut fuer verteilte SystemeGroesser (16 Bytes), fragmentiert Indizes stark

Fremdschluessel und Beziehungen (ERM)

Der Fremdschluessel (Foreign Key, FK) verknuepft Tabellen: Eine Spalte in Tabelle A verweist auf den Primaerschluessel einer Zeile in Tabelle B. Das Entity-Relationship-Modell (ERM) beschreibt genau diese Beziehungen zwischen “Entitaeten” (Dingen) grafisch, bevor man die eigentlichen Tabellen anlegt.

CREATE TABLE Bestellungen (
    BestellID   INT IDENTITY(1,1) PRIMARY KEY,
    KundeID     INT NOT NULL,
    Bestelldatum DATE NOT NULL DEFAULT GETDATE(),
    CONSTRAINT FK_Bestellungen_Kunden
        FOREIGN KEY (KundeID) REFERENCES Kunden(KundeID)
);

Drei Beziehungstypen kommen in der Praxis vor:

  1. 1:n (eins zu viele) - ein Kunde hat mehrere Bestellungen. Das ist der Standardfall, geloest mit einem FK in der “n”-Tabelle.
  2. n:m (viele zu viele) - ein Artikel kann in vielen Bestellungen vorkommen, eine Bestellung enthaelt viele Artikel. Das braucht eine Verknuepfungstabelle (auch Junction Table oder Zwischentabelle genannt), z. B. Bestellpositionen mit BestellID und ArtikelID als zusammengesetztem Schluessel.
  3. 1:1 (eins zu eins) - selten, z. B. ein Mitarbeiter hat genau einen Dienstausweis-Datensatz. Oft wird das aus Performance- oder Sicherheitsgruenden in zwei Tabellen aufgeteilt (z. B. sensible Lohndaten separat mit eigenen Berechtigungen).
-- n:m-Beziehung ueber Verknuepfungstabelle
CREATE TABLE Bestellpositionen (
    BestellID  INT NOT NULL,
    ArtikelID  INT NOT NULL,
    Menge      INT NOT NULL,
    PRIMARY KEY (BestellID, ArtikelID),
    FOREIGN KEY (BestellID) REFERENCES Bestellungen(BestellID),
    FOREIGN KEY (ArtikelID) REFERENCES Artikel(ArtikelID)
);

Normalisierung einfach erklaert (1NF bis 3NF)

Normalisierung ist der systematische Prozess, Redundanz aus Tabellen zu entfernen, damit Daten nicht mehrfach und potenziell widerspruechlich gespeichert werden. Das ist wichtig zu verstehen, wenn du beurteilen musst, ob ein “komisches” Datenbankdesign ein Bug oder Absicht ist.

Ausgangslage: Eine unnormalisierte Tabelle

BestellID | Kunde        | Ort      | Artikel1  | Artikel2   | ArtikelPreis
1         | Mueller AG   | Bern     | Schraube  | Mutter     | 0.10, 0.05

Probleme: Wiederholende Gruppen (Artikel1, Artikel2), mehrere Werte in einer Zelle, Kundendaten werden bei jeder Bestellung wiederholt.

1. Normalform (1NF): Atomare Werte, keine Wiederholungsgruppen

Jede Spalte darf nur einen einzelnen (atomaren) Wert enthalten, keine Listen. Statt Artikel1/Artikel2 brauchst du eine eigene Zeile pro Artikel (siehe Bestellpositionen oben).

2. Normalform (2NF): Voll funktionale Abhaengigkeit vom gesamten Schluessel

Gilt nur relevant bei zusammengesetzten Schluesseln. Jede Nicht-Schluessel-Spalte muss vom gesamten Schluessel abhaengen, nicht nur von einem Teil. Beispiel eines Verstosses: In Bestellpositionen (BestellID, ArtikelID, Menge, ArtikelBezeichnung) haengt ArtikelBezeichnung nur von ArtikelID ab, nicht vom vollen Schluessel (BestellID, ArtikelID). Loesung: ArtikelBezeichnung gehoert in die Tabelle Artikel.

3. Normalform (3NF): Keine transitiven Abhaengigkeiten

Eine Nicht-Schluessel-Spalte darf nicht von einer anderen Nicht-Schluessel-Spalte abhaengen. Beispiel: In Kunden (KundeID, PLZ, Ort) haengt Ort von PLZ ab, nicht direkt vom Schluessel KundeID. Sauberer waere eine eigene Tabelle PLZ_Orte (PLZ, Ort). In der Praxis wird das oft bewusst nicht bis zur letzten Konsequenz durchgezogen (siehe unten).

Trade-off: Normalisiert vs. denormalisiert

KriteriumNormalisiert (3NF)Denormalisiert
DatenredundanzMinimalBewusst vorhanden
Schreibperformance (INSERT/UPDATE)Gut, da nur ein Ort geaendert wirdSchlechter, mehrere Kopien muessen synchron gehalten werden
Leseperformance bei komplexen ReportsBraucht viele JOINs, kann langsam seinSchnell, da Daten schon “flach” vorliegen
Gefahr von InkonsistenzenGeringHoch, wenn Sync vergessen wird
Typischer EinsatzTransaktionale Systeme (OLTP): ERP, CRMData Warehouse, Reporting (OLAP), Caching-Tabellen

ACID-Transaktionen: Warum Geld nicht verschwindet

Eine Transaktion buendelt mehrere Datenbankoperationen zu einer logischen Einheit, die entweder komplett durchgefuehrt oder komplett verworfen wird. Klassisches Beispiel: Eine Ueberweisung zieht Geld von Konto A ab und schreibt es Konto B gut - beide Schritte muessen zusammen gelingen oder zusammen scheitern.

Die vier ACID-Eigenschaften garantieren das:

  • Atomicity (Atomaritaet): Alles oder nichts. Bricht die Transaktion mitten drin ab (Stromausfall, Fehler), werden alle bereits ausgefuehrten Teilschritte zurueckgerollt (Rollback).
  • Consistency (Konsistenz): Die Datenbank bewegt sich von einem gueltigen Zustand in einen anderen gueltigen Zustand. Constraints (Fremdschluessel, CHECK-Regeln) werden nie verletzt.
  • Isolation (Isolation): Parallele Transaktionen beeinflussen sich nicht gegenseitig, als liefen sie nacheinander ab (auch wenn sie technisch gleichzeitig laufen).
  • Durability (Dauerhaftigkeit): Ist eine Transaktion committed (bestaetigt), bleibt sie auch nach einem Stromausfall oder Absturz erhalten - dank Transaktionslog.
BEGIN TRANSACTION;

UPDATE Konten SET Saldo = Saldo - 500 WHERE KontoID = 1;
UPDATE Konten SET Saldo = Saldo + 500 WHERE KontoID = 2;

-- Pruefen, ob beide Updates ok waren
IF @@ERROR = 0
    COMMIT TRANSACTION;
ELSE
    ROLLBACK TRANSACTION;

Isolationsstufen (Isolation Levels)

Volle Isolation waere am sichersten, aber am langsamsten (jede Transaktion muesste auf jede andere warten). Deshalb gibt es abgestufte Isolation Levels, die einen Kompromiss zwischen Konsistenz und Performance erlauben:

Isolation LevelVerhindert Dirty ReadVerhindert Non-Repeatable ReadVerhindert Phantom ReadTypischer Einsatz
Read UncommittedNeinNeinNeinSelten, nur fuer grobe Reports ohne Konsistenzanspruch
Read Committed (Standard bei SQL Server)JaNeinNeinStandardfall fuer die meisten Anwendungen
Repeatable ReadJaJaNeinFinanzberichte, die waehrend der Laufzeit stabil bleiben muessen
SerializableJaJaJaKritische Finanztransaktionen, hoechste Konsistenzanforderung

SELECT und JOIN: Die Basis, die jeder Support-Mitarbeiter lesen koennen sollte

Du musst kein SQL-Entwickler sein, aber wenn ein Applikationsentwickler dir einen Debug-Query schickt oder du selbst im SQL Server Management Studio (SSMS) nachschauen willst, ob Daten “wirklich fehlen” oder “nur nicht angezeigt werden”, brauchst du diese Grundlagen.

SELECT-Grundgeruest

SELECT KundeID, Firma, Ort
FROM Kunden
WHERE Ort = 'Bern'
ORDER BY Firma ASC;

JOIN: Tabellen verknuepfen

Ein JOIN kombiniert Zeilen aus zwei (oder mehr) Tabellen anhand einer gemeinsamen Spalte, meist Primaer-/Fremdschluessel.

-- INNER JOIN: nur Zeilen, die in BEIDEN Tabellen einen passenden Partner haben
SELECT b.BestellID, k.Firma, b.Bestelldatum
FROM Bestellungen b
INNER JOIN Kunden k ON b.KundeID = k.KundeID;

-- LEFT JOIN: alle Kunden, auch wenn sie noch KEINE Bestellung haben
SELECT k.Firma, b.BestellID
FROM Kunden k
LEFT JOIN Bestellungen b ON k.KundeID = b.KundeID
WHERE b.BestellID IS NULL;  -- findet Kunden OHNE Bestellung
JOIN-TypErgebnisTypischer Support-Use-Case
INNER JOINNur Zeilen mit Treffer in beiden Tabellen”Zeige alle Bestellungen mit Kundenname”
LEFT JOINAlle Zeilen der linken Tabelle, plus Treffer aus rechter (sonst NULL)“Welche Kunden haben noch nie bestellt?” (typische Datenreinigungs-Abfrage)
RIGHT JOINSpiegelbild von LEFT JOINSelten genutzt, meist per LEFT JOIN mit vertauschter Tabellenreihenfolge geloest
FULL OUTER JOINAlle Zeilen aus beiden Tabellen, egal ob TrefferDatenabgleich zwischen zwei Systemen (z. B. ERP vs. CRM)

Deadlocks und Locking: Wenn zwei Transaktionen sich blockieren

Damit ACID-Isolation funktioniert, setzt die Datenbank Sperren (Locks) auf Zeilen, Seiten oder ganze Tabellen, waehrend eine Transaktion sie bearbeitet. Das verhindert, dass zwei Transaktionen gleichzeitig denselben Datensatz inkonsistent aendern.

Ein Deadlock entsteht, wenn zwei Transaktionen sich gegenseitig blockieren: Transaktion A haelt eine Sperre auf Zeile 1 und wartet auf Zeile 2, waehrend Transaktion B eine Sperre auf Zeile 2 haelt und auf Zeile 1 wartet. Keine kann weitermachen.

Transaktion A                    Transaktion B
------------------------------   ------------------------------
UPDATE Konten SET ... WHERE ID=1  UPDATE Konten SET ... WHERE ID=2
(haelt Lock auf Zeile 1)          (haelt Lock auf Zeile 2)
UPDATE Konten SET ... WHERE ID=2  UPDATE Konten SET ... WHERE ID=1
(wartet auf Lock von B)  <---->   (wartet auf Lock von A)
                    DEADLOCK!

Die Datenbank erkennt das automatisch (Deadlock Detection) und beendet eine der beiden Transaktionen zwangsweise mit einem Rollback (“Deadlock Victim”) - die andere darf weiterlaufen.

Symptome, die im Ticket landen

  • Anwendung “haengt” fuer mehrere Sekunden, dann Fehlermeldung wie “Transaction (Process ID X) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.”
  • Timeouts (“Der Vorgang wurde abgebrochen, da das Zeitlimit ueberschritten wurde”)
  • Berichte oder Batch-Jobs, die nachts laufen und morgens als fehlgeschlagen gemeldet werden

Erste Diagnoseschritte fuer den Support

-- SQL Server: Aktuelle Sperren und blockierende Sessions anzeigen
SELECT
    blocking_session_id AS BlockedBy,
    session_id AS BlockedSession,
    wait_type,
    wait_time,
    wait_resource
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0;
-- Deadlock-Historie aus dem System_Health Extended Events Log auslesen (SQL Server)
SELECT
    xed.value('@timestamp', 'datetime2') AS DeadlockZeit,
    xed.query('.') AS DeadlockGraph
FROM (
    SELECT CAST(target_data AS XML) AS TargetData
    FROM sys.dm_xe_session_targets st
    JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
    WHERE s.name = 'system_health'
) AS Data
CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS Tab(xed);

Entscheidungsbaum: Selbst loesen oder eskalieren?

Ticket: "Anwendung/Bericht verhaelt sich seltsam bei Datenbankzugriff"

├─ Ist es ein einmaliger Timeout/Deadlock, App laeuft danach normal?
│   └─ Ja → Vorfall dokumentieren, Nutzer informieren, beobachten. Kein Eskalationsbedarf.

├─ Fehlermeldung nennt explizit "Deadlock" oder "Timeout expired" wiederholt?
│   └─ Ja → Blockierende Sessions pruefen (sys.dm_exec_requests).
│         Tritt es taeglich zur gleichen Zeit auf (z. B. Batch-Job)?
│         ├─ Ja → Applikationsteam/DBA einschalten, Deadlock-Graph mitliefern.
│         └─ Nein, einmalig → Beobachten, Ticket dokumentieren.

├─ Nutzer meldet "Daten fehlen" in einem Bericht?
│   └─ Pruefen: Basiert der Bericht auf INNER JOIN? Fehlen nur Datensaetze ohne Referenz?
│         ├─ Ja, JOIN-Logik erklaert es → Kein Bug, Rueckmeldung an Nutzer/Applikationsteam.
│         └─ Nein, Daten fehlen trotz vorhandener Referenz → An DBA/Applikationsteam eskalieren,
│           moeglicher Datenintegritaets- oder Replikationsfehler.

├─ Datenbankserver reagiert generell langsam, hohe CPU/IO-Last?
│   └─ Eskalation an DBA: Kandidat fuer Index-Tuning, Statistik-Updates oder Kapazitaetsproblem.
│       Siehe dazu SQL Server Indizes und Tuning.

└─ Verdacht auf Datenkorruption, fehlgeschlagene Wiederherstellung, Backup-Probleme?
    └─ SOFORT eskalieren (P1). Nichts selbst reparieren, keine Skripte gegen Produktivdaten fahren.

Praxis-Checkliste fuer den Alltag

  1. Bei jedem “die Anwendung haengt”-Ticket: Zuerst pruefen, ob es sich um eine blockierende Session handelt, bevor du den Anwendungsserver neu startest.
  2. Bei “Daten fehlen im Bericht”: JOIN-Logik hinterfragen, bevor du einen Datenbankfehler vermutest.
  3. Bei Loeschfehlern wegen Fremdschluessel-Constraints: Nicht den Constraint deaktivieren, sondern mit dem Anwendungsverantwortlichen klaeren, ob ein Soft-Delete-Flag existiert.
  4. Bei wiederkehrenden Deadlocks: Deadlock-Graph sichern und mit konkretem Zeitstempel an DBA/Hersteller-Support weiterleiten - “es deadlockt manchmal” hilft niemandem.
  5. Nie direkt in Produktivtabellen schreiben ohne Transaktion, Backup-Check und Testlauf mit SELECT.

Weiterlernen

Videos

YouTube
Was ist eine Transaktion und ACID? (Mit MySQL Beispiel)
YouTube
SQL: Inner Join - Mehrere Tabellen miteinander verknuepfen!

Kommentare

Frage, Verbesserungsvorschlag oder eigene Erfahrung zu diesem Artikel? Schreib einen Kommentar. Neue Beiträge erscheinen nach kurzer Moderation.

  • Lade Kommentare …
Kommentar schreiben