4

我们有一个 SQL Server 2008 Enterprise 数据库,它有两种不同的模式,一种是我们维护的锁定模式,另一种是开放的模式,我们允许外部开发团队根据自己的需要添加和修改。通常这对我们来说没问题,但一个特定的团队喜欢把它搞砸,它会影响其他所有人。所以2个问题:

  1. In hindsight I wish we had set up something robust from the outset but we did not, just the default install. It would be nice to be able to see what has been done to the schema so far, even if its as simple as 'User XYZ changed Procedure ABC on 07/12/2012 at 9:00 AM'. Is there anything built into SQL Server and enabled by default that tracks this that we might leverage, and if so where/how?
  2. As far as a long term solution goes, what would you recommend for this? I've been reading up on DDL triggers a bit and that seems like a promising option. If you've used this approach can you share a bit with how it worked and what you could do with it?

thank you

4

4 回答 4

4

我有一个系统使用 DDL 触发器来处理这类事情。它足以满足我的需求。它最初是在 Sql Server 2005 上开发的,现在在 Sql Server 2008R2 系统上运行。它类似于 Aaron Bertrand 评论中的链接所描述的。

创建一个与此类似的表。

CREATE TABLE [dbo].[SchemaLog](
    [SchemaLogID] [int] IDENTITY(1,1) NOT NULL,
    [PostTimeUtc] [datetime] NOT NULL,
    [DatabaseUser] [nvarchar](128) NOT NULL,
    [Event] [nvarchar](128) NOT NULL,
    [Schema] [nvarchar](128) NULL,
    [Object] [nvarchar](128) NULL,
    [TSQL] [nvarchar](max) NOT NULL,
    [XmlEvent] [xml] NOT NULL,
 CONSTRAINT [PK_SchemaLog_1] PRIMARY KEY CLUSTERED 
(
    [SchemaLogID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

确保每个人都对表具有插入权限,然后创建一个类似于此的 ddl 触发器。

CREATE TRIGGER [ddlDatabaseTriggerLog] ON DATABASE  FOR DDL_DATABASE_LEVEL_EVENTS AS  
BEGIN     
    SET NOCOUNT ON;     
    DECLARE @data XML;     
    DECLARE @schema sysname;     
    DECLARE @object sysname;     
    DECLARE @eventType sysname;     
    SET @data = EVENTDATA();     
    SET @eventType = @data.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname');     
    SET @schema = @data.value('(/EVENT_INSTANCE/SchemaName)[1]', 'sysname');     
    SET @object = @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')      
    IF @object IS NOT NULL         
        PRINT '  ' + @eventType + ' - ' + @schema + '.' + @object;     
    ELSE         
        PRINT '  ' + @eventType + ' - ' + @schema;     

    IF @eventType IS NULL         
        PRINT CONVERT(nvarchar(max), @data);     

    INSERT [dbo].[SchemaLog]          (         
        [PostTimeUtc]
    ,          [DatabaseUser]
    ,          [Event]
    ,          [Schema]
    ,          [Object]
    ,          [TSQL]
    ,          [XmlEvent]         )      
    VALUES          (         
        GETUTCDATE()
    ,          CONVERT(sysname, CURRENT_USER)
    ,          @eventType
    ,          CONVERT(sysname, @schema)
    ,          CONVERT(sysname, @object)
    ,          @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)')
    ,          @data         ); 

END;

查看以按顺序选择更改

create view SchemaLogOrdered
as
SELECT top 10000 *
FROM            dbo.SchemaLog
ORDER BY  SchemaLogID DESC
于 2012-07-13T14:48:53.620 回答
1

Redgate 选项如下。

1) 开始审核架构更改的最简单方法是安装DLM Dashboard。这是一个免费工具,可使用 DDL 触发器提醒和记录所有更改,并将包含您要求的信息。

2) 正如 Andy Davies 已经提到的那样,正确的方法是开始源代码控制您的模式,就像您对应用程序代码一样。完成此操作后,您可以通过将数据库包含在持续集成和发布管理实践中来提高数据库生命周期管理的成熟度。

于 2015-08-04T09:41:13.213 回答
0

对于第二个问题,您可以考虑将触发器作为一个选项。在以下示例中,使用 SQL Server 的 EVENTDATA() 函数捕获有关触发触发器的事件的信息。SQL 脚本创建 DDL 触发器,该触发器在数据库级别捕获 CREATE、ALTER 和 DROP 事件(尽管可以在服务器级别创建触发器以捕获服务器上所有数据库的事件;应该使用 ON ALL SERVER 选项,而不是在数据库上)

CREATE TRIGGER Audit_DDL ON DATABASE
FOR CREATE_TABLE , ALTER_TABLE , DROP_TABLE
AS
DECLARE
@event xml;
SET @event = EVENTDATA(
                  );
INSERT INTO Audit_DDL_Events
VALUES( REPLACE( CONVERT( varchar( 50
                             ) , @event.query( 'data(/EVENT_INSTANCE/PostTime)'
                                             )
                    ) , 'T' , ' '
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/LoginName)'
                                    )
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/UserName)'
                                    )
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/DatabaseName)'
                                    )
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/SchemaName)'
                                    )
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/ObjectName)'
                                    )
           ) , 
    CONVERT( varchar( 150
                    ) , @event.query( 'data(/EVENT_INSTANCE/ObjectType)'
                                    )
           ) , 
    CONVERT( varchar( max
                    ) , @event.query( 'data(/EVENT_INSTANCE/TSQLCommand/CommandText)'
                                    )
           )
  );

还必须为来自 EVENTDATA XML 的审计数据创建一个适当的存储表:

CREATE TABLE Audit_DDL_Events( DDL_Event_Time datetime , 
                           DDL_Login_Name varchar( 150
                                                 ) , 
                           DDL_User_Name varchar( 150
                                                ) , 
                           DDL_Database_Name varchar( 150
                                                    ) , 
                           DDL_Schema_Name varchar( 150
                                                  ) , 
                           DDL_Object_Name varchar( 150
                                                  ) , 
                           DDL_Object_Type varchar( 150
                                                  ) , 
                           DDL_Command varchar( max
                                              )
                         );
于 2014-02-24T18:31:59.307 回答
0

您可以考虑将您的数据库置于源代码控制之下。也许让每个外部团队都采用您数据库的一个分支或分支。这使您可以通过提交审核更改,并能够选择要合并的更改和/或在合并之前查看/编辑这些更改。

查看http://www.red-gate.com/products/sql-development/sql-source-control/了解一种可用的产品。

结合 Github 或 Bitbucket 等解决方案,通过 Internet 更直接地向外部贡献者开放源代码控制存储库。

于 2012-07-13T13:22:18.213 回答