SQL Server事件通知有什么用呢?若是你想监控SQL Server的DDL操做,你能够经过DDL触发器(参考:SQL Server DDL触发器运用),也能够经过SQL Server 事件通知把这个事件相关的信息发送到 Service Broker 服务;他们最大的区别就是DDL触发器能够进行ROLLBACK,而事件通知不行;还有,事件通知是异步发送消息的;html
SQL Server 事件通知还能够响应部分SQL跟踪事件,即SQL Trace (参考:SQL Server 默认跟踪(Default Trace)、SQL Server 建立跟踪);他们最大的区别就是跟踪事件能够自定义生成哪些数据列,而事件通知是生成固定的XML;还有,每次从新启动服务器时,都必须从新启动跟踪。sql
事件通知将有关事件的信息发送给 Service Broker 服务。执行事件通知可对各类 Transact-SQL 数据定义语言 (DDL) 语句和 SQL跟踪事件作出响应,并将这些事件的相关信息发送到 Service Broker 服务。数据库
事件通知能够用来执行如下操做:编程
能够将事件通知用做替代 DDL 触发器和 SQL 跟踪的编程方法,由于你能够经过读取Service Broker 服务中的队列,在程序中对信息进行处理。安全
事件信息做为 xml 类型的变量传递给 Service Broker 服务,它提供了有关事件的发生时间、受影响的数据库对象、涉及的 Transact-SQL 批处理语句的信息以及其余信息。服务器
下图是我对事件通知逻辑关系的理解,当数据库A或者实例B产生DDL就会激发事件通知,这个通知把相应的DDL的XML信息发送给队列,你能够经过SQL获取到队列中的XML;异步
(Figure1:事件通知逻辑关系图)async
建立事件通知的event_type参数 能够为 Transact-SQL DDL 事件类型、SQL 跟踪事件类型或 Service Broker 事件类型有关限定 Transact-SQL DDL 事件类型的列表,请参阅 DDL事件。 Service Broker 事件类型为 QUEUE_ACTIVATION 和 BROKER_QUEUE_DISABLED。 有关详细信息,请参阅事件通知。性能
数据库的DDL操做默认会被记录到Default Trace默认跟踪中(参考:SQL Server 默认跟踪(Default Trace)),这是一个被动式的监控;而主动式的监控就可使用DDL触发器(参考:SQL Server DDL触发器运用);咱们还可使用事件通知的形式监控DDL,下面就着重讲讲实现过程。测试
下面建立一个SSB_DB数据库,捕获数据库实例的DDL语句;
--Step1:建立示例数据库 USE master GO IF EXISTS(SELECT name FROM sys.databases WHERE name = 'SSB_DB') DROP DATABASE SSB_DB GO CREATE DATABASE SSB_DB GO USE SSB_DB GO --Step2:建立队列,默认为开启 CREATE QUEUE NotifyQueue_DDL --WITH STATUS=ON GO --Step3:建立服务 CREATE SERVICE NotifyService_DDL ON QUEUE NotifyQueue_DDL ([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]); GO --Step4:对系统目录视图sys.databases进行查询 SELECT service_broker_guid FROM sys.databases WHERE name = 'SSB_DB' /* DB19CBE8-0581-4604-B44A-812C29A565BB */ --Step5:建立事件通知,使用上面返回的GUID值 CREATE EVENT NOTIFICATION NotifyEvent_DDL ON DATABASE FOR DDL_DATABASE_LEVEL_EVENTS TO SERVICE 'NotifyService_DDL', 'DB19CBE8-0581-4604-B44A-812C29A565BB'; --Step6:测试 CREATE TABLE TestTable (a int) GO DROP TABLE TestTable; GO --Step7:使用Select或Recieve(其中Recieve会删除队列中的事件消息)查询队列 SELECT CAST(message_body as xml) EventInfo FROM dbo.NotifyQueue_DDL
上面的SQL脚本,你须要注意如下几点:
1. 建立的EVENT NOTIFICATION是针对当前数据库的(ON DATABASE),只有在当前数据库发生的DDL才会被捕获;
2. 使用DDL_DATABASE_LEVEL_EVENTS将会监控当前数据库全部DDL事件,你可使用DDL_SERVER_LEVEL_EVENTS监控数据库实例的DDL操做,更多的DDL事件能够参考:DDL 事件组;
3. 关于service_broker_guid,你应该经过查询确认这个值,它的做用是指定解析 broker_service 所依据的 Service Broker 实例。
执行Step7返回下图的结果,这是执行Step6脚本产生的两条DDL消息:
(Figure3:DDL事件在队列中的XML信息)
经过下面的SQL脚本能够对Figure4所示的XML进行解释,保存到表中:
执行Step10将返回Figu
--Step8:建立表 CREATE TABLE [dbo].[EventInfo]( [EventInfoID] [int] IDENTITY(1,1) NOT NULL, [PostTime] [datetime] NOT NULL, [ServerName] [sysname] NOT NULL, [LoginName] [sysname] NOT NULL, [DatabaseUser] [sysname] NOT NULL, [DatabaseName] [sysname] NOT NULL, [Schema] [sysname] NULL, [Object] [sysname] NULL, [TSQL] [nvarchar](max) NOT NULL, [Event] [sysname] NOT NULL, [XmlEvent] [xml] NOT NULL, CONSTRAINT [PK_EventInfo_EventInfoID] PRIMARY KEY NONCLUSTERED ( [EventInfoID] ASC ) ON [PRIMARY] ) ON [PRIMARY] --Step9:建立分离XML的存储过程 -- ============================================= -- Author: <听风吹雨> -- Create date: <2013.06.19> -- Description: <分离XML> -- Blog: <http://www.cnblogs.com/gaizai/> -- ============================================= CREATE PROCEDURE sp_SeparateXML AS BEGIN SET NOCOUNT ON; DECLARE @data XML DECLARE @itemCur CURSOR SET @itemCur = CURSOR FOR SELECT CAST(message_body as xml) EventInfo FROM [SSB_DB].[dbo].NotifyQueue_DDL OPEN @itemCur FETCH NEXT FROM @itemCur INTO @data WHILE @@FETCH_STATUS=0 BEGIN --逻辑处理 INSERT [SSB_DB].[dbo].[EventInfo]( [PostTime], [ServerName], [LoginName], [DatabaseUser], [DatabaseName], [Schema], [Object], [TSQL], [Event], [XmlEvent]) VALUES( @data.value(