通过SQL Server默认跟踪追踪数据库DDL操作的执行者
在日常运维中,常会遇到因数据库对象被创建、修改或删除而导致应用异常的情况。当问题解决后,往往需要回答"谁执行了该操作?"这一关键问题。
虽然 SQL Server 2005 起支持 DDL 触发器可记录此类事件,但若未提前配置,则无法回溯历史操作。此时,许多管理员会转向第三方日志分析工具读取事务日志(transaction log),却忽略了内置的默认跟踪功能。
实际上,SQL Server 自带一个轻量级后台跟踪机制——默认跟踪(Default Trace),它持续记录关键数据库活动,包括对象创建、删除、修改等行为,无需额外配置即可使用。尽管它不能完全替代 DDL 触发器,但在排查故障时是极为有效的辅助手段。
默认跟踪仅捕获部分重要事件:审计类、数据库级、错误信息、全文索引操作以及对象相关的增删改操作。本文聚焦于对象级别的变更事件,以定位具体操作人员。
首先检查默认跟踪是否启用:
SELECT * FROM sys.configurations WHERE configuration_id = 1568;
若返回值为 0,说明功能未开启。可通过以下命令启用(需具备相应权限):
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'default trace enabled', 1;
GO
RECONFIGURE;
GO
接下来获取当前默认跟踪文件路径:
SELECT * FROM ::fn_trace_getinfo(0);
该查询将返回多个信息项,其中 value 字段包含跟踪文件的实际路径,如 C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG\log.trc。
现在我们模拟一次完整的操作流程。先创建一个测试数据库:
USE master;
GO
CREATE DATABASE TraceDB;
随后查询默认跟踪文件中与该数据库创建相关的记录,通过限定条件缩小范围:
SELECT
loginname,
loginsid,
spid,
hostname,
applicationname,
servername,
databasename,
objectname,
e.category_id,
cat.name AS [CategoryName],
textdata,
starttime,
eventclass,
eventsubclass, -- 0: 开始, 1: 提交
e.name AS EventName
FROM ::fn_trace_gettable('C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG\log.trc', 0)
INNER JOIN sys.trace_events e ON eventclass = trace_event_id
INNER JOIN sys.trace_categories cat ON e.category_id = cat.category_id
WHERE databasename = 'TraceDB'
AND objectname IS NULL
AND e.category_id = 5
AND e.trace_event_id = 46; -- 46: 对象创建
注意:结果中可能包含多个条目,因为事件子类(eventsubclass)分别为 0(开始)和 1(提交),表示事务的起止。
接下来,在新数据库中创建一张表:
USE TraceDB;
GO
CREATE TABLE dbo.MyTable (
id INT IDENTITY(1,1) NOT NULL,
sometext CHAR(3) NULL
) ON [PRIMARY];
再次查询跟踪文件,筛选出该表创建事件:
WHERE databasename = 'TraceDB'
AND objectname = 'MyTable'
AND e.category_id = 5
AND e.trace_event_id = 46;
接着尝试修改表结构:
ALTER TABLE MyTable ADD col INT;
此时应使用 trace_event_id = 164 来捕获对象修改事件:
WHERE databasename = 'TraceDB'
AND objectname = 'MyTable'
AND e.category_id = 5
AND e.trace_event_id = 164;
最后,删除该表:
DROP TABLE MyTable;
对应地,使用 trace_event_id = 47 查询删除事件:
WHERE databasename = 'TraceDB'
AND objectname = 'MyTable'
AND e.category_id = 5
AND e.trace_event_id = 47;
通过以上方式,可以清晰还原每次数据库对象变更的操作时间、执行用户、客户端程序及原始语句,从而有效追溯责任归属。