Are you still running profiler or have you transferred to using Extended Events? I use Extended Events almost exclusively now because it's so much easier compared to using profiler or trace from T-SQL. Not to mentioned you can capture more things
The other day someone checked in some code and every now and then the build would fail with the error
Msg 15151, Level 16, State 19, Line 51
Cannot drop the event session 'ProcsExecutions', because it does not exist or you do not have permission.
I decided to take a look at the code and saw what the problem was. I will recreate the code here and then show you what needs to be changed. This post will not go into what Extended Events are, you can look that up in the SQL Server Extended Events documentation
Start by creating the Extended Event session by executing the following T-SQL
CREATE EVENT SESSION ProcsExecutions ON SERVER ADD EVENT sqlserver.rpc_completed( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') ), ADD EVENT sqlserver.rpc_starting( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') )
To start the Extended Event session from T-SQL, execute the following command
ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = START;
Below is what the code looked like that was checked in.
You can run it and it will execute without a problem
IF EXISTS (SELECT name FROM sys.dm_xe_sessions WHERE name = 'ProcsExecutions') DROP EVENT SESSION ProcsExecutions ON SERVER GO CREATE EVENT SESSION ProcsExecutions ON SERVER ADD EVENT sqlserver.rpc_completed( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') ), ADD EVENT sqlserver.rpc_starting( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') ) ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = START; GO
However if you run the following command now
ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = STOP;
And then execute the same create Extended Event T-SQL Query again
IF EXISTS (SELECT name FROM sys.dm_xe_sessions WHERE name = 'ProcsExecutions') DROP EVENT SESSION ProcsExecutions ON SERVER GO CREATE EVENT SESSION ProcsExecutions ON SERVER ADD EVENT sqlserver.rpc_completed( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') ), ADD EVENT sqlserver.rpc_starting( ACTION(sqlos.task_time,sqlserver.client_app_name, sqlserver.client_hostname,sqlserver.database_name,sqlserver.sql_text) WHERE ([sqlserver].[database_name]=N'Test') ) ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = START; GO
Msg 25631, Level 16, State 1, Line 29
The event session, "ProcsExecutions", already exists. Choose a unique name for the event session.
So why is that? There are 2 DMV that exist sys.dm_xe_sessions and sys.server_event_sessions. The DMV sys.dm_xe_sessions only returns a row for Extended Event sessions that are in the running state, the DMV sys.server_event_sessions will return a row even if the Extended Event session is not currently running
Lets' take a look at what that looks like by running some queries and commands
First we are going to stop the session and then query the sys.dm_xe_sessions DMV
--Stop the session if is running ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = STOP; GO -- this query returns only the running Extended Event sessions SELECT dxs.name, dxs.create_time,* FROM sys.dm_xe_sessions AS dxs;
Output
-----------------
hkenginexesession
system_health
sp_server_diagnostics session
telemetry_xevents
As you can see our Extended Event session is not returned because it is not in a running state
Now lets's query the sys.server_event_sessions DMV and check if our Extended Event session is returned
-- this query returns also Extended Event sessions that are not currently running SELECT * FROM sys.server_event_sessions
Output
-----------------
system_health
AlwaysOn_health
telemetry_xevents
ProcsExecutions
As you can see our Extended Event session is returned even though it is not in a running state
If we now start the session again and then check the sys.dm_xe_sessions DMV, we will get back out session
-- start the session again ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = START; GO SELECT dxs.name, dxs.create_time,* FROM sys.dm_xe_sessions AS dxs;
Output
-----------------
hkenginexesession
system_health
sp_server_diagnostics session
telemetry_xevents
ProcsExecutions
So now our Extended Event session is returned because it is in a running state
Instead of this query to check for the existence
IF EXISTS (SELECT name FROM sys.dm_xe_sessions WHERE name = 'ProcsExecutions') DROP EVENT SESSION ProcsExecutions ON SERVER GO
What we really want is this
IF EXISTS (SELECT name FROM sys.server_event_sessions WHERE name = 'ProcsExecutions') DROP EVENT SESSION ProcsExecutions ON SERVER GO
So basically we change the dmv from sys.dm_xe_sessions to sys.server_event_sessions in IF EXISTS check
So it is a pretty easy change, just swap out the DMV
If you want to stop a session if it is running, you can go ahead and implement something like this
IF EXISTS (SELECT name FROM sys.dm_xe_sessions WHERE name = 'ProcsExecutions') BEGIN PRINT 'The Session Was Running' ALTER EVENT SESSION ProcsExecutions ON SERVER STATE = STOP; END IF NOT EXISTS (SELECT name FROM sys.dm_xe_sessions WHERE name = 'ProcsExecutions') PRINT 'The Session is NOT Running'
That's all for this post, hopefully it will be useful to someone
No comments:
Post a Comment