我的任务是在新数据库创建时建立警报。
我们有一个中央服务器,可以连接到我们所有的SQL服务器,并通过链接服务器捕获不同的指标。
我需要以某种方式捕获每个服务器上的所有数据库的列表,并将该列表存储在我的中央服务器上。然后每天运行几次SQL代理作业,将远程服务器上的当前数据库列表与中央服务器上的数据库列表进行比较。如果已在远程服务器上添加数据库或已删除数据库,请发送电子邮件。
我只是很难把各个部分放在一起,并且正在寻找任何有用的信息。如果一个方法更可行,我也会对另一种方法持开放态度。
此致 GB
答案 0 :(得分:2)
你真的需要维护db的列表吗?如果没有,只需使用服务器范围的DDL触发器在创建或删除数据库时生成电子邮件。
CREATE TRIGGER trgCreateDatabase
ON ALL SERVER
FOR CREATE_DATABASE
AS
DECLARE @Subj NVARCHAR(255)
DECLARE @MailBody NVARCHAR(MAX)
SET @Subj = @@SERVERNAME + ' - Database Created'
SELECT @MailBody =
'TSql Command: ' + EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)') + CHAR(13) + CHAR(10) +
'Login Name: ' + EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]','nvarchar(max)')
EXEC msdb..sp_send_dbmail
@from_address = 'From@Someone.com',
@recipients = 'To@Someeone.com',
@Subject = @Subj,
@body = @MailBody
GO
CREATE TRIGGER trgDropDatabase
ON ALL SERVER
FOR DROP_DATABASE
AS
DECLARE @Subj NVARCHAR(255)
DECLARE @MailBody NVARCHAR(MAX)
SET @Subj = @@SERVERNAME + ' - Database Dropped'
SELECT @MailBody =
'TSql Command: ' + EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)') + CHAR(13) + CHAR(10) +
'Login Name: ' + EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]','nvarchar(max)')
EXEC msdb..sp_send_dbmail
@from_address = 'From@Someone.com',
@recipients = 'To@Someeone.com',
@Subject = @Subj,
@body = @MailBody
GO
答案 1 :(得分:1)
我曾经有一个维护数据库,它使用RegisteredDatabases表跟踪数据库。然后,SQL代理作业将按计划运行,并检查sys.databases是否从我的维护数据库知道的内容中移除。存储过程将引发错误,导致SQL代理作业通过警报系统发送电子邮件,或者只是从列表中删除数据库(通常仅在手动运行sproc时使用)。
以下代码用于我的专业项目。你需要从中取出你想要的碎片。
CREATE PROCEDURE [Configuration].[usp_RefreshRegisteredDatabases]
@Purge BIT = 0
AS
SET NOCOUNT ON;
--Vars
DECLARE @PurgeDBList udt_DatabaseList
--Populate new databases, if there are any
INSERT INTO [Configuration].[RegisteredDatabases] (DatabaseName)
SELECT [Sdb].[name]
FROM [sys].[databases] Sdb
LEFT OUTER JOIN [Configuration].[RegisteredDatabases] Rdb ON [Sdb].name = Rdb.DatabaseName
WHERE Rdb.DatabaseName IS NULL
--Throw error if database(s) no longer exist but the @Purge flag is set to 0.
IF EXISTS ( SELECT [Rdb].[DatabaseName]
FROM [sys].[databases] Sdb
RIGHT OUTER JOIN [Configuration].[RegisteredDatabases] Rdb ON [Sdb].name = Rdb.DatabaseName
WHERE Sdb.name IS NULL)
AND @Purge = 0
BEGIN
RAISERROR('Registered database(s) no longer exists. If any configurations are pointing to this database they will fail. Query Configuration.vwOrphanedDatabases for more details.',16,1)
END
--Remove databases from the list where they don't exist anymore
IF EXISTS ( SELECT [Rdb].[DatabaseName]
FROM [sys].[databases] Sdb
RIGHT OUTER JOIN [Configuration].[RegisteredDatabases] Rdb ON [Sdb].name = Rdb.DatabaseName
WHERE Sdb.name IS NULL )
AND @Purge = 1
BEGIN
INSERT INTO @PurgeDBList (RegisteredDatabaseID, DatabaseName)
SELECT Rdb.DatabaseID, [Rdb].[DatabaseName]
FROM [sys].[databases] Sdb
RIGHT OUTER JOIN [Configuration].[RegisteredDatabases] Rdb ON [Sdb].name = Rdb.DatabaseName
WHERE Sdb.name IS NULL
EXEC [Configuration].[usp_PurgeAllReferencesToDatabase] @DatabaseList = @PurgeDBList
END
答案 2 :(得分:0)
我假设您已经拥有服务器列表。循环查询sys.databases的服务器列表。使用动态SQL生成链接服务器查询。
答案 3 :(得分:0)
您可以使用SSIS。 SSIS包可以发送到服务器执行以下SQL -
USE master;
SELECT @@ServerName, NAME FROM sysdatabases;
并对具有数据库列表的中央服务器进行查找,并标记数据库中不存在的数据库并插入它们。
答案 4 :(得分:0)
我可能会使用PowerShell版本。
import-module sqlps
DIR SQLSERVER:\SQL\localhost\DEFAULT\Databases | select Name
更改每个服务器的localhost,将列表转储到内存中并加载到SQL中以获取永久记录。您还可以快速比较主列表。
或者,因为您已经在使用链接服务器,所以查询
select @@servername, name from linkedserver.master.sys.databases
与主列表进行比较。