SQL Server fournit de nombreux outils de monitoring d’arrière-plan par défaut, comme le journal SQL Server, la session d’événements étendus system_health, mais aussi une trace SQL Profiler. Cette dernière est enregistrée dans un fichier dans le répertoire des journaux, et SQL Server conserve 6 fichiers de cette trace.
Elle capture, entre autres, les événements d’échec d’authentification, la création d’objets dans TempDB, les warnings sur Hash et Sort, les grossissements de fichiers, et de nombreux autres événements. Ceux-ci peuvent aider à comprendre, a posteriori, ce qui a causé une grande consommation de CPU, des latences disque, …
Comme cette trace est écrite sur disque, il peut malencontreusement arriver que ce dernier devienne plein, provoquant alors l’arrêt automatique et forcé de la trace. Ce léger incident (l’arrêt de la trace, pas l’absence d’espace disque libre !) n’empêche aucunement l’instance de fonctionner, ou au moins d’être accessible. Cependant, comment peut-on redémarrer cette trace sans redémarrer l’instance SQL Server ?
En effet, la documentation nous indique que la trace par défaut n’est démarrée que lorsque l’instance démarre aussi … nous allons voir que c’est incomplet. Une fois le disque supportant la trace disposant à nouveau d’espace disque libre, on constate que la trace par défaut est arrêtée à l’aide de l’instruction suivante :
1 2 | SELECT * FROM sys.traces |
Lorsque la trace par défaut est active, cette requête retourne une ligne, dont la colonne id est à 1. On peut vérifier que c’est la trace par défaut à l’aide de la valeur de la colonne is_default : 1 si c’est le cas, 0 à l’inverse :
Dans la situation de l’incident que nous évoquons, cette même requête ne retournera pas de ligne (ou tout du moins aucune dont la colonne is_default est à 1). Pour démarrer la trace par défaut, il suffit de s’en remettre à l’option de configuration d’instance default trace enabled :
1 2 3 | SELECT * FROM sys.configurations WHERE name LIKE '%trace%' |
On voit que c’est une option avancée et dynamique, ce qui signifie qu’un redémarrage de l’instance SQL Server n’est pas nécessaire. Dès lors, pour réactiver la trace par défaut, il suffit de positionner cette option à 0, puis immédiatement ensuite à 1, ce qui est sa valeur par défaut :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | -- Activation de la modification des options d'instance avancées EXEC sp_configure 'show advanced options', 1 GO RECONFIGURE GO -- Désactivation de la trace par défaut EXEC sp_configure 'default trace enabled', 0 GO RECONFIGURE GO -- Ré-activation de la trace par défaut EXEC sp_configure 'default trace enabled', 1 GO RECONFIGURE GO -- Désactivation de la modification des options d'instance avancées EXEC sp_configure 'show advanced options', 0 GO RECONFIGURE GO |
Sur exécution de ce lot, l’onglet Messages du panneau de résultats de SQL Server Management Studio affiche :
Configuration option ‘show advanced options’ changed from 0 to 1. Run the RECONFIGURE statement to install.
Configuration option ‘default trace enabled’ changed from 1 to 0. Run the RECONFIGURE statement to install.
Configuration option ‘default trace enabled’ changed from 0 to 1. Run the RECONFIGURE statement to install.
Configuration option ‘show advanced options’ changed from 1 to 0. Run the RECONFIGURE statement to install.
Et l’on voit alors que la trace a été démarrée, en interrogeant une nouvelle fois la vue sys.traces.
On trouvera aussi dans les journal de SQL Server les lignes suivantes :
1 2 3 4 5 | -- Recherche de l'heure de dernier démarrage de l'instance SQL Server SELECT sqlserver_start_time FROM sys.dm_os_sys_info -- Recherche du démarrage de la trace par défaut EXEC xp_readerrorlog 0, 1, N'Trace ID 1' |
Ici on voit bien que la trace par défaut a été démarré par le système (le SPID est inférieur à 50), quelques millisecondes après le démarrage de celui-ci. Elle a ensuite été redémarrée par nos soins un peu plus tard.
Petite note finale : les fonctionnalités SQL Trace et SQL Profiler sont obsolètes, et remplacées par la fonctionnalité d'événements étendus, plus puissante et performante. Vous pouvez voir comment les utiliser dans cette vidéo, en gardant bien à l’esprit que dès SQL Server 2012, une interface graphique intégrée à SQL Server Management Studio permet de créer une session sans écrire de code, et de visualiser les événements capturés à la façon de ce que permet SQL Profiler.
Enfin, pour interroger un fichier de trace SQL Profiler, il suffit d’utiliser la fonction sys.fn_trace_gettable(). Donc pour en faire l’analyse, on peut utiliser le lot suivant :
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 | DECLARE @events TABLE ( event_id tinyint , event_name sysname ) INSERT @events VALUES (0, 'Reserved') , (1, 'Reserved') , (2, 'Reserved') , (3, 'Reserved') , (4, 'Reserved') , (5, 'Reserved') , (6, 'Reserved') , (7, 'Reserved') , (8, 'Reserved') , (9, 'Reserved') , (10, 'RPC:Completed') , (11, 'RPC:Starting') , (12, 'SQL:BatchCompleted') , (13, 'SQL:BatchStarting') , (14, 'Audit Login') , (15, 'Audit Logout') , (16, 'Attention') , (17, 'ExistingConnection') , (18, 'Audit Server Starts and Stops') , (19, 'DTCTransaction') , (20, 'Audit Login Failed') , (21, 'EventLog') , (22, 'ErrorLog') , (23, 'Lock:Released') , (24, 'Lock:Acquired') , (25, 'Lock:Deadlock') , (26, 'Lock:Cancel') , (27, 'Lock:Timeout') , (28, 'Degree of Parallelism Event (7.0 Insert)') , (29, 'Reserved') , (30, 'Reserved') , (31, 'Reserved') , (32, 'Reserved') , (33, 'Exception') , (34, 'SP:CacheMiss') , (35, 'SP:CacheInsert') , (36, 'SP:CacheRemove') , (37, 'SP:Recompile') , (38, 'SP:CacheHit') , (39, 'Deprecated') , (40, 'SQL:StmtStarting') , (41, 'SQL:StmtCompleted') , (42, 'SP:Starting') , (43, 'SP:Completed') , (44, 'SP:StmtStarting') , (45, 'SP:StmtCompleted') , (46, 'Object:Created') , (47, 'Object:Deleted') , (48, 'Reserved') , (49, 'Reserved') , (50, 'SQL Transaction') , (51, 'Scan:Started') , (52, 'Scan:Stopped') , (53, 'CursorOpen') , (54, 'TransactionLog') , (55, 'Hash Warning') , (56, 'Reserved') , (57, 'Reserved') , (58, 'Auto Stats') , (59, 'Lock:Deadlock Chain') , (60, 'Lock:Escalation') , (61, 'OLE DB Errors') , (62, 'Reserved') , (63, 'Reserved') , (64, 'Reserved') , (65, 'Reserved') , (66, 'Reserved') , (67, 'Execution Warnings') , (68, 'Showplan Text (Unencoded)') , (69, 'Sort Warnings') , (70, 'CursorPrepare') , (71, 'Prepare SQL') , (72, 'Exec Prepared SQL') , (73, 'Unprepare SQL') , (74, 'CursorExecute') , (75, 'CursorRecompile') , (76, 'CursorImplicitConversion') , (77, 'CursorUnprepare') , (78, 'CursorClose') , (79, 'Missing Column Statistics') , (80, 'Missing Join Predicate') , (81, 'Server Memory Change') , (82, 'User Configurable (0-9)') , (83, 'User Configurable (0-9)') , (84, 'User Configurable (0-9)') , (85, 'User Configurable (0-9)') , (86, 'User Configurable (0-9)') , (87, 'User Configurable (0-9)') , (88, 'User Configurable (0-9)') , (89, 'User Configurable (0-9)') , (90, 'User Configurable (0-9)') , (91, 'User Configurable (0-9)') , (92, 'Data File Auto Grow') , (93, 'Log File Auto Grow') , (94, 'Data File Auto Shrink') , (95, 'Log File Auto Shrink') , (96, 'Showplan Text') , (97, 'Showplan All') , (98, 'Showplan Statistics Profile') , (99, 'Reserved') , (100, 'RPC Output Parameter') , (101, 'Reserved') , (102, 'Audit Statement GDR Event') , (103, 'Audit Object GDR Event') , (104, 'Audit AddLogin Event') , (105, 'Audit Login GDR Event') , (106, 'Audit Login Change Property Event') , (107, 'Audit Login Change Password Event') , (108, 'Audit Add Login to Server Role Event') , (109, 'Audit Add DB User Event') , (110, 'Audit Add Member to DB Role Event') , (111, 'Audit Add Role Event') , (112, 'Audit App Role Change Password Event') , (113, 'Audit Statement Permission Event') , (114, 'Audit Schema Object Access Event') , (115, 'Audit Backup/Restore Event') , (116, 'Audit DBCC Event') , (117, 'Audit Change Audit Event') , (118, 'Audit Object Derived Permission Event') , (119, 'OLEDB Call Event') , (120, 'OLEDB QueryInterface Event') , (121, 'OLEDB DataRead Event') , (122, 'Showplan XML') , (123, 'SQL:FullTextQuery') , (124, 'Broker:Conversation') , (125, 'Deprecation Announcement') , (126, 'Deprecation Final Support') , (127, 'Exchange Spill Event') , (128, 'Audit Database Management Event') , (129, 'Audit Database Object Management Event') , (130, 'Audit Database Principal Management Event') , (131, 'Audit Schema Object Management Event') , (132, 'Audit Server Principal Impersonation Event') , (133, 'Audit Database Principal Impersonation Event') , (134, 'Audit Server Object Take Ownership Event') , (135, 'Audit Database Object Take Ownership Event') , (136, 'Broker:Conversation Group') , (137, 'Blocked Process Report') , (138, 'Broker:Connection') , (139, 'Broker:Forwarded Message Sent') , (140, 'Broker:Forwarded Message Dropped') , (141, 'Broker:Message Classify') , (142, 'Broker:Transmission') , (143, 'Broker:Queue Disabled') , (144, 'Reserved') , (145, 'Reserved') , (146, 'Showplan XML Statistics Profile') , (148, 'Deadlock Graph') , (149, 'Broker:Remote Message Acknowledgement') , (150, 'Trace File Close') , (151, 'Reserved') , (152, 'Audit Change Database Owner') , (153, 'Audit Schema Object Take Ownership Event') , (154, 'Reserved') , (155, 'FT:Crawl Started') , (156, 'FT:Crawl Stopped') , (157, 'FT:Crawl Aborted') , (158, 'Audit Broker Conversation') , (159, 'Audit Broker Login') , (160, 'Broker:Message Undeliverable') , (161, 'Broker:Corrupted Message') , (162, 'User Error Message') , (163, 'Broker:Activation') , (164, 'Object:Altered') , (165, 'Performance statistics') , (166, 'SQL:StmtRecompile') , (167, 'Database Mirroring State Change') , (168, 'Showplan XML For Query Compile') , (169, 'Showplan All For Query Compile') , (170, 'Audit Server Scope GDR Event') , (171, 'Audit Server Object GDR Event') , (172, 'Audit Database Object GDR Event') , (173, 'Audit Server Operation Event') , (175, 'Audit Server Alter Trace Event') , (176, 'Audit Server Object Management Event') , (177, 'Audit Server Principal Management Event') , (178, 'Audit Database Operation Event') , (180, 'Audit Database Object Access Event') , (181, 'TM: Begin Tran starting') , (182, 'TM: Begin Tran completed') , (183, 'TM: Promote Tran starting') , (184, 'TM: Promote Tran completed') , (185, 'TM: Commit Tran starting') , (186, 'TM: Commit Tran completed') , (187, 'TM: Rollback Tran starting') , (188, 'TM: Rollback Tran completed') , (189, 'Lock:Timeout (timeout > 0)') , (190, 'Progress Report: Online Index Operation') , (191, 'TM: Save Tran starting') , (192, 'TM: Save Tran completed') , (193, 'Background Job Error') , (194, 'OLEDB Provider Information') , (195, 'Mount Tape') , (196, 'Assembly Load') , (197, 'Reserved') , (198, 'XQuery Static Type') , (199, 'QN: subscription') , (200, 'QN: parameter table') , (201, 'QN: template') , (202, 'QN: dynamics') SELECT FTG.DatabaseName , E.event_name , FTG.ApplicationName , COUNT(*) AS occurences , MIN(FTG.StartTime) AS first_time , MAX(FTG.StartTime) AS last_time , FTG.SessionLoginName , E.event_id FROM sys.fn_trace_gettable ( ( SELECT LEFT(path, LEN(path) - CHARINDEX('\', REVERSE(path))) + '\Log.trc' FROM sys.traces WHERE is_default = 1 ) , 6 ) AS FTG LEFT JOIN @events AS E ON E.event_id = FTG.EventClass WHERE FTG.EventClass NOT BETWEEN 65527 AND 65528 GROUP BY FTG.DatabaseName, E.event_name, FTG.ApplicationName, E.event_id, FTG.SessionLoginName ORDER BY first_time |
Alors bon traçage à tous !