Einleitung
„Kennst du das auch? Du hast eine schier endlos oft aufgerufene Funktion, die in jedem zweiten Query steckt – sei es im Reporting, in Batch‑Jobs oder in Live‑Anwendungen. Da suchst du stundenlang nach einem Fenster, in dem du sie mal eben ändern könntest, ohne dass irgendwo Verbindungen abbrechen oder Prozesse hängen bleiben. Es ist, als würdest du versuchen, in einem Bienenstock eine Biene zu fangen, ohne den ganzen Stock aufzuscheuchen. Genau hier kommt mein bewährtes Super‑Skript ins Spiel, das mir seit Jahren tagtäglich hilft, den perfekten Zeitpunkt zu nutzen und den heimlichen Blockierer zu enttarnen!“
Warum dieses Skript dein neuer bester Freund wird
Statt wild im SPAZIERGANG zwischen SSMS‑Fenstern hin und her zu klicken, erlaubt dir dieses Skript:
- Einen einzigen Aufruf mit dem Namen deiner Stored Procedure oder Funktion.
- Automatische Erkennung, ob es sich um eine Prozedur, Skalar‑ oder Tabellen‑Funktion handelt.
- Abfrage aller aktiven Locks auf genau dieses Objekt in deiner aktuellen Datenbank.
- Übersichtliche Ausgabe der Session‑ID, des Benutzers, Hosts, Lock‑Typs und sogar des gerade ausgeführten Statements.
- Tipps, wie du die blockierende Session identifizierst und – falls nötig – einfach beendest.
So entgeht dir kein heimlicher Blockierer mehr – selbst bei Funktionen, die nonstop im Einsatz sind!
Aufbau des Skripts im Detail
1) Parameter & Objekt‑ID ermitteln
DECLARE
@ObjectName NVARCHAR(128) = N'dbo.DeinObjektName',
@ObjID INT,
@ObjectType NVARCHAR(32);
SET @ObjID = OBJECT_ID(@ObjectName);
IF @ObjID IS NULL
BEGIN
RAISERROR('Objekt %s nicht gefunden.',16,1,@ObjectName);
RETURN;
END
- @ObjectName: Hier gibst du einmalig den vollqualifizierten Namen an – egal ob Prozedur oder Funktion.
- OBJECT_ID ermittelt die interne ID im System‑Katalog.
- Falls nichts gefunden wird, bekommst du eine freundliche Fehlermeldung und das Skript stoppt sofort.
2) Objekttyp automatisch bestimmen
IF OBJECTPROPERTY(@ObjID,'IsProcedure') = 1
SET @ObjectType = N'Stored Procedure';
ELSE IF OBJECTPROPERTY(@ObjID,'IsScalarFunction') = 1
SET @ObjectType = N'Skalar‑Funktion';
ELSE IF OBJECTPROPERTY(@ObjID,'IsTableFunction') = 1
SET @ObjectType = N'Tabellen‑Funktion';
ELSE IF OBJECTPROPERTY(@ObjID,'IsInlineFunction') = 1
SET @ObjectType = N'Inline‑Funktion';
ELSE
SET @ObjectType = N'Unbekannter Objekttyp';
PRINT CONCAT('Untersuche Locks für ', @ObjectType, ' ', @ObjectName, ' (Objekt‑ID = ', @ObjID, ')');
- Ab hier weiß das Skript genau, mit welchem Objekt es zu tun hat – und du siehst eine klare Meldung im Ergebnisfenster.
3) Aktive Locks abfragen
SELECT
tl.request_session_id AS SessionID,
es.login_name AS LoginName,
es.host_name AS HostName,
er.status AS RequestStatus,
er.command AS Command,
tl.resource_type AS ResourceType,
tl.request_mode AS LockMode,
tl.request_status AS LockStatus,
SUBSTRING(st.text,
(er.statement_start_offset/2)+1,
((CASE er.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE er.statement_end_offset
END
- er.statement_start_offset)/2)+1
) AS ExecutingStatement
FROM sys.dm_tran_locks AS tl
JOIN sys.dm_exec_requests AS er
ON er.session_id = tl.request_session_id
JOIN sys.dm_exec_sessions AS es
ON es.session_id = tl.request_session_id
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
WHERE tl.resource_associated_entity_id = @ObjID
AND tl.resource_type = 'OBJECT'
AND tl.resource_database_id = DB_ID();
- sys.dm_tran_locks zeigt alle Locks mit Details.
- sys.dm_exec_requests/sessions ergänzt um Status, Benutzer und Host.
- CROSS APPLY liefert dir den exakt ausgeführten SQL‑Text – super nützlich, falls mehrere Transaktionen gleichzeitig laufen.
- Filter auf
resource_type='OBJECT'
und deine aktuelle Datenbank verhindert unnötige Ergebnisse.
Beim Blick auf LockMode = ‘X’ (Exclusive) und LockStatus = ‘GRANTED’ findest du in der Regel den Übeltäter.
4) Session‑Details nachschlagen
-- Variante A: Schnell mit sp_who2
-- EXEC sp_who2;
-- Variante B: Detaillierte Infos
SELECT
session_id,
login_name,
host_name,
status,
program_name,
database_id,
last_request_start_time,
last_request_end_time
FROM sys.dm_exec_sessions
WHERE session_id = <SessionID>;
- sp_who2 liefert eine schnelle Übersicht – ideal, um mehrere Sessions zu scannen.
- sys.dm_exec_sessions gibt dir volle Transparenz: wann die letzte Abfrage gestartet und beendet wurde, mit welchem Programm der Client verbunden ist, usw.
5) Sp_WhoIsActive (Option)
Falls du das geniale sp_WhoIsActive installiert hast, kannst du mit einem Zusatzparameter noch mehr Insights gewinnen:
EXEC sp_WhoIsActive
@filter_session_id = <SessionID>,
@get_locks = 1,
@get_outer_command = 1;
Das zeigt dir Blocker‑Chains, offene Transaktionen und vieles mehr in einer schönen Tabelle.
6) Gegenmaßnahmen
- Kill vorübergehend:
KILL <SessionID>;
- Nur in unkritischen Szenarien oder zu Testzwecken!
- Ursache finden: Schau in der Anwendung nach, ob Transaktionen offenbleiben oder komplexe Abfragen lange laufen.
- Deployment‑Strategie anpassen: Plane DDL‑Änderungen (ALTER PROCEDURE/FUNCTION) zu Zeiten, in denen möglichst wenige Sessions aktiv sind.
Fazit
Ob deine Funktion nun jede Sekunde aufgerufen wird oder deine Prozedur Teil einer nächtlichen Batch‑Verarbeitung ist – mit diesem Skript findest du den Blockierer im Handumdrehen. Übergebe einfach den Objekt‑Namen, und schon siehst du, wer gerade den exklusiven Zugriff hält. Perfektes Timing war noch nie so einfach! 🚀