如何跟踪数据库依赖关系?


37

随着内部应用程序数年的发展,您偶尔会发现许多表,人们认为这些表不再相关并且想要删除。在SQL环境中以及可能在SSIS之类的东西中,有什么实用的方法来识别数据库依赖关系?

我曾经在一些相当残酷的地方工作过,例如:

  • 首先删除,然后问问题(如果它试图提取不再存在的表,可能会杀死数据仓库构建)
  • 首先删除权限,然后等待错误报告(如果故障处理不当,可能会导致静默错误)

我很欣赏SQL Server附带的工具来跟踪该实例中的依赖关系,但是如果您在不同实例上有数据库,这些工具似乎会遇到麻烦。是否有使查询依存关系更容易的选项,也许回答诸如“此列在哪里使用”之类的问题?诸如“在此存储过程中的该另一台服务器上已结束”或“此SSIS程序包中已结束”的答案?

Answers:


14

没有简单的方法可以做到这一点。触发器不起作用,就像您从表中选择一样,不会触发任何触发器。我发现最好的方法是让开发人员跟踪他们使用的内容。当要删除某些内容时,请与所有开发团队进行检查,并在每个人退出后重新命名该对象。然后一个月都没有破裂,可以放下物体。


7
  1. 搜索代码以用于sy​​s.sql_modules.definition:是否已引用?然后...
  2. 检查权限:哪些客户端代码可以调用它?然后...
  3. 探查器

从而:

  • 对于没有引用和权限的表,将不使用该表。
  • 在没有引用和某些权限的情况下,运行探查器以查看用法
  • 没有权限和引用,添加使用情况的日志记录

我之前做过的事情是使该表成为掩盖该表的视图,然后使该视图执行不良:(交叉连接本身,不同)。您实际上并没有将其删除,但确实会导致客户端超时或投诉...


6

我过去使用的一种快速方法(它实际上取决于表的大小,索引性能的数量等)是添加触发器,该触发器在对表执行操作时记录时间戳。正如我已经说过的那样,这可能会导致性能问题,因此需要谨慎对待-还要注意您的日志记录表不使用标识字段,因为这会弄乱一些使用@@ IDENTITY的旧代码。当然,这可能只是表明应用程序中的某个功能一段时间未使用。

当所有可能影响数据库的代码不在数据库中时(即随机客户端查询数据库),很难跟踪依赖关系。

编辑:为了解决表不能具有SELECT触发器的问题,这是假定表具有索引(仅在2008年测试)的另一个选项。

SELECT          
    last_user_seek,
    last_user_scan,
    last_user_lookup,
    last_user_update
FROM
    sys.dm_db_index_usage_stats AS usage_stats
INNER JOIN
sys.tables AS tables ON tables.object_id = usage_stats.object_id
WHERE
    database_id = DB_ID() AND
    tables.name = 'mytable' 

但是请注意,在服务器重新启动,分离等情况下,会清除使用情况统计信息表。因此,您需要设置一个作业来收集数据。我知道一点技巧。


4

我过去使用的一种方法是建立要删除的表的候选列表,然后重命名它们并查找故障。

我如何建立清单的方法是:

  1. 查看当前存储过程,触发器和函数中未使用的表

  2. 空表(零记录);

  3. 未引用的表(没有任何关系的表);

  4. 查看自数据库服务器启动以来未使用哪些表(DMV)

在文本文件中建立列表之后,我制作了一个批处理脚本,该脚本将从本地映射的版本控制文件夹中解析我们的.cs文件(我们只有.net项目),并查看这些表是否在.cs文件中使用(不应该发生,但是嘿。。。。如果不是,那么很明显,如果是,那么我们将建立一个列表,并给开发人员检查该模块是否仍在使用中。

简而言之,以前的家伙是对的,没有灵丹妙药。


3

我在公司实施的策略是将所有与SQL Server接触的内容置于源代码管理的中央位置。

  • asp.net项目
  • SSRS项目
  • SSIS项目
  • 我什至将所有数据库对象脚本化为各种存储库。

我还没有设置它,但是最终我想实现某种索引/中央搜索机制,可以用来搜索特定的表,存储过程等。我们实际上是一个新的SQL Server Shop-从FoxPro转换。因此,旧的SQL对象不是什么大问题,但是我正在为未来做计划。

我在重命名/跟踪方法中看到的问题是某些事情仅每年运行一次,甚至每年都不运行。更不用说人们要求您写的各种特别内容,然后在几个月或几年后再询问一次。


3

有多种工具和技术可用于跟踪依赖项,包括:

我知道的工具:

  • SQL Server依赖关系查看器(但如果在创建表之前创建sp using table会出现问题)
  • Redgate SQL依赖跟踪器(通过@Eric Humphrey的答案)
  • Resharper(.net工具,可用于查看调用路径,我认为它可用于跟踪使用关键SQL调用的位置)

方法

  • 代码搜索SQL对象的使用(不过复制了上面的一些工具)
  • 查看使用情况统计信息(即:何时最后一次调用SQL对象),我使用以下SQL:

    SELECT 
        last_execution_time,   
        (SELECT TOP 1 
            SUBSTRING(s2.text,statement_start_offset / 2+1 , 
                ((CASE WHEN statement_end_offset = -1 THEN 
                    (LEN(CONVERT(nvarchar(max),s2.text)) * 2) 
                ELSE statement_end_offset END) - statement_start_offset) / 2+1)
        )  AS sql_statement,
        execution_count
    FROM sys.dm_exec_query_stats AS s1 
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS s2  
    WHERE 
        s2.text like '%[OBJECT NAME]%' 
        and last_execution_time > [DATE YOU CARE ABOUT]
    ORDER BY last_execution_time desc

注意:当服务器重新启动,分离等情况时,使用情况统计表将被清除。因此,您需要设置一个作业来收集数据。我知道一点技巧。(来自@Miles D)

技术技巧

  • 搜索上次使用情况(请参阅上面的使用情况统计信息)
  • 搜索它的使用位置(请参阅工具)
  • 查看开发人员的代码使用情况(通过@MrDenny)
  • 重命名对象(即:使用_toBeDropped发布/前缀)并注意错误
  • 更改权限,并注意错误
  • 放下物体祈祷

2

几年前,我试图构建一种工具来检查类似的东西。TL; DR的答案是我发现当时无法使用可用资源。

该列在哪里使用?

当您意识到该select *列所在的表中使用了许多查询,视图和存储过程时,此问题将变得更加复杂。然后,您需要查看使用这些结果的程序-因此,您需要一些扫描仪/索引器/解析器能够读取可能是C#,Delphi,Java,VB,ASP(经典)等的源代码,只是试图查找对该列的每个引用。然后,您需要分析那些程序,以尝试确定该代码是否被调用了。



2

这并不是您问题的真正答案,但我认为值得一提:这是数据库之外的所有系统都应通过view和sproc进行通信的原因之一。您可以在可搜索的.sql文件中找到这些脚本的生成脚本,因此可以轻松查看外部是否正在使用特定的表或列。

当然,SSIS通常通常直接连接到表,因此这可能对您现在的需求没有太大帮助。但是,当开发人员连接到您的数据库并抱怨必须等待您(或充当DBA的任何人)提出他们所需的视图和存储库时,您可以告诉他们:“任何表或列都可能被删除或重命名。 m仅负责使您了解视图和存储库的更改。” 他们只需要对这些特定更改进行回归测试。


0

TSQL以下可以使用sys.dm_sql_referencing_entities或sys.sql_expression_dependencies

其他工具,例如SQL Negotiator Pro,Redgate等,也可以使用GUI直观地生成此工具

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.