如何防止停止或关闭其它用户的SQL Trace

停止或关闭 SQL Trace ,一般是通过存储过程

sp_trace_setstatus [ @traceid = ] trace_id , [ @status = ] status

来实现的。


该储存过程需要两个参数,

第一个是trace_id

第二个是状态码,其中取值含义如下表

状态码 含义
0 停止指定的Trace
1 开启指定的Trace
2 关闭并从服务器删除指定的Trace

 

从上面的分析可以看出,停止或关闭的Trace是由trace_id唯一指定的。trace_id在整个sql server实例中肯定是唯一的,所以通过仅仅指定trace_id就可以停止或关闭唯一的一个Trace。但是sql server会重用trace_id,这样导致一些难以预见的问题。

正常情况:

  1. 程序A创建某个Trace,sql server返回trace_id为2
  2. 程序A保存该trace_id以便后续操作
  3. 程序A开启该Trace
  4. 运行一段时间之后,程序A通过提供trace_id将该Trace停止并关闭

异常情况:

  1. 程序A创建某个Trace,sql server返回trace_id为2
  2. 程序A保存该trace_id以便后续操作
  3. 程序A开启该Trace
  4. 该Trace运行一段时间之后,意外崩溃,sql server回收trace_id(2)
  5. 程序B开启某个Trace,trace_id为2
  6. 程序A运行一段时间之后,程序A通过提供trace_id(2)将Trace停止并关闭

明显在第5步中程序A误停止并关闭了程序B开启的Trace。

为了解决这种误操作问题,我们需要在执行停止或关闭操作之前额外检查Trace的其它属性已确定它确实是自己开启的Trace。

但是不幸的是,sql server并没有提供多少SQL Trace属性(sys.fn_trace_getinfo (Transact-SQL))给我们去确定某个Trace。

不过我们仍然可以通过 sys.traces 该目录视图获取一些有用的信息, 在这里我们选取 start_time 作为一个额外的校验属性。

因此,我们的程序逻辑变更为

  1. 程序A创建某个Trace,sql server返回trace_id为2
  2. 程序A保存该trace_id以便后续操作
  3. 程序A开启该Trace
  4. 程序A通过提供trace_id从目录视图 sys.traces (
    select start_time from sys.traces where id=2

    )中获取并保存该Trace的start_time

  5. 运行一段时间之后,程序A再次从目录视图sys.traces获取trace_id为2的start_time,并将其与之前保存的start_time对比,如果相等则通过提供trace_id将该Trace停止并关闭,否则不进行任何停止或关闭操作

除了停止和关闭操作之外,其它仅仅通过提供trace_id的操作也可能产生误操作,这些情况下,我们必须寻找其它的一些可校验的其他属性来唯一确定一个trace就是自己想要操作的Trace。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>