在VS环境中,我一直使用数据库项目来实现更新脚本。我倾向于为脚本使用诸如“ DatabaseUpdate17.sql”或“ PriceUpdateFebruary2010.sql”之类的难以想象的名称。将它们作为数据库项目使我可以将它们与Team Server任务,错误(如果我们进行了代码审查,也与它们)联系在一起。我还在每个数据库(我拥有权限)中都包含一个专门用于收集模式更改的表。
CREATE TABLE [dbo].[AuditDDL](
[EventID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[EventData] [xml] NULL, -- what did they do
[EventUser] varchar(100) NOT NULL, -- who did it
[EventTime] [datetime] DEFAULT (getdate()) -- when did they do it
)
GO
好吧,这照顾了6 Ws中的3 Ws。
CREATE TRIGGER [trgAuditDDL]
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
INSERT INTO AuditDDL(EventData, EventUser)
SELECT EVENTDATA(), original_login()
GO
我包括一个插入语句,用于记录补丁程序的开始和结束。补丁程序之外发生的事件值得我们关注。
例如,“补丁17”的“开始补丁”插入看起来像:
INSERT INTO [dbo].[AuditDDL]
([EventData]
,[EventUser])
VALUES
('<EVENT_INSTANCE><EventType>BEGIN PATCH 17</EventType></EVENT_INSTANCE>'
,ORIGINAL_LOGIN())
GO
由于它也可以在重建索引时捕获,因此您需要每个月左右运行以下操作来清除这些事件:
DELETE FROM AuditDDL
WHERE [EventData].exist('/EVENT_INSTANCE/EventType/text()[fn:contains(.,"ALTER_INDEX")]') =1
GO
DELETE FROM AuditDDL
WHERE [EventData].exist('/EVENT_INSTANCE/EventType/text()[fn:contains(.,"UPDATE_STATISTICS")]') =1
GO
先前发布在Server Fault上的早期版本。
在符合SOX和PCI-DSS的环境中,您将永远无法访问生产服务器。因此,脚本需要事先清除并执行。更新脚本顶部的注释包括新表,存储的proc,函数等的列表以及已修改表,存储的proc,函数等的列表。如果数据被修改,请说明正在修改的内容以及原因。
第二个问题是,如果两个单独的任务更改同一数据库对象,则有时最终需要手动协调更改。这可能只是事实,但似乎仍然应该有一些自动方式来“标记”这些问题或其他内容。
我从来没有遇到过可以自动跟踪的工具。以前的雇主使用“数据库所有者”的原则-只有一个人亲自负责数据库。这个人不是唯一使用该数据库的开发人员,而是所有更改都必须经过他们。这样可以很好地防止更改相互冲突和破坏。