Locking- und Blocking-Probleme im SQL Server: Wie ich Engpässe erkenne und mit optimierter Transaktionssteuerung löse

Wenn’s klemmt – aber nix crasht

Blocking ist kein Fehler.
Blocking ist gewollt.
Aber wenn’s zu lange dauert, klemmt alles.

Ein Prozess hält Locks.
Ein anderer wartet.
Und Du fragst Dich, warum alles hängt.

Ich zeig Dir, wie ich das erkenne – und löse.

Was ist was?

BegriffBeschreibung
LockingSQL Server sperrt Daten für Integrität
BlockingEin Prozess wartet auf einen Lock
DeadlockZwei Prozesse blockieren sich gegenseitig

Locking brauchst Du.
Blocking musst Du im Griff haben.
Deadlocks musst Du verhindern.

Blocking live sehen

Ich nutze diese Query:

SELECT 
    blocking_session_id AS Blocker,
    session_id AS Blocked,
    wait_type,
    wait_time,
    wait_resource,
    text AS Abfrage
FROM sys.dm_exec_requests
JOIN sys.dm_exec_sessions ON session_id = blocking_session_id
OUTER APPLY sys.dm_exec_sql_text(sql_handle)
WHERE blocking_session_id <> 0

Zeigt Dir sofort, wer wen blockt – und warum.
Ideal für Live-Monitoring.

Deadlocks erkennen

SQL Server schreibt Deadlocks ins Errorlog.
Oder Du aktivierst das per Trace-Flag:

DBCC TRACEON (1222, -1)

Oder Du nutzt Extended Events:

CREATE EVENT SESSION [DeadlockMonitor] ON SERVER
ADD EVENT sqlserver.deadlock_graph
ADD TARGET package0.ring_buffer
WITH (STARTUP_STATE = ON)

Dann kannst Du Deadlocks auswerten – visuell und strukturiert.

Ursache Nr. 1: Transaktionen zu lang

Viele Blockings entstehen durch lange Transaktionen.
Beispiel:

BEGIN TRANSACTION

UPDATE tblKunde SET Ort = 'Hamburg' WHERE Ort = 'HH'

-- Benutzer geht Kaffee holen...

COMMIT

In der Zwischenzeit: alles blockiert.
Ich sage: Kurze Transaktionen. Immer.

Ursache Nr. 2: Reihenfolge beachten

Zwei Prozesse greifen auf dieselben Tabellen – aber in unterschiedlicher Reihenfolge.

Prozess A:

BEGIN TRAN
UPDATE tblKunde WHERE ID = 1
UPDATE tblRechnung WHERE KundeID = 1
COMMIT

Prozess B:

BEGIN TRAN
UPDATE tblRechnung WHERE KundeID = 1
UPDATE tblKunde WHERE ID = 1
COMMIT

Boom: Deadlock.
Ich halte mich an eine feste Sperrreihenfolge.
Immer.

Lesende Prozesse entkoppeln

Wenn SELECTs warten müssen, ist das Mist.

Lösung:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Oder sauberer:

SELECT * FROM tblRechnung WITH (NOLOCK)

Aber Achtung: Dirty Reads.
Für Berichte okay – nicht für Buchhaltung.

Alternativ: Snapshot-Isolation aktivieren.

ALTER DATABASE DeineDB SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE DeineDB SET READ_COMMITTED_SNAPSHOT ON

Dann hast Du lesbare Stände – ohne Blockade.

Indexe helfen – oder schaden

Wenn WHERE-Klauseln keine passenden Indexe haben, scannt SQL Server alles.
Und sperrt mehr als nötig.

Ich prüfe Abfragen mit:

SET STATISTICS IO ON
SET STATISTICS TIME ON

Oder:

EXEC sp_blitzcache

Große I/O = großes Lock-Risiko.

Locking granularer steuern

Du kannst Locking auch direkt beeinflussen.

SELECT * FROM tblKunde WITH (ROWLOCK)

Oder mit UPDLOCK:

SELECT * FROM tblRechnung WITH (UPDLOCK) WHERE ID = 123

Aber: Das ist Profi-Werkzeug.
Falsch eingesetzt = schlimmer als vorher.

Meine Best Practices

  • Transaktionen so kurz wie möglich
  • Konsistente Sperrreihenfolge
  • Lesevorgänge entkoppeln oder mit Snapshot-Isolation
  • Große DML-Operationen nachts oder in Batches
  • Indizes gezielt optimieren
  • Blocking regelmäßig überwachen

Kontrolle statt Zufall.

Blocking wirst Du nie ganz vermeiden.
Aber Du kannst es steuern.
Und Engpässe auflösen, bevor sie wehtun.

Ich schau mir Locking immer an.
Weil langsame Systeme oft nur festhängen.
Nicht überlastet sind.

Kategorien:

Schlagwörter:

Keine Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert