-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUSP_CHECK_BROKER.sql
417 lines (357 loc) · 11.3 KB
/
USP_CHECK_BROKER.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
IF OBJECT_ID(N'dbo.USP_CHECK_BROKER') IS NOT NULL
BEGIN
DROP PROCEDURE DBO.USP_CHECK_BROKER;
END;
GO
CREATE PROCEDURE dbo.USP_CHECK_BROKER
@REPAIR BIT = 0
, @START DATETIME = NULL
, @VERBOSE BIT = 0
AS
/******************************************************************************
** Diagnostics sur le service BROKER de SQL Server
Réparation du Broker : EXEC USP_CHECK_BROKER @REPAIR = 1
Diagnostics détaillés : EXEC USP_CHECK_BROKER @VERBOSE = 1
*******************************************************************************/
BEGIN
SET NOCOUNT ON;
DECLARE @WARNINGS TABLE (
MSG VARCHAR(MAX));
DECLARE @SQL NVARCHAR(MAX) = '';
DECLARE @TIMER INT;
DECLARE @QNAME VARCHAR(200);
DECLARE @END DATETIME = GETDATE();
DECLARE @CONVERSATION_HANDLE UNIQUEIDENTIFIER;
IF @START IS NULL
BEGIN
SET @START = DATEADD(dd, -1, GETDATE());
END;
IF @REPAIR = 1
BEGIN
SET @SQL = '';
-- Fin des conversation ouvertes
DECLARE CONV CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT DISTINCT
[conversation_handle]
FROM sys.conversation_endpoints;
OPEN CONV;
FETCH NEXT FROM CONV INTO @CONVERSATION_HANDLE;
WHILE @@FETCH_STATUS = 0
BEGIN
END CONVERSATION @CONVERSATION_HANDLE WITH CLEANUP;
FETCH NEXT FROM CONV INTO @CONVERSATION_HANDLE;
END;
CLOSE CONV;
DEALLOCATE CONV;
--on set le owner de la DB à sa
SET @SQL = 'USE master;
ALTER AUTHORIZATION ON DATABASE::' + DB_NAME() + ' TO sa;';
EXEC sp_executesql @SQL;
IF
(
SELECT DB.is_broker_enabled
FROM sys.databases AS DB
WHERE DB.name = DB_NAME()
) = 0
BEGIN
--afin d'éviter tout soucis de service_broker_id identique, on reseed
--et on met en route le broker
SET @SQL = 'USE master;
ALTER DATABASE ' + DB_NAME() + ' SET NEW_BROKER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE ' + DB_NAME() + ' SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE;';
EXEC sp_executesql @SQL;
END;
SET @SQL = '';
SELECT @SQL+=' ALTER QUEUE ' + name + ' WITH STATUS = ON , ACTIVATION (STATUS = ON), POISON_MESSAGE_HANDLING (STATUS = OFF) ;
'
FROM sys.service_queues
WHERE is_ms_shipped = 0;
-- Activation des queues inactives
EXEC sp_executesql @SQL;
END;
--Test 1: is SB enabled and running properly?
IF EXISTS
(
SELECT 'sys.databases' AS [sys.databases]
, DB.service_broker_guid
, DB.is_broker_enabled
, DB.name
, DB.database_id
FROM sys.databases AS DB
WHERE DB.database_id = DB_ID()
AND DB.service_broker_guid IS NOT NULL
AND DB.is_broker_enabled <> 1
)
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('Test 1: Service Broker is not enabled/running correctly.');
END;
--Test 2: look for dropped Q monitors
IF EXISTS
(
SELECT 1
FROM sys.service_queues AS Q
INNER JOIN sys.dm_broker_queue_monitors AS MON
ON Q.object_id = MON.queue_id
AND MON.database_id = DB_ID()
WHERE Q.is_ms_shipped = 0 --dont show me system stuff
AND MON.State = 'DROPPED'
)
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('Test 2: We have DROPPED queue monitors. Please investigate.');
END;
--Test 3: check for Qs in NOTIFIED state
--this means that the Q activator was notified, but is not issuing the proper RECEIVE. This could mean that the shell activator proc is enabled, or it
--could mean the activator is bad, or ???
SET @TIMER = 0;
WHILE EXISTS
(
SELECT 1
FROM sys.service_queues AS Q
INNER JOIN sys.dm_broker_queue_monitors AS MON
ON Q.object_id = MON.queue_id
AND MON.database_id = DB_ID()
WHERE Q.is_ms_shipped = 0 --dont show me system stuff
AND MON.state = 'NOTIFIED'
)
BEGIN
SET @TIMER = @TIMER + 1;
IF @TIMER > 5
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('WARNING: Queues exist in NOTIFIED state for over 10 seconds. This may mean we have only a shell activator proc installed. Please investigate.');
BREAK;
END;
WAITFOR DELAY '00:00:02'; --wait 2 seconds and try again
END;
--Test 4: are any of our activated Qs sitting in a disabled state. This likely means the activator isn't working.
IF EXISTS
(
SELECT 1
FROM sys.service_queues
WHERE is_activation_enabled = 1
AND (is_enqueue_enabled = 0
OR is_receive_enabled = 0)
)
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('Test 4: Activated Queues exist that are disabled for enqueue and receive.
This likely means the activator procedure is throwing errors.
Issue the following command: ALTER QUEUE [] WITH ACTIVATION (DROP);
Then manually run the activation procedure that is erroring, correct the errors, and run SETUP again.');
END;
--Test 5: "Poison Message" detection
IF EXISTS
(
SELECT 1
FROM sys.service_queues
WHERE is_receive_enabled = 0
)
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('We have disabled queues, probably from poison messages. Please investigate.
The queue can be re-enabled with: ALTER QUEUE [] WITH STATUS = ON
after the problem is resolved. ');
END;
--Test 6: do we have a "Conversation Population Explosion"?
--this means that we have a ton of conversations not in a CLOSED state.
--CLOSED conversations hang around for about 30 mins as a security precaution so just ignore them.
--In this case we may not have our conversations working correctly and the receiver is not ending the conversation.
--there is no magic to 500. And if we ever enable Service Broker for more things then the number may need to go up.
IF
(
SELECT COUNT(*)
FROM sys.conversation_endpoints
WHERE state_desc != 'CLOSED'
) > 500
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('WARNING: We may not be CLOSEing conversations properly. Please investigate.');
END;
--Test 7: do we have conversations stuck in the transmission Q? If so something is misconfigured.
SET @TIMER = 0;
WHILE EXISTS
(
SELECT 1
FROM sys.transmission_queue
)
BEGIN
SELECT @TIMER = @TIMER + 1;
IF @TIMER > 5
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('WARNING: There may be items in the transmission_queue that are not being processed. Or we have VERY busy queues. Please investigate.');
BREAK;
END;
WAITFOR DELAY '00:00:02'; --wait 2 seconds and try again
END;
--Test 8: Monitoring is not activated
IF EXISTS
(
SELECT 1
FROM sys.service_queues AS Q
WHERE Q.is_ms_shipped = 0
AND NOT EXISTS
(
SELECT 1
FROM sys.dm_broker_queue_monitors AS MON
WHERE Q.object_id = MON.queue_id
AND MON.database_id = DB_ID()
)
)
BEGIN
INSERT INTO @WARNINGS(MSG)
VALUES('Test 8: Monitoring is not activated, EXEC USP_CHECK_BROKER @REPAIR = 1; ');
END;
IF NOT EXISTS
(
SELECT 1
FROM @WARNINGS
)
BEGIN
SELECT 'Service Broker OK' AS MSG;
END;
ELSE
BEGIN
SELECT WARN.MSG
FROM @WARNINGS AS WARN
WHERE WARN.MSG != '';
END;
SELECT Q.[name] AS QUEUE_NAME
, MON.[STATE] AS [STATE]
, DB.IS_BROKER_ENABLED AS IS_BROKER_ENABLED
, Q.IS_ENQUEUE_ENABLED AS IS_ENQUEUE_ENABLED
, Q.IS_RECEIVE_ENABLED AS IS_RECEIVE_ENABLED
, Q.IS_ACTIVATION_ENABLED AS IS_ACTIVATION_ENABLED
, MON.TASKS_WAITING AS TASKS_WAITING
, MON.LAST_ACTIVATED_TIME AS LAST_ACTIVATED_TIME
, MON.LAST_EMPTY_ROWSET_TIME AS LAST_EMPTY_ROWSET_TIME
, Q.MAX_READERS AS MAX_READERS
, Q.ACTIVATION_PROCEDURE AS ACTIVATION_PROCEDURE
, Q.EXECUTE_AS_PRINCIPAL_ID AS EXECUTE_AS_PRINCIPAL_ID
, SUSER_SNAME(DB.owner_sid) AS [OWNER_NAME]
, DB.[name] AS [DB_NAME]
, DB.service_broker_guid
FROM SYS.SERVICE_QUEUES AS Q
CROSS JOIN sys.databases AS db
LEFT JOIN sys.dm_broker_queue_monitors AS mon
ON Q.object_id = mon.queue_id
AND db.database_id = mon.database_id
WHERE db.database_id = DB_ID()
AND Q.IS_MS_SHIPPED = 0;
IF @VERBOSE = 1
BEGIN
--just runs a bunch of misc queries that may be helpful for troubleshooting
IF EXISTS
(
SELECT 1
FROM sys.transmission_queue
)
BEGIN
SELECT *
, CONVERT(XML, message_body) AS message_body_XML
, 'sys.transmission_queue' AS [sys.transmission_queue]
FROM sys.transmission_queue;
END;
IF EXISTS
(
SELECT 1
FROM sys.conversation_endpoints
)
BEGIN
SELECT SVC.NAME AS [SERVICE_NAME]
, Q.ACTIVATION_PROCEDURE
, SVC_CONTRACT.NAME AS [CONTRACT_NAME]
, Q_CONTRACT.ACTIVATION_PROCEDURE AS [CONTRACT_PROCEDURE]
, CONV.*
, 'sys.conversation_endpoints' AS [sys.conversation_endpoints]
FROM sys.conversation_endpoints AS CONV
INNER JOIN sys.services AS SVC
ON SVC.SERVICE_ID = CONV.SERVICE_ID
INNER JOIN sys.services AS SVC_CONTRACT
ON SVC_CONTRACT.SERVICE_ID = CONV.SERVICE_CONTRACT_ID
INNER JOIN sys.SERVICE_QUEUES AS Q
ON Q.OBJECT_ID = SVC.SERVICE_QUEUE_ID
LEFT JOIN sys.SERVICE_QUEUES AS Q_CONTRACT
ON Q_CONTRACT.OBJECT_ID = SVC_CONTRACT.SERVICE_QUEUE_ID;
END;
IF EXISTS
(
SELECT 1
FROM sys.dm_broker_activated_tasks
)
BEGIN
SELECT *
, 'sys.dm_broker_activated_tasks' AS [sys.dm_broker_activated_tasks]
FROM sys.dm_broker_activated_tasks;
END;
IF EXISTS
(
SELECT 1
FROM sys.conversation_endpoints
)
BEGIN
SELECT far_service
, state_desc
, COUNT(*) AS messages
FROM sys.conversation_endpoints
GROUP BY state_desc
, far_service
ORDER BY far_service
, state_desc;
END;
-- Log SQL SERVER
EXEC xp_readerrorlog 0
, 1
, NULL
, NULL
, @START
, @END
, 'DESC';
--display the contents of the queues
DECLARE ssb CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT Q.name
FROM sys.service_queues AS Q
WHERE Q.is_ms_shipped = 0;
OPEN ssb;
FETCH NEXT FROM ssb INTO @QNAME;
SET @SQL = '';
WHILE(@@fetch_status = 0)
BEGIN
IF @SQL != ''
BEGIN
SET @SQL = @SQL + ' UNION ';
END;
SET @SQL = @SQL + 'SELECT ''' + @QNAME + ''' AS QUEUENAME , * FROM ' + @QNAME + ' WITH (NOLOCK)';
FETCH NEXT FROM ssb INTO @QNAME;
END;
CLOSE ssb;
DEALLOCATE ssb;
IF @SQL != ''
BEGIN
SET @SQL = ' DECLARE @NB INT ;
WITH Q AS ( ' + @SQL + ' ) SELECT @NB = COUNT(*) FROM Q ;
IF @NB >0
WITH Q AS ( ' + @SQL + ' ) SELECT * FROM Q ;
';
EXEC sp_executesql @SQL;
END;
-- Performance counters
SELECT [object_name]
, counter_name
, cntr_value
, instance_name
FROM sys.dm_os_performance_counters
WHERE instance_name = DB_NAME()
AND counter_name IN('Tasks Running', 'Task Limit Reached', 'Tasks Aborted/sec')
UNION
SELECT [object_name]
, counter_name
, cntr_value
, instance_name
FROM sys.dm_os_performance_counters
WHERE counter_name IN('Activation Errors Total', 'Broker Transaction Rollbacks', 'Corrupted Messages Total', 'Enqueued TransmissionQ Msgs/sec', 'Dequeued TransmissionQ Msgs/sec', 'SQL SENDs/sec', 'SQL SEND Total', 'SQL RECEIVEs/sec', 'SQL RECEIVE Total');
END;
END;
GO