2012-12-07 48 views
8

Phiên bản SQL Server - 2008 R2Nhận cơ sở dữ liệu SQL Server Cross Phụ thuộc

Tôi đang làm việc để đánh giá giải pháp DMS, với mục tiêu tiếp quản bảo trì. Giải pháp ban đầu có một cơ sở dữ liệu trung tâm, có dữ liệu liên quan đến nhà sản xuất. Nó cũng có một cơ sở dữ liệu cho mỗi đại lý, có nghĩa là có rất nhiều phụ thuộc cơ sở dữ liệu chéo.

Những vấn đề:

  • Không DB tài liệu
  • Không có mã bình luận
  • Rất nhiều đống
  • Không có đối tượng tiêu chuẩn quy ước đặt tên
  • Các trung tâm DB có 460+ bảng và 900 + SPROCS , ngoài các đối tượng khác
  • Mỗi đại lý DB có 370+ bảng và 2350+ SProcs, trong tiện ích bổ sung n đến các đối tượng khác

Bước đầu tiên, tôi đề xuất làm sạch hoàn toàn phụ thuộc vào đối tượng, bao gồm phụ thuộc cơ sở dữ liệu chéo. Tôi đã thử sử dụng giải pháp của Red Gate, nhưng đầu ra là quá lớn. Tất cả những gì tôi muốn là một danh sách các đối tượng trong cơ sở dữ liệu không có bất kỳ sự phụ thuộc nào - chúng không phụ thuộc vào các đối tượng khác, cũng như không có bất kỳ đối tượng nào phụ thuộc vào chúng.

Đây là kịch bản tôi đã sử dụng để có được một danh sách phụ thuộc:

SELECT 
DB_NAME() referencing_database_name, 
OBJECT_NAME (referencing_id) referencing_entity_name, 
ISNULL(referenced_schema_name,'dbo') referenced_schema_name, 
referenced_entity_name, 
ao.type_desc referenced_entity_type, 
ISNULL(referenced_database_name,DB_NAME()) referenced_database_name 
FROM sys.sql_expression_dependencies sed 
JOIN sys.all_objects ao 
ON sed.referenced_entity_name = ao.name 

tôi sẽ tạo ra một bảng - Dependencies - vào mà tôi sẽ được chèn kết quả này thiết lập từ mỗi DB. Bước tiếp theo, tôi cũng sẽ tạo một bảng khác - AllObjects - sẽ chứa danh sách tất cả các đối tượng trong Cơ sở dữ liệu. Đây là kịch bản để làm điều này:

SELECT 
DB_NAME() DBName, 
name, 
type_desc 
FROM sys.all_objects 
WHERE type_desc IN 
(
'VIEW', 
'SQL_TABLE_VALUED_FUNCTION', 
'SQL_STORED_PROCEDURE', 
'SQL_INLINE_TABLE_VALUED_FUNCTION', 
'USER_TABLE', 
'SQL_SCALAR_FUNCTION' 
) 

Bây giờ, một danh sách các tên từ bảng này, không xuất hiện trong cột referenced_entity_name trong bảng phụ thuộc nên đưa ra một danh sách các đối tượng mà tôi đang tìm kiếm.

SELECT 
AO.DBName, 
AO.name, 
AO.type_desc 
FROM AllObjects AO 
LEFT OUTER JOIN Dependencies D ON 
D.referenced_database_name = AO.DBName AND 
D.referenced_entity_name = AO.name AND 
D.referenced_entity_type = AO.type_desc 
WHERE 
D.referenced_database_name IS NULL AND 
D.referenced_entity_name IS NULL AND 
D.referenced_entity_type IS NULL 

Bây giờ các câu hỏi:

  1. Một số đối tượng phụ thuộc dường như mất tích trong đầu ra. Tôi thiếu là gì?
  2. Làm cách nào để xác thực rằng phát hiện của tôi là chính xác?
  3. Ý tôi là có cách khác để thực hiện việc này, vì vậy tôi có thể so sánh kết quả và kiểm tra kỹ?

Cảm ơn trước,

Raj

+0

Bạn cũng quan tâm đến các đối tượng SYSTEM? –

+0

Nhưng loại = 'U' sẽ chỉ cung cấp cho người dùng bảng, phải không? Tôi cũng cần xem xét các đối tượng được tạo khác. – Raj

+0

Rất tiếc, "và is_ms_shipped = 0" có thể phù hợp hơn cho truy vấn thứ 2. Điều này sẽ loại trừ các đối tượng cụ thể của hệ thống. –

Trả lời

3

Oh, MS đã rất nỗ lực giỏi phát hiện phụ thuộc chéo cơ sở dữ liệu với sys.sql_expression_dependencies, nhưng tôi đã nhìn thấy nó bỏ lỡ những thứ trước đây. Trong trường hợp của bạn, tôi muốn tìm một ví dụ về một sự thiếu phụ thuộc, và bắt đầu backtracking: bạn đã bỏ nó từ truy vấn của bạn một số làm thế nào? Nếu có, hãy sửa truy vấn của bạn. Liệu sys.sql_expression_dependencies bỏ qua một lớp phụ thuộc nào đó? Dưới những điều kiện nào? Là SQL động để đổ lỗi? v.v.

Bạn cũng nên chạy sp_refreshsqlmodule cho từng đối tượng trong sys.sql_modules và sau đó chạy lại mã của bạn. Nó buộc SQL Server phải làm mới thông tin phụ thuộc (với khả năng tốt nhất của nó).

Bây giờ, để xác thực, thiết lập dấu vết và lắng nghe sự kiện 114, "Sự kiện truy cập đối tượng lược đồ kiểm tra", cộng với sự kiện bắt đầu và hoàn thành cho thủ tục lưu trữ và/hoặc cuộc gọi RPC. Bao gồm các cột DatabaseName, ParentName, ObjectName, ServerName, SPIDRequestID (đối với các kết nối được bật MARS). Có lẽ một số người khác nữa. "Sự kiện truy cập đối tượng lược đồ kiểm tra" xảy ra bất cứ khi nào một đối tượng được truy cập, vì vậy hãy thực hiện ứng dụng trong khi theo dõi này đang chạy, sau đó đối chiếu dữ liệu bằng SPID + RequestId và so sánh nó với kết quả của bạn bằng cách sử dụng sys.sql_expression_dependencies. Nếu bất cứ điều gì là trong dữ liệu theo dõi không xuất hiện trong dữ liệu phụ thuộc của bạn, sau đó bạn đã bỏ lỡ một cái gì đó.

7

Bạn có thể so sánh kết quả của mình với kết quả mà tập lệnh sau tìm thấy. Đây là toàn bộ article

CREATE PROCEDURE [dbo].[get_crossdatabase_dependencies] AS 

SET NOCOUNT ON; 

CREATE TABLE #databases(
    database_id int, 
    database_name sysname 
); 

INSERT INTO #databases(database_id, database_name) 
SELECT database_id, [name] 
FROM sys.databases 
WHERE 1 = 1 
    AND [state] <> 6 /* ignore offline DBs */ 
    AND database_id > 4; /* ignore system DBs */ 

DECLARE 
    @database_id int, 
    @database_name sysname, 
    @sql varchar(max); 

CREATE TABLE #dependencies(
    referencing_database varchar(max), 
    referencing_schema varchar(max), 
    referencing_object_name varchar(max), 
    referenced_server varchar(max), 
    referenced_database varchar(max), 
    referenced_schema varchar(max), 
    referenced_object_name varchar(max) 
); 

WHILE (SELECT COUNT(*) FROM #databases) > 0 BEGIN 
    SELECT TOP 1 @database_id = database_id, 
       @database_name = database_name 
    FROM #databases; 

    SET @sql = 'INSERT INTO #dependencies select 
     DB_NAME(' + convert(varchar,@database_id) + '), 
     OBJECT_SCHEMA_NAME(referencing_id,' 
      + convert(varchar,@database_id) +'), 
     OBJECT_NAME(referencing_id,' + convert(varchar,@database_id) + '), 
     referenced_server_name, 
     ISNULL(referenced_database_name, db_name(' 
      + convert(varchar,@database_id) + ')), 
     referenced_schema_name, 
     referenced_entity_name 
    FROM ' + quotename(@database_name) + '.sys.sql_expression_dependencies'; 

    EXEC(@sql); 

    DELETE FROM #databases WHERE database_id = @database_id; 
END; 

SET NOCOUNT OFF; 

SELECT * FROM #dependencies; 
+1

Xin lưu ý rằng nếu cơ sở dữ liệu ngoại tuyến, nó sẽ vẫn cố gắng truy cập và do đó sẽ bị lỗi –

+0

Điểm tốt, tôi vừa thêm một dòng vào bộ lọc 'WHERE' để bỏ qua cơ sở dữ liệu OFFLINE^_ ^ – Oreo

Các vấn đề liên quan