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?
Begriff | Beschreibung |
---|---|
Locking | SQL Server sperrt Daten für Integrität |
Blocking | Ein Prozess wartet auf einen Lock |
Deadlock | Zwei 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.
Keine Antworten