您好,欢迎访问一九零五行业门户网

事件通知(EventNotification)实践

事件通知(event notification )实践 问题描述 作为dba,我们常常需要在sql server实例或数据库级别上跟踪正在发生的事件。有没有方法跟踪这些修改而不会太影响sql server性能呢? 解决方案 sql server 2005及其以后版本提供了事件通知(event notification
事件通知(event notification)实践 
问题描述
作为dba,我们常常需要在sql server实例或数据库级别上跟踪正在发生的事件。有没有方法跟踪这些修改而不会太影响sql server性能呢?
解决方案
sql server 2005及其以后版本提供了事件通知(event notification)机制,来跟踪发生在数据库或实例级别上的事件或修改。这其实也可以通过ddl触发器或这sql跟踪来实现,但是事件通知有异步相应事件和运行在事务范围之外的优点,因此能作为数据库应用程序的一部分,捕获预定义的事件,而无需占用分配给事务的资源。
事件通知是一个使用ddl触发器或sql跟踪的可编程的替代方案,执行相应不同的ddl语句、sql跟踪、service broker事件(像queue_activation或broker_queue_disabled),然后以xml格式发送信息到sql server service broker服务。换句话说,当创建一个通知,sql server跟踪预定义的事件,并将发生的事件写入到ssb服务,然后异步地从ssb队列接收信息。
步骤一:
首先检查service broker是否在数据库级别被启用,如果没有,启用它。然后创建一个ssb队列,ssb服务将会用这个队列去存储消息到服务。该服务使用内置的契约(契约定义了一个能发送到ssb服务的消息类型),http://schemas.microsoft.com/sql/notifications/posteventnotification,专用于事件通知(event notification)。注意:你需要排他访问数据去执行修改数据库命令。
--check if the database is enabled for service broker--if not then enable itif exists (select * from sys.databases where name = 'adventureworks2012'and is_broker_enabled = 0)alter database adventureworks2012 set enable_broker;gouse adventureworks2012go--create a queue which will hold the tracked informationcreate queue dbo.eventnotificationqueuego--check if the queue is created or notselect * from sys.service_queueswhere name = 'eventnotificationqueue'go--create a service on which tracked information will be sentcreate service [//adventureworks2012/eventnotificationservice]on queue dbo.eventnotificationqueue([http://schemas.microsoft.com/sql/notifications/posteventnotification])go--check if the service is created or notselect * from sys.serviceswhere name = '//adventureworks2012/eventnotificationservice'go
步骤二:
创建两个数据库级别的通知。首先,当有一个创建表命令执行时,将发出通知;然后,当有一个修改表命令执行时,将发出通知。也可以创建一个通知事件组;例如,你可以创建一个单一的通知ddl_table_events去跟踪像创建、修改、删除表的所有事件。
--create a notification to track create table commandcreate event notification notifycreatetableeventson databasefor create_tableto service '//adventureworks2012/eventnotificationservice' , 'current database'go--create a notification to track alter table commandcreate event notification notifyaltertableeventson databasefor alter_tableto service '//adventureworks2012/eventnotificationservice' , 'current database'go--check if both the above notifications created or notselect * from sys.event_notificationswhere name in ('notifycreatetableevents','notifyaltertableevents')go
步骤三:
创建一个服务器级别的通知,当一个错误在sql server实例级别触发时,该通知即被触发。可以查看sys.server_event_notifications目录视图查看通知是否存在于该服务器上。
--create a notification to error occuring at server levelcreate event notification notifyerroreventson server with fan_infor errorlogto service '//adventureworks2012/eventnotificationservice', 'current database'go--check if the above notification was created or notselect * from sys.server_event_notificationswhere name in ('notifyerrorevents')go
步骤四:
验证刚才建立的事件通知是否在正常工作。在这个脚本里,先创建一个表,然后修改它,它将会被数据库级别的事件通知捕获到,并且我使用了raiserror(with log从句需要被服务器级别事件通知捕获)在sql server里触发一个错误,该错误将会被上一个服务器级别的事件通知捕获到。
--generate a create table eventcreate table abc(col1 int,col2 int)go--generate an alter table eventalter table abcadd col3 intgo--generate a server level eventraiserror (n'generating error for event notification testing...', 16, 1)with loggo--review if the events were tracked in queueselect cast(message_body as xml) as message_in_xmlfrom dbo.eventnotificationqueuego
步骤五:
事件通知以xml格式发送捕获到的信息到ssb服务;可以查询队列去看到捕获的信息,但是你需要用receive命令从队列接收消息,如下所示,处理它们并从队列中移除。使用receive命令你可以设置在一次接受的记录的数量。在这个脚本中,我使用top (1)命令接受第一行队列中的消息,并显示它的内容。事件通知以xml格式发送消息(注意:我们使用创建服务的内置契约,它定义了只有xml数据能被写入到服务),因此我转换消息体到xml数据类型。因为我使用了top (1)从句在receive命令,因为队列中有3条记录,我运行了下面的命令3次。查询的结果如下图。也可以使用一个循环的结构去从队列读取所有的记录,而不用运行这个脚本多次。
declare @targetdialoghandle uniqueidentifier;declare @eventmessage xml;declare @eventmessagetypename sysname;waitfor( receive top(1)@targetdialoghandle = conversation_handle,@eventmessage = convert(xml, message_body),@eventmessagetypename = message_type_namefrom dbo.eventnotificationqueue), timeout 1000;select @targetdialoghandle as dialoghandle, @eventmessagetypename as messagetypename,@eventmessage.value('(/event_instance/eventtype)[1]', 'varchar(128)' ) as eventtype,@eventmessage.value('(/event_instance/servername)[1]', 'varchar(128)' ) as servername,@eventmessage.value('(/event_instance/databasename)[1]', 'varchar(128)' ) as databasename,@eventmessage.value('(/event_instance/loginname)[1]', 'varchar(128)' ) as loginname,@eventmessage.value('(/event_instance/tsqlcommand/commandtext)[1]','nvarchar(max)') as tsqlcommand,@eventmessage.value('(/event_instance/textdata)[1]', 'varchar(128)' ) as textdata,@eventmessage.value('(/event_instance/severity)[1]', 'varchar(128)' ) as severity,@eventmessage.value('(/event_instance/error)[1]', 'varchar(128)' ) as errornumber
650) this.width=650; title=clip_image001 style=max-width:90% alt=clip_image001 src=http://www.68idc.cn/help/uploads/allimg/151111/121a34r9-0.jpg border=0 style=max-width:90% />
650) this.width=650; title=clip_image002 style=max-width:90% alt=clip_image002 src=http://www.68idc.cn/help/uploads/allimg/151111/121a341r-1.jpg border=0 style=max-width:90% />
650) this.width=650; title=clip_image003 style=max-width:90% alt=clip_image003 src=http://www.68idc.cn/help/uploads/allimg/151111/121a31948-2.jpg border=0 style=max-width:90% />
步骤六:
下面的代码可以清理并删除所有的对象,以创建的相反顺序。
drop event notification notifycreatetableevents on databasegodrop event notification notifyaltertableevents on databasegodrop event notification notifyerrorevents on servergodrop table abcgodrop service [//adventureworks2012/eventnotificationservice]godrop queue dbo.eventnotificationqueuego
权限需求:
1. 为了创建一个数据库级别的事件通知,需要在该数据库有create database ddl event notification权限。为了删除它,你必需是该事件通知的拥有者,或者在该数据库有alter any database event notification权限。
2. 为了创建服务器级别的通知,你需要有create ddl event notification权限。为了删除它,你必需是该事件通知的拥有者,或者在该服务器有alter any event notification权限。
3. 为了创建事件通知捕获sql跟踪,你需要在该服务器有create trace event notification权限。为了删除它,你必需是该事件通知的拥有者,或者有alter any event notification权限。
4. 为了创建队列范围的事件通知,你需要有该队列的alter权限。为了删除它,你必需是该事件通知的拥有者,或者有该队列的alter权限。
备注:
1. 你可以查询sys.event_notification_event_types获取所有可以创建事件通知的事件的列表,也可以查看ddl事件,ddl事件组,sql跟踪事件,sql跟踪事件组。
2. 去查看事件通知和触发器之间的不同,可以访问这里;事件通知和sql跟踪的不同,可以访问这里。
3. 你不能直接修改一个通知,你需要删除并重建它。
其它类似信息

推荐信息