如何检测对数据库的任何更改(DDL和DML)


13

我的客户端的SQL服务器上有很多数据库。这些数据库正在开发中,因此开发人员可以设计,重构,进行数据修改等。有些数据库很少更改。我的客户必须确保所有人(备份)的安全,并花一些时间来管理环境。(该公司没有数据库管理员的职位。)经过长时间的讨论,由于易于还原,客户决定使用每日完全备份策略。

因此,这是情况的摘要:

  • 数据库的数量每天都会变化。
  • 更改的数据库(意味着数据和/或结构已更改)应备份。
  • 未更改的数据库不得备份。
  • 解决方案不得影响数据库结构(这不是限制性要求)
  • 该“备份引擎”将自动工作。

主要问题:如何检测数据库已更改。问题的第一部分(DDL更改)可以通过使用DDL触发器来解决。但是数据更改(DML更改)是一个问题。无法将DML触发器应用于所有数据库的所有表以跟踪更改(性能,扩展对象的管理...)。备份引擎必须跟踪所有更改,以将每个数据库标记为准备备份。

  • 更改数据捕获是一种解决方案,但似乎过于繁琐(它也需要SQL Server Enterprise Edition)。

  • 另一种方法是跟踪数据库文件的更改(大小或上次更改时间),但无法正常工作:当数据库超出所有保留的可用空间并且sp_spaceused不是解决方案时,数据库可以更改其大小。

  • 跟踪是一种解决方案,但它会导致性能问题并需要其他管理。

是否有解决方案可以计算实际的数据库使用量,而又不影响其他数据库管理对象(如统计数据……)?可以肯定的是,对表数据的更改不会改变表的大小不会触发(我认为),但这总比没有好。确实,我在寻找SQL Server 2008的直接或间接解决方案。

感谢您的任何评论,解决方案和想法。

添加:

这是解决方案(感谢Marian):

Select
    NextLSN = MAX(fn.[Current LSN])
    ,Databasename = DB_NAME()
 from fn_dblog(NULL,    NULL) fn
     LEFT JOIN sys.allocation_units au
         ON fn.AllocUnitId = au.allocation_unit_id
     LEFT  JOIN sys.partitions p
         ON p.partition_id = au.container_id
     LEFT  JOIN sys.objects so
         ON so.object_id = p.object_id  
    WHERE 
    (
        (Operation IN 
       ('LOP_INSERT_ROWS','LOP_MODIFY_ROW',
            'LOP_DELETE_ROWS','LOP_BEGIN_XACT','LOP_COMMIT_XACT') 
            AND so.is_ms_shipped = 0)
        OR 
        ([Lock Information] like '%ACQUIRE_LOCK_SCH_M OBJECT%')
    )

那么您是否将此作为工作的一部分实施?我很想有一种每天输出(例如,凌晨2点)从前24小时到目录的所有更改的方法,因此我可以为自己准备一些更改日志。
jcolebrand

@jcolebrand是的,我做到了。就我而言,我必须检查任何数据库活动,然后进行备份(完全或差异)。我正在检查LSN(日志记录的主键),该函数fn_dblog返回。就这些。我认为这不会对您有帮助。我尚未研究fn_dblog可以返回的数据的所有功能,但我认为它不会返回与之相关的所有信息。如您所见,还有许多其他系统表加入其中。如果容易的话,我们将有很多普通的,便宜的工具:)
garik 2011年

Answers:


7

一种想法是每天制作快照,并使用文件监视器来监视磁盘上快照文件的大小。仅当在其中添加了数据时,快照才会增加其大小,因此,如果您找到监视实际大小(报告大小)的工具,那将是一个有效的主意。

现在..我没有使用它,所以不能给您技术见解:-)。

另一个想法是验证每个数据库的事务日志(当然,如果您在数据库上使用完全恢复模式),并使用我在论坛上看到的某些功能(db_fnlog ..或其他内容)来读取日志中的操作,并查看是否有任何删除/插入/更新。

这些都不是一件容易的事。.但我希望您会发现它们有用。

PS:找到了具有日志读取功能的文章(顺便说一句是fndblog :-):阅读Jens K. Suessmeyer的事务日志


1
我不是在谈论db文件的大小,而是在谈论快照本地文件,该文件是通过以下方式创建的:创建数据库xxxdb作为yyydb的快照。在此处查看有关快照的详细信息:msdn.microsoft.com/en-us/library/ms175158.aspx
玛丽安

1
  • 对于DDL更改,您可以阅读 Default Trace
  • 对于DML修改,因为您发现CDC太重了,您可以运行自己的轻量级服务器端跟踪,该跟踪仅跟踪相关事件

1

对于DDL更改,您可以使用DDL触发器,但是您可以尝试使用3种不同的选项进行DML更改

1)变更跟踪2)CDC(变更数据捕获)3)审核功能

对于变更跟踪,您可以看到以下链接http://www.mssqltips.com/sqlservertip/1819/using-change-tracking-in-sql-server-2008/

此更改跟踪将仅用于表是否已更改...但是很难找到已更改的数据..如果要查找已更改的数据,则可以进行Chnage数据捕获。

对于sqlserver中的Aduit,您可以检查以下链接 http://blogs.msdn.com/b/manisblog/archive/2008/07/21/sql-server-2008-auditing.aspx


1
+1,但CDC随企业版一起提供
garik 2011年

1

对于DML更改,可以利用以下任何本机SQL Server审核功能:

  • SQL Server更改跟踪
  • SQL Server更改数据捕获
  • SQL Server审核

每种方法都有其优点和缺点,但是“审核”是Microsoft最新推出的,因此,最好将其与当前和将来的解决方案一起构建。

请注意,只有审核功能才提供有关谁/何时/如何的信息


0

您可以使用跟踪文件检测任何ddl更改。下面是获取更改的脚本。

SELECT 
    te.name AS eventtype
    ,t.loginname
    ,t.spid
    ,t.starttime
    ,t.objectname
    ,t.databasename
    ,t.hostname
    ,t.ntusername
    ,t.ntdomainname
    ,t.clientprocessid
    ,t.applicationname  
FROM sys.fn_trace_gettable
(
    CONVERT
    (VARCHAR(150)
    ,(
        SELECT TOP 1 
            value
        FROM sys.fn_trace_getinfo(NULL)  
        WHERE property = 2
    )),DEFAULT
) T 
INNER JOIN sys.trace_events as te 
    ON t.eventclass = te.trace_event_id 
WHERE eventclass=164

您可以使用此脚本检测对表和存储过程的任何修改:

SELECT 
    SO.Name
    ,SS.name 
    ,SO.type_desc 
    ,SO.create_date
    ,SO.modify_date 
 FROM sys.objects AS SO
INNER JOIN sys.schemas AS SS 
    ON SS.schema_id = SO.schema_id 
WHERE DATEDIFF(D,modify_date, GETDATE()) < 50
AND TYPE IN ('P','U')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.