|
--reminder, this runs on the central monitorING box, and uses xp_cmdshell and the like to connect to the "new" box. |
|
|
|
|
|
/* |
|
Event Notification - add server to monitoring. Probably simpler to do by hand, but I like this. |
|
|
|
See http://thebakingdba.blogspot.com/ for more information, look for Event Notifications |
|
|
|
Given a parameter of servername, WHEN RUN ON THE EN "repository", it will |
|
a) try to determine the servername for the "sender" |
|
b) get the service_broker_guid from that server for MSDB |
|
c) get the service_broker_guid from the local host |
|
d) create a return route on the repository for that host |
|
e) on the far side, build the endpoint, route, and event notification, and send a test record |
|
f) verify we are receiving that message |
|
|
|
|
|
Please read Version Info for potential issues. |
|
|
|
|
|
2012/08/28 mdb - version 1.0 |
|
2012/11/15 mdb - 1.1, deals with machines that already have service broker by using the existing TCP endpoint; more comments |
|
2013/01/22 mdb - 1.11 fix for 1.1; only SB machines would have worked. |
|
2013/02/12 mdb - 1.2 adding "test" vs "real" flag to actually deploy, or just tell you what to do; adding authentication perms |
|
Permissions code from Arshad Ali @ http://www.databasejournal.com/features/mssql/understanding-sql-server-service-broker-authentication.html |
|
Service code name from Namwar Rizvi http://sqltips.wordpress.com/2007/08/06/retrieve-sql-server-service-account-name-from-registry-through-tsql/ |
|
Please note BOTH MACHINES MUST BE IN THE SAME DOMAIN or there must be trust between the domains, otherwise you can't send messages. |
|
Also assumes that the service account IS A DOMAIN ACCOUNT. |
|
2013/02/27 mdb - 1.21 more perms work; if not the same account, then create necessary Login and Grant Connect. Assumes |
|
2013/03/20 mdb - 1.22 fixed propertyvalue code, which showed that some events weren't being added properly. |
|
2013/03/21 mdb - 1.25 lots of cleanups. Ping test from Watched Server, checking for Local Auth, etc. |
|
2013/03/26 mdb - 1.26 added "UPDATE" to fix any problems, found bug with version info. Fixed. |
|
2014/04/01 mdb - 1.27 added code to deal with AO & fix bug; these days there can be more than one tcp endpoint. |
|
2014/07/01 mdb - 1.28 adding code |
|
2014/09/11 mdb - 1.29 adding new group for SQL Server 2014. |
|
2015/03/30 mdb - 1.30 removing the new group, since it's actually already included under security, so it throws a "dupe" error. |
|
|
|
--note that because we're running XP_cmdshell to ping far side servers, connections must actually work. Trusted for delegation and kerberos and the like |
|
|
|
*/ |
|
|
|
/* |
|
Troubleshooting Service Broker Conversations |
|
http://rusanu.com/2005/12/20/troubleshooting-dialogs/ |
|
http://rusanu.com/2007/11/28/troubleshooting-dialogs-the-sequel/ (ssbdiagnose) |
|
http://blog.maskalik.com/sql-server-service-broker/troubleshooting-external-activation |
|
*/ |
|
|
|
--run this code on the server that is your EN repository |
|
use eventnotificationrec |
|
go |
|
declare @servername sysname, |
|
@distinct_servername sysname, |
|
@hostname sysname, |
|
@sql nvarchar(2000), |
|
@cmd nvarchar(2000), |
|
@local_guid varchar(36), |
|
@new_source_GUID varchar(36), |
|
@port varchar(6), |
|
@productversion VARCHAR(20), |
|
@existing_port varchar(6), |
|
@en_repository_server varchar(20) --name of the server that will receive all the data |
|
, @deploy VARCHAR(10) |
|
, @do_permissions BIT |
|
, @repository_service_name VARCHAR(100) |
|
, @watched_server_service_name VARCHAR(100) |
|
|
|
if object_id('tempdb..#get_new_server_info') is not null |
|
DROP TABLE #get_new_server_info |
|
CREATE TABLE #get_new_server_info (id INT IDENTITY, [OUTPUT] varchar(255)) |
|
|
|
SET @en_repository_server = @@SERVERNAME--'WIN-NDTAUPQET7L' |
|
set @servername = 'newservername' --the server you're adding |
|
SET @deploy = 'update' --REAL to actually run all the commands; otherwise it just prints out statements. |
|
--UPDATE to update the rules on boxes, using the current strings. Does NOT change Endpoints, etc. |
|
--FAKE otherwise |
|
SET @do_permissions = 1 --1 to do them, 0 to skip. Only needed if service accounts between Repository & Watched Server are different. Code will grab logins for both, and compare. |
|
--default is 0 because INSTANCES DON"T CURRENTLY WORK. If no instances, 1 is fine. Will fix, but need this now. Probably use a WMI call to get all the instance names. |
|
-- either way, we check the default instance's name, because we don't want to put it on a server with local authentication |
|
-------------- |
|
--PING TEST - make sure the watched server can connect to the repository. For one-way routing issues. |
|
--REQUIRES XP_CMDSHELL be enabled on the watched server; need to add code to turn it on/off as needed |
|
-------------- |
|
SET @sql = 'xp_cmdshell ''ping ' + @en_repository_server + '''' |
|
SET @cmd = 'sqlcmd -Q "' + @sql + '" -E -d master -S ' + @servername |
|
PRINT @cmd |
|
INSERT INTO #get_new_server_info |
|
EXEC xp_cmdshell @cmd |
|
IF (SELECT SUM (CHARINDEX('(0% loss)',[OUTPUT])) FROM #get_new_server_info) >0 |
|
BEGIN |
|
PRINT 'ping test successful - can reach server' |
|
END |
|
ELSE |
|
BEGIN |
|
PRINT 'ping test failed - cannot connect! (xp_cmdshell off? login failed?) Setting @deploy to FAKE so it doesn''t run commands' |
|
IF @deploy = 'real' |
|
BEGIN |
|
SET @deploy = 'fake' |
|
END |
|
SELECT * FROM #get_new_server_info |
|
END |
|
TRUNCATE TABLE #get_new_server_info |
|
|
|
--Retrieve the Service accounts from registry. The person running the script must have Windows admin rights on the box(?) |
|
IF @deploy = 'real' --changed from checking do_permissions, since we need this to make sure it will succeed |
|
BEGIN |
|
--get local SQL service's name; needed so we know whether we're adding perms |
|
EXECUTE master.dbo.xp_instance_regread |
|
N'HKEY_LOCAL_MACHINE', |
|
N'SYSTEM\CurrentControlSet\Services\MSSQLSERVER', |
|
N'ObjectName', |
|
@repository_service_name OUTPUT, |
|
N'no_output' |
|
|
|
--get the service name for the Watched server; if different network, probably won't work. |
|
-- if same domain, make sure it's given perms. |
|
|
|
select @cmd = 'sqlcmd -Q "declare @repository_service_name varchar(100); EXECUTE master.dbo.xp_instance_regread N''HKEY_LOCAL_MACHINE'', N''SYSTEM\CurrentControlSet\Services\MSSQLSERVER'', N''ObjectName'', @repository_service_name OUTPUT, N''no_output''; select @repository_service_name" -E -S ' + @servername |
|
INSERT INTO #get_new_server_info |
|
EXEC xp_cmdshell @cmd |
|
|
|
SELECT @watched_server_service_name = output FROM #get_new_server_info |
|
WHERE OUTPUT NOT LIKE '(%' |
|
AND OUTPUT NOT LIKE '--%' |
|
AND OUTPUT IS NOT NULL |
|
AND (LTRIM(RTRIM(output))) <> '' |
|
|
|
TRUNCATE TABLE #get_new_server_info |
|
END |
|
|
|
--come up with a port for the server; use 4022 by default, 4023 if it's an instance. |
|
if charindex('\',@servername) = 0 |
|
begin |
|
select @port='4022' |
|
end |
|
else |
|
begin |
|
select @port = '4023' |
|
end --need code for more than 1 named instance on a server |
|
|
|
--we need three different names - the service name, a unique name for the route, and the hostname for tcpip |
|
select @distinct_servername = replace(@servername,'\','__'), |
|
@hostname = case charindex('\',@servername) |
|
when 0 then @servername |
|
when null then @servername |
|
else left(@servername,charindex('\',@servername)-1) |
|
end |
|
|
|
--get our Service Broker's GUID so we can add it to their route. |
|
select @local_guid = service_broker_guid from sys.databases where name = 'EventNotificationRec' |
|
|
|
--trying to get the GUID for the far-side server. 3rd row should be it, but since it's unordered we're doing it this way |
|
select @cmd = 'sqlcmd -Q "SELECT service_broker_guid FROM sys.databases WHERE name = ''msdb''" -E -S ' + @servername |
|
INSERT INTO #get_new_server_info |
|
EXEC xp_cmdshell @cmd |
|
SELECT @new_source_GUID = [output] FROM #get_new_server_info where [output] like '%-%-%-%-%' and [output] not like '%--%' |
|
|
|
--getting the productversion, so we can add/remove EN groups as needed |
|
TRUNCATE TABLE #get_new_server_info |
|
select @cmd = 'sqlcmd -Q "SELECT SERVERPROPERTY(''productversion'')" -E -S ' + @servername |
|
|
|
INSERT INTO #get_new_server_info |
|
EXEC xp_cmdshell @cmd |
|
SELECT @productversion = [OUTPUT] FROM #get_new_server_info WHERE ISNUMERIC(LEFT(output,3))= 1 |
|
|
|
--last chance to set to fake before we start adding things. |
|
IF @watched_server_service_name IN ('NT AUTHORITY\NetworkService', 'LocalSystem') |
|
BEGIN |
|
PRINT 'Warning - Watched Service is using local authentication. |
|
Unless you have granted public access, this will not work! |
|
setting @deploy = ''fake''' |
|
|
|
SET @deploy = 'fake' |
|
END |
|
|
|
--------------------------------------------------------- |
|
--Find port if TCP endpoint already exists on machine. -- |
|
-- If it does, use it (there can be only one). -- |
|
-- For machines with cross-server SB already in use. -- |
|
-- If not, use the assigned @port -- |
|
--------------------------------------------------------- |
|
select @cmd = 'sqlcmd -Q "set nocount on;SELECT port FROM master.sys.tcp_endpoints where port>0 and type_desc = ''SERVICE_BROKER''" -E -S ' + @servername |
|
TRUNCATE TABLE #get_new_server_info |
|
INSERT INTO #get_new_server_info |
|
EXEC xp_cmdshell @cmd |
|
|
|
SELECT @existing_port = LTRIM(RTRIM([OUTPUT])) FROM #get_new_server_info |
|
WHERE [OUTPUT] NOT IN ('port ','-----------') |
|
AND [OUTPUT] IS NOT NULL |
|
|
|
DROP TABLE #get_new_server_info |
|
|
|
--create route on the Repository server first. If new server already has an endpoint, use that, otherwise use the @port |
|
IF NOT EXISTS(SELECT * FROM sys.routes WHERE name = 'ENAudit_ReturnRoute_' + @distinct_servername) |
|
BEGIN |
|
select @sql = 'CREATE ROUTE [ENAudit_ReturnRoute_' + @distinct_servername + '] |
|
WITH SERVICE_NAME = ''http://schemas.microsoft.com/SQL/Notifications/EventNotificationService'', |
|
BROKER_INSTANCE = ''' + @new_source_guid + ''', |
|
ADDRESS = ''TCP://' + @hostname + ':' + COALESCE(@existing_port,@port) + ''';' |
|
|
|
PRINT @sql |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec sp_executesql @sql --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
END |
|
|
|
---------------------------------- |
|
--Setup remote "sender" endpoint-- |
|
--uses SQLCMD -- |
|
---------------------------------- |
|
--mdb 2012/01/22 adding ISNULL for @existing_port; prevented NON-service-broker DBs from getting an endpoint. Rookie mistake. |
|
--mdb 2013/02/05 still not working right with existing SB servers |
|
--IF @port <> ISNULL(@existing_port,0) |
|
IF ISNULL(@existing_port,0) = 0 --if there is no existing SB |
|
BEGIN |
|
select @sql = null, @cmd = null |
|
select @sql = 'CREATE ENDPOINT ENAudit_Endpoint STATE = STARTED ' |
|
+ 'AS TCP (LISTENER_PORT = ' + @port + ') ' |
|
+ 'FOR SERVICE_BROKER (AUTHENTICATION = WINDOWS,ENCRYPTION = SUPPORTED)' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d master -S ' + @servername |
|
|
|
PRINT @cmd |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec xp_cmdshell @cmd |
|
END |
|
|
|
-------------------------------- |
|
-- Grant login and connect to the foreign endpoint, so they can converse. |
|
-- Code assumes you're using domain accounts, not machine accounts. |
|
-- In order to avoid certificates, both must be same domain or domains must be trusted by each other. |
|
-- If your machines use the same service account, it will work without this. |
|
-- If the service names are not the same between the Watched & Repository server, |
|
-- the Repository needs connect perms to the the Watched server & endpoint, |
|
-- and the Watched service's login needs connect perms to the Repository. |
|
-- More info at http://msdn.microsoft.com/en-us/library/ms166065(v=sql.90).aspx |
|
-------------------------------- |
|
IF @do_permissions = 1 AND @repository_service_name <> @watched_server_service_name |
|
AND @repository_service_name IS NOT NULL AND @watched_server_service_name IS NOT null |
|
AND CHARINDEX('/', @repository_service_name)>0 AND CHARINDEX('/', @watched_server_service_name)>0 --make sure they are domain accounts |
|
AND @watched_server_service_name <> 'NT AUTHORITY\NetworkService' |
|
BEGIN |
|
PRINT 'updating/adding perms' |
|
select @sql = null, @cmd = null |
|
|
|
--first do the far side |
|
select @sql = 'create login [' + @repository_service_name + '] from WINDOWS;' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d master -S ' + @servername |
|
PRINT @cmd |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec xp_cmdshell @cmd |
|
END |
|
|
|
select @sql = 'grant connect on endpoint::ENAudit_Endpoint to [' + @repository_service_name + ']' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d master -S ' + @servername |
|
PRINT @cmd |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec xp_cmdshell @cmd |
|
END |
|
|
|
--Now the Repository |
|
select @sql = 'create login [' + @watched_server_service_name + '] from WINDOWS;' |
|
PRINT @sql |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec sp_executesql @sql --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
|
|
select @sql = 'grant connect on endpoint::ENAudit_Endpoint to [' + @watched_server_service_name + ']' |
|
PRINT @sql |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec sp_executesql @sql --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
END |
|
END |
|
|
|
----------------------------------- |
|
-- Set up the Route in MSDB, as -- |
|
-- it has SB enabled by default -- |
|
----------------------------------- |
|
select @sql = null, @cmd = null |
|
select @sql = 'CREATE ROUTE [ENAudit_DestinationRoute]' |
|
+' WITH SERVICE_NAME = ''ENAudit_Service'',' |
|
+' BROKER_INSTANCE = ''' + @local_guid + ''' , ' |
|
+' ADDRESS = ''TCP://' + @en_repository_server + ':4022'';' --that's the listener port on the _Repository_ box |
|
|
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d msdb -S ' + @servername |
|
PRINT @cmd |
|
IF @deploy ='REAL' |
|
BEGIN |
|
exec xp_cmdshell @cmd --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
|
|
----------------------------- |
|
-- Now create the actual Event Notification. |
|
-- Theoretically you can create this using the system tables, but it's different |
|
-- between versions of SQL and so this is easier and only has to be updated each major SQL release. |
|
----------------------------- |
|
|
|
select @sql = null, @cmd = null |
|
--if we're using UPDATE, drop the old one so we can add the new one. |
|
select @sql = 'DROP EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d msdb -S ' + @servername |
|
|
|
PRINT @cmd |
|
IF @deploy ='Update' |
|
BEGIN |
|
exec xp_cmdshell @cmd --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
|
|
select @sql = null, @cmd = null |
|
--You could just do DDL_SERVER_LEVEL_EVENTS and ALTER_SERVER_CONFIGURATION, but that includes stats. |
|
--full list of EN groups: http://msdn.microsoft.com/en-us/library/ms180824(v=sql.90).aspx |
|
--can also add a variety of traces: see http://msdn.microsoft.com/en-us/library/ms187476(v=sql.105).aspx |
|
select @sql = 'CREATE EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ' |
|
+'ON SERVER ' |
|
|
|
--If you want _everything_ (including statistics!), just use the below line. Simpler to type, but more impact. |
|
-- You could filter them via the enaudit_exclusion_list, but it's still more impact on the initiator; |
|
-- doubly so if you add the TRC events since they include stats as well. |
|
--+ 'FOR DDL_EVENTS, ALTER_SERVER_CONFIGURATION ' |
|
|
|
-- Note that sp_rename doesn't fire EN! |
|
|
|
--using the chart http://msdn.microsoft.com/en-us/library/ms180824(v=sql.90).aspx which is 2005, |
|
-- but there's a query to get them all (note it changes each edition): http://msdn.microsoft.com/en-us/library/bb510452(v=sql.105).aspx |
|
/* |
|
--for a to-be-written dynamic creation script. Current version works on 2005/2008/r2/2012. |
|
--Take this query, run it against the sender in order to get all the server-level events. |
|
-- Exclude DDL_TABLE_VIEW_EVENTS, then add all the subcomponents for DDL_TABLE_VIEW_EVENTS except STATISTICS |
|
WITH DirectReports(name, parent_type, type, level, sort, type_name) AS |
|
( |
|
SELECT CONVERT(varchar(255),type_name), parent_type, type, 1, CONVERT(varchar(255),type_name), type_name |
|
FROM sys.trigger_event_types |
|
WHERE parent_type IS NULL |
|
UNION ALL |
|
SELECT CONVERT(varchar(255), REPLICATE ('| ' , level) + e.type_name), |
|
e.parent_type, e.type, level + 1, |
|
CONVERT (varchar(255), RTRIM(sort) + '| ' + e.type_name), |
|
e.type_name |
|
FROM sys.trigger_event_types AS e |
|
INNER JOIN DirectReports AS d |
|
ON e.parent_type = d.type |
|
) |
|
SELECT parent_type, level, type, name, type_name |
|
FROM DirectReports |
|
ORDER BY sort; |
|
*/ |
|
--Server-level events, including config; SQL Server 2005 and above |
|
+'FOR DDL_SERVER_LEVEL_EVENTS,' |
|
|
|
--DDL_TABLE_VIEW_EVENTS, minus Statistics which are constantly updated and constantly created, even on temp objects created by 3rd party tools |
|
+'DDL_TABLE_EVENTS,DDL_VIEW_EVENTS,DDL_INDEX_EVENTS,' |
|
|
|
--and the rest of the DDL_DATABASE_LEVEL_EVENTS |
|
+'DDL_SYNONYM_EVENTS,DDL_FUNCTION_EVENTS,DDL_PROCEDURE_EVENTS,' |
|
+'DDL_TRIGGER_EVENTS,DDL_EVENT_NOTIFICATION_EVENTS,DDL_ASSEMBLY_EVENTS,' |
|
+'DDL_TYPE_EVENTS,DDL_DATABASE_SECURITY_EVENTS,DDL_SSB_EVENTS,' |
|
+'DDL_XML_SCHEMA_COLLECTION_EVENTS,DDL_PARTITION_EVENTS' |
|
|
|
--and the events added in SQL Server 2008 |
|
IF @productversion NOT LIKE '9.%' |
|
SET @sql = @sql + |
|
+',DDL_PLAN_GUIDE_EVENTS,DDL_DEFAULT_EVENTS,DDL_EXTENDED_PROPERTY_EVENTS' |
|
+',DDL_FULLTEXT_CATALOG_EVENTS,DDL_FULLTEXT_STOPLIST_EVENTS' |
|
+',DDL_RULE_EVENTS,RENAME' |
|
--dupes because they are sub-events of ddl_server_level_events |
|
--+',ALTER_INSTANCE,DDL_DATABASE_EVENTS' |
|
--+',DDL_ENDPOINT_EVENTS,DDL_EVENT_SESSION_EVENTS,DDL_EXTENDED_PROCEDURE_EVENTS' |
|
--+',DDL_LINKED_SERVER_EVENTS,DDL_MESSAGE_EVENTS,DDL_REMOTE_SERVER_EVENTS' |
|
--+',DDL_RESOURCE_GOVERNOR_EVENTS,DDL_SERVER_SECURITY_EVENTS' |
|
|
|
--and the 1 event added in SQL Server 2008 R2; using NOT LIKE to auto-include future versions |
|
IF @productversion NOT LIKE '9.%' AND @productversion NOT LIKE '10.0%' |
|
SET @sql = @sql + ',ALTER_SERVER_CONFIGURATION' |
|
|
|
--and the events added in SQL Server 2012; using NOT LIKE to auto-include future versions |
|
IF @productversion NOT LIKE '9.%' AND @productversion NOT LIKE '10%' |
|
SET @sql = @sql + ',DDL_SEARCH_PROPERTY_LIST_EVENTS,DDL_SEQUENCE_EVENTS' |
|
|
|
--and now 2014! Only one this time, DDL_DATABASE_AUDIT_EVENTS (oh, the irony); using NOT LIKE to auto-include future versions |
|
--not needed - database audit events fall under the security group, which is already added. |
|
--IF @productversion NOT LIKE '9.%' AND @productversion NOT LIKE '10%' AND @productversion NOT LIKE '11%' |
|
--SET @sql = @sql + ',DDL_DATABASE_AUDIT_EVENTS ' |
|
|
|
|
|
--trace events - TRC_OBJECTS is just alter/create/drop, added since they have HOSTNAME |
|
SET @sql = @sql |
|
+ ',TRC_OBJECTS, ERRORLOG' --EVENTLOG ,TRC_DEPRECATION,.... Deprecation at your own risk. Be CAREFUL. |
|
+' TO SERVICE ''ENAudit_Service'', ''' + @local_guid + ''';' --central dbid for EventNotification_Receiver |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -d msdb -S ' + @servername |
|
|
|
PRINT @cmd |
|
IF @deploy IN ('REAL','UPDATE') |
|
BEGIN |
|
exec xp_cmdshell @cmd --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
|
|
WAITFOR DELAY '00:00:05' |
|
|
|
--------------------------------- |
|
--create and drop test objects -- |
|
-- and ensure it's working. -- |
|
--------------------------------- |
|
|
|
select @sql = 'create table tempdb.dbo.test_for_audit (field_a int)' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -S ' + @servername |
|
PRINT @cmd |
|
IF @deploy IN ('REAL','UPDATE') |
|
BEGIN |
|
exec xp_cmdshell @cmd --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
|
|
select @sql = 'drop table tempdb.dbo.test_for_audit' |
|
select @cmd = 'sqlcmd -Q "' + @sql + '" -E -S ' + @servername |
|
IF @deploy IN ('REAL','UPDATE') |
|
BEGIN |
|
exec xp_cmdshell @cmd --this one runs locally, so we use sp_executesql; WORKS and has been done |
|
END |
|
ELSE |
|
BEGIN |
|
PRINT @cmd |
|
END |
|
|
|
IF @deploy IN ('REAL','UPDATE') |
|
BEGIN |
|
WAITFOR DELAY '00:00:10' |
|
select top 100 * from ENAudit_Events WHERE PostTime > GETDATE()-.01 AND ServerName = @servername |
|
END |
|
|
|
|
|
/* |
|
|
|
--sqlcmd -Q "CREATE EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER FOR DDL_SERVER_LEVEL_EVENTS,DDL_TABLE_EVENTS,DDL_VIEW_EVENTS,DDL_INDEX_EVENTS,DDL_SYNONYM_EVENTS,DDL_FUNCTION_EVENTS,DDL_PROCEDURE_EVENTS,DDL_TRIGGER_EVENTS,DDL_EVENT_NOTIFICATION_EVENTS,DDL_ASSEMBLY_EVENTS,DDL_TYPE_EVENTS,DDL_DATABASE_SECURITY_EVENTS,DDL_SSB_EVENTS,DDL_XML_SCHEMA_COLLECTION_EVENTS,DDL_PARTITION_EVENTS,TRC_OBJECTS, ERRORLOG TO SERVICE 'ENAudit_Service', '5E885B6D-D24D-4FEB-8E64-0F8D1DE16905';" -E -d msdb -S myservera |
|
--sqlcmd -Q "CREATE EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER FOR DDL_SERVER_LEVEL_EVENTS,DDL_TABLE_EVENTS,DDL_VIEW_EVENTS,DDL_INDEX_EVENTS,DDL_SYNONYM_EVENTS,DDL_FUNCTION_EVENTS,DDL_PROCEDURE_EVENTS,DDL_TRIGGER_EVENTS,DDL_EVENT_NOTIFICATION_EVENTS,DDL_ASSEMBLY_EVENTS,DDL_TYPE_EVENTS,DDL_DATABASE_SECURITY_EVENTS,DDL_SSB_EVENTS,DDL_XML_SCHEMA_COLLECTION_EVENTS,DDL_PARTITION_EVENTS,TRC_OBJECTS, ERRORLOG TO SERVICE 'ENAudit_Service', '5E885B6D-D24D-4FEB-8E64-0F8D1DE16905';" -E -d msdb -S myserverb |
|
|
|
THEY MATCH. So we can issue the same command and sync the events of each server. |
|
|
|
sqlcmd -Q "drop EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER" -E -d msdb -S myserverb |
|
sqlcmd -Q "CREATE EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER FOR DDL_SERVER_LEVEL_EVENTS,DDL_TABLE_EVENTS,DDL_VIEW_EVENTS,DDL_INDEX_EVENTS,DDL_SYNONYM_EVENTS,DDL_FUNCTION_EVENTS,DDL_PROCEDURE_EVENTS,DDL_TRIGGER_EVENTS,DDL_EVENT_NOTIFICATION_EVENTS,DDL_ASSEMBLY_EVENTS,DDL_TYPE_EVENTS,DDL_DATABASE_SECURITY_EVENTS,DDL_SSB_EVENTS,DDL_XML_SCHEMA_COLLECTION_EVENTS,DDL_PARTITION_EVENTS,TRC_OBJECTS, ERRORLOG TO SERVICE 'ENAudit_Service', '5E885B6D-D24D-4FEB-8E64-0F8D1DE16905';" -E -d msdb -S myserverb |
|
|
|
|
|
|
|
|
|
backup database model to disk ='nul' --testing errorlog |
|
|
|
sqlcmd -Q "SELECT service_broker_guid FROM sys.databases WHERE name = 'msdb'" -E -S VM2 |
|
8B85664B-24AB-4B5A-ABAA-0AE5301D4E2D |
|
CREATE ROUTE [ENAudit_ReturnRoute_VM2] |
|
WITH SERVICE_NAME = 'http://schemas.microsoft.com/SQL/Notifications/EventNotificationService', |
|
BROKER_INSTANCE = '8B85664B-24AB-4B5A-ABAA-0AE5301D4E2D', |
|
ADDRESS = 'TCP://VM2:4022'; |
|
|
|
sqlcmd -Q "CREATE ENDPOINT ENAudit_Endpoint STATE = STARTED AS TCP (LISTENER_PORT = 4022) FOR SERVICE_BROKER (AUTHENTICATION = WINDOWS,ENCRYPTION = SUPPORTED)" -E -d master -S VM2 |
|
sqlcmd -Q "CREATE ROUTE [ENAudit_DestinationRoute] WITH SERVICE_NAME = 'ENAudit_Service', BROKER_INSTANCE = '9CF39735-7E60-490F-92B6-26EBFEC19F5E' , ADDRESS = 'TCP://WIN-NDTAUPQET7L:4022';" -E -d msdb -S VM2 |
|
sqlcmd -Q "CREATE EVENT NOTIFICATION [ENAudit_ServerDDLEvents] ON SERVER FOR DDL_SERVER_LEVEL_EVENTS,DDL_TABLE_EVENTS,DDL_VIEW_EVENTS,DDL_INDEX_EVENTS,DDL_SYNONYM_EVENTS,DDL_FUNCTION_EVENTS,DDL_PROCEDURE_EVENTS,DDL_TRIGGER_EVENTS,DDL_EVENT_NOTIFICATION_EVENTS,DDL_ASSEMBLY_EVENTS,DDL_TYPE_EVENTS,DDL_DATABASE_SECURITY_EVENTS,DDL_SSB_EVENTS,DDL_XML_SCHEMA_COLLECTION_EVENTS,DDL_PARTITION_EVENTS,TRC_OBJECTS TO SERVICE 'ENAudit_Service', '9CF39735-7E60-490F-92B6-26EBFEC19F5E';" -E -d msdb -S VM2 |
|
|
|
|
|
-------------demo cleanup------------ |
|
--on vm2: |
|
use master |
|
go |
|
drop event notification [ENAudit_ServerDDLEvents] ON SERVER |
|
go |
|
use msdb |
|
go |
|
drop route [ENAudit_DestinationRoute] |
|
go |
|
drop endpoint ENAudit_Endpoint |
|
|
|
----------------------------------- |
|
------ON LOCAL |
|
use EventNotificationRec |
|
drop route [ENAudit_ReturnRoute_VM2] |
|
*/ |
|
|