Skip to content

Commit cb61400

Browse files
committed
82 – Troubleshooting laufender Sessions & Requests (SSMS / SQL Server)
1 parent 6ca6b7f commit cb61400

6 files changed

Lines changed: 1103 additions & 0 deletions

File tree

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/* ----------------------------------------------------------------------
2+
Kontext-Check: Verbindung, DB, Login/Host/Client und Serverzeit
3+
Zweck: Verifiziert, gegen welchen Server/DB/Benutzer/Client du arbeitest.
4+
---------------------------------------------------------------------- */
5+
SELECT
6+
@@SERVERNAME AS server_name,
7+
DB_NAME() AS current_database,
8+
SUSER_SNAME() AS login_name,
9+
HOST_NAME() AS host_name,
10+
PROGRAM_NAME() AS program_name,
11+
SYSDATETIMEOFFSET() AS server_time;
12+
13+
14+
/* ----------------------------------------------------------------------
15+
(1) Parameter: Zielprozedur und Suchmuster
16+
- @ProcName: Name der gesuchten Stored Procedure.
17+
- @LikeText: Freitext-Suchmuster für SQL-Text (heuristisch).
18+
- @MyLogin/@MyHost/@MyProg: Umgebung des aktuellen Clients (optional nützlich).
19+
- @SSMSFilter: Filter auf SSMS-Clients (anpassbar für ADS o. ä.).
20+
---------------------------------------------------------------------- */
21+
DECLARE @ProcName SYSNAME = N'dbo.usp_Lookup_LW_Order_LW';
22+
DECLARE @LikeText NVARCHAR(200)= N'%usp_Lookup_LW_Order_LW%';
23+
24+
DECLARE @MyLogin SYSNAME = SUSER_SNAME();
25+
DECLARE @MyHost NVARCHAR(128) = HOST_NAME();
26+
DECLARE @MyProg NVARCHAR(128) = PROGRAM_NAME();
27+
28+
DECLARE @SSMSFilter NVARCHAR(200) = N'%Microsoft SQL Server Management Studio%';
29+
30+
31+
/* ----------------------------------------------------------------------
32+
(2) Ziel-Session (SPID) ermitteln:
33+
- Sammelt passende aktive Requests in @m (ohne die eigene Session).
34+
- Filter über SQL-Text (@LikeText) oder EXEC-Aufruf der Prozedur.
35+
- Stellt sicher, dass genau 1 Treffer existiert -> sonst THROW.
36+
Ergebnis: @target_spid enthält die eindeutige Ziel-Session.
37+
---------------------------------------------------------------------- */
38+
DECLARE @target_spid INT;
39+
40+
DECLARE @m TABLE
41+
(
42+
session_id INT PRIMARY KEY,
43+
start_time DATETIME2,
44+
login_name SYSNAME,
45+
host_name NVARCHAR(128),
46+
program_name NVARCHAR(128)
47+
);
48+
49+
INSERT INTO @m (session_id, start_time, login_name, host_name, program_name)
50+
SELECT
51+
r.session_id,
52+
r.start_time,
53+
s.login_name,
54+
s.host_name,
55+
s.program_name
56+
FROM sys.dm_exec_requests AS r
57+
JOIN sys.dm_exec_sessions AS s ON s.session_id = r.session_id
58+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
59+
WHERE s.is_user_process = 1
60+
AND r.session_id <> @@SPID
61+
AND (t.text LIKE @LikeText OR t.text LIKE N'%EXEC%'+@ProcName+'%');
62+
63+
-- 0 Treffer -> eindeutige Fehlermeldung
64+
IF NOT EXISTS (SELECT 1 FROM @m)
65+
THROW 51000, 'No matching session found. Refine your filter (LIKE/@ProcName).', 1;
66+
67+
-- >1 Treffer -> eindeutige Fehlermeldung (oder hier Policy für TOP(1) wählen)
68+
IF (SELECT COUNT(*) FROM @m) > 1
69+
THROW 51001, 'Multiple matching sessions found. Narrow your filter (login/host/program/proc).', 1;
70+
71+
-- genau 1 Treffer -> SPID übernehmen
72+
SELECT @target_spid = session_id FROM @m;
73+
74+
-- Optional: Sichtprüfung der gefundenen Session-Metadaten
75+
SELECT * FROM @m;
76+
77+
PRINT(@target_spid);
78+
79+
80+
/* ----------------------------------------------------------------------
81+
Detailblick auf die Ziel-Session (Request-Ebene):
82+
- Status/Command/Startzeit
83+
- Wartegründe (wait_type/last_wait_type/wait_time)
84+
- Blocker (blocking_session_id)
85+
- DB-Name und aktueller SQL-Text
86+
Zweck: Erste, schnelle Ursachenanalyse (Locks, Memory-Grant, I/O, etc.).
87+
---------------------------------------------------------------------- */
88+
SELECT
89+
r.session_id, r.status, r.command, r.start_time,
90+
r.wait_type, r.last_wait_type, r.wait_time, r.blocking_session_id,
91+
DB_NAME(r.database_id) AS database_name,
92+
t.text AS sql_text
93+
FROM sys.dm_exec_requests r
94+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t
95+
WHERE r.session_id = @target_spid;
96+
97+
98+
/* ----------------------------------------------------------------------
99+
(2a) "Meine Requests" (hier: auf die Ziel-Session eingeschränkt):
100+
- Zeigt Laufzeit, Fortschritt (percent_complete, falls vorhanden),
101+
Blocker, DB und SQL-Text.
102+
Hinweis: percent_complete ist nur bei bestimmten Operationen > 0.
103+
---------------------------------------------------------------------- */
104+
SELECT
105+
r.session_id,
106+
s.login_name, s.host_name, s.program_name,
107+
r.status, r.command, r.start_time,
108+
r.percent_complete, r.total_elapsed_time/1000.0 AS elapsed_s,
109+
r.blocking_session_id,
110+
DB_NAME(r.database_id) AS database_name,
111+
t.text AS sql_text
112+
FROM sys.dm_exec_requests AS r
113+
JOIN sys.dm_exec_sessions AS s
114+
ON s.session_id = r.session_id
115+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
116+
WHERE r.session_id = @target_spid
117+
ORDER BY r.start_time ASC;
118+
119+
120+
/* ----------------------------------------------------------------------
121+
(3) Läuft noch meine Stored Procedure?
122+
- Hier kein heuristisches Muster mehr, sondern direkter Filter auf @target_spid.
123+
- Liefert Status, Command, Startzeit, Umgebung und SQL-Text.
124+
Zweck: Bestätigung, dass die ermittelte SPID wirklich "deine" Ausführung ist.
125+
---------------------------------------------------------------------- */
126+
SELECT
127+
r.session_id, r.status, r.command, r.start_time,
128+
s.login_name, s.host_name, s.program_name,
129+
DB_NAME(r.database_id) AS database_name,
130+
t.text AS sql_text
131+
FROM sys.dm_exec_requests AS r
132+
JOIN sys.dm_exec_sessions AS s ON s.session_id = r.session_id
133+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
134+
WHERE s.is_user_process = 1
135+
AND r.session_id = @target_spid
136+
ORDER BY r.start_time ASC;
137+
138+
139+
/* ----------------------------------------------------------------------
140+
Status/Waits/Blocker & SQL-Text der Ziel-SPID:
141+
- Kompakte Ansicht für Troubleshooting (Warten, Blocker, DB, SQL).
142+
---------------------------------------------------------------------- */
143+
SELECT r.session_id, r.status, r.command, r.start_time,
144+
r.wait_type, r.last_wait_type, r.wait_time, r.blocking_session_id,
145+
DB_NAME(r.database_id) AS db_name,
146+
t.text
147+
FROM sys.dm_exec_requests r
148+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t
149+
WHERE r.session_id = @target_spid;
150+
151+
152+
/* ----------------------------------------------------------------------
153+
Blocker-Hierarchie:
154+
- Zeigt an, welche Sessions andere blockieren (Kette).
155+
- Hier als Gesamtüberblick für alle mit Blocking; Fokus auf @target_spid
156+
folgt in der nächsten Abfrage "wer blockiert wen?".
157+
---------------------------------------------------------------------- */
158+
;WITH c AS (
159+
SELECT session_id, blocking_session_id
160+
FROM sys.dm_exec_requests WHERE blocking_session_id <> 0
161+
)
162+
SELECT DISTINCT r.session_id AS victim, r.blocking_session_id AS blocker,
163+
vt.text AS victim_sql, bt.text AS blocker_sql
164+
FROM sys.dm_exec_requests r
165+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) vt
166+
OUTER APPLY sys.dm_exec_sql_text((SELECT r2.sql_handle FROM sys.dm_exec_requests r2 WHERE r2.session_id=r.blocking_session_id)) bt
167+
WHERE r.blocking_session_id <> 0;
168+
169+
170+
/* ----------------------------------------------------------------------
171+
Memory-Grant-Warteschlange (global):
172+
- Zeigt Sessions mit angeforderten/gewährten Speichermengen für Abfragen.
173+
- Hohe wait_time_ms + granted_memory_kb = 0 deuten auf Engpässe hin.
174+
---------------------------------------------------------------------- */
175+
SELECT session_id, requested_memory_kb, granted_memory_kb,
176+
required_memory_kb, max_used_memory_kb, wait_time_ms
177+
FROM sys.dm_exec_query_memory_grants
178+
WHERE session_id = @target_spid
179+
ORDER BY wait_time_ms DESC;
180+
181+
182+
/* ----------------------------------------------------------------------
183+
Wer blockiert wen? (inkl. Kette) – auf die Ziel-Session fokussiert:
184+
- Baut eine Kette von Blockings auf und filtert dann @target_spid.
185+
- Erkennt schnell, ob die Ziel-Session Opfer in einer Blocker-Kette ist.
186+
---------------------------------------------------------------------- */
187+
;WITH blockers AS (
188+
SELECT
189+
r.session_id,
190+
r.blocking_session_id,
191+
CAST(CONCAT(r.session_id, N'') AS NVARCHAR(4000)) AS chain
192+
FROM sys.dm_exec_requests AS r
193+
WHERE r.blocking_session_id <> 0
194+
UNION ALL
195+
SELECT
196+
r.session_id,
197+
r.blocking_session_id,
198+
CAST(b.chain + N' -> ' + CAST(r.session_id AS NVARCHAR(10)) AS NVARCHAR(4000)) AS chain
199+
FROM sys.dm_exec_requests AS r
200+
JOIN blockers b ON r.blocking_session_id = b.session_id
201+
WHERE r.blocking_session_id <> 0
202+
)
203+
SELECT DISTINCT
204+
s.session_id,
205+
s.login_name, s.host_name, s.program_name,
206+
r.status, r.command, r.start_time,
207+
r.blocking_session_id,
208+
b.chain
209+
FROM sys.dm_exec_sessions s
210+
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
211+
LEFT JOIN blockers b ON s.session_id = b.session_id
212+
WHERE s.is_user_process = 1
213+
AND s.session_id = @target_spid
214+
ORDER BY s.session_id;
215+
216+
217+
/* ----------------------------------------------------------------------
218+
Ausführungsplan (aktuell) der Ziel-Session:
219+
- Liefert Plan XML (query_plan) + SQL-Text; hilfreich zur Plananalyse.
220+
- Hinweis: Nicht jeder Request liefert einen Plan (z. B. kurze/laufende).
221+
---------------------------------------------------------------------- */
222+
SELECT TOP (20)
223+
r.session_id, r.status, r.command, r.start_time,
224+
DB_NAME(r.database_id) AS database_name,
225+
t.text AS sql_text,
226+
qp.query_plan
227+
FROM sys.dm_exec_requests AS r
228+
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
229+
OUTER APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp
230+
WHERE r.session_id = @target_spid
231+
ORDER BY r.start_time ASC;
232+
233+
234+
/* ----------------------------------------------------------------------
235+
Aktive Transaktionen der Ziel-Session:
236+
- Verknüpft Session -> SessionTransactions -> ActiveTransactions -> DB/Log.
237+
- Zeigt Typ/Status/Begin-Zeitpunkt und Log-Verbrauch pro DB.
238+
Zweck: Prüfen, ob lange/umfangreiche Transaktionen die Ursache sind.
239+
---------------------------------------------------------------------- */
240+
SELECT
241+
s.session_id,
242+
at.transaction_id,
243+
at.name,
244+
at.transaction_begin_time,
245+
at.transaction_type, -- 1=Read/Write, 2=Read-only, 3=System, 4=Distributed
246+
at.transaction_state, -- 0..8 (2=Active, 6=Committed, 7=Rolled back, ...)
247+
dt.database_id,
248+
DB_NAME(dt.database_id) AS database_name,
249+
dt.database_transaction_log_bytes_used/1024.0/1024.0 AS log_used_MB
250+
FROM sys.dm_exec_sessions AS s
251+
JOIN sys.dm_tran_session_transactions AS st ON st.session_id = s.session_id
252+
JOIN sys.dm_tran_active_transactions AS at ON at.transaction_id = st.transaction_id
253+
LEFT JOIN sys.dm_tran_database_transactions AS dt ON dt.transaction_id = at.transaction_id
254+
WHERE s.is_user_process = 1
255+
AND s.session_id = @target_spid
256+
ORDER BY at.transaction_begin_time;

0 commit comments

Comments
 (0)