Tại sao đánh rơi chìa khóa nước ngoài mất nhiều thời gian?


13

Tôi đã tạo một kịch bản, từng cái một, xóa tất cả các khóa ngoại khỏi cơ sở dữ liệu, giống như thế này:

ALTER TABLE MyTable1 DROP CONSTRAINT FK_MyTable1_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col2

Điều làm tôi ngạc nhiên là kịch bản mất nhiều thời gian: trung bình 20 giây cho mỗi FOP DROP. Bây giờ, tôi hiểu rằng việc tạo FK có thể là một vấn đề lớn, bởi vì máy chủ phải đi và kiểm tra xem ràng buộc FK không bị vi phạm ngay từ đầu, nhưng có giảm không? Máy chủ sẽ làm gì khi thả FK mất quá nhiều thời gian? Điều này là cho cả sự tò mò của riêng tôi, và để hiểu nếu có một cách để làm cho mọi thứ nhanh hơn. Có thể loại bỏ FK (không chỉ vô hiệu hóa chúng) sẽ cho phép tôi nhanh hơn nhiều trong quá trình di chuyển, và do đó giảm thiểu thời gian chết.


1
Có thể một quy trình khác đặt các khóa lược đồ được chia sẻ trên cơ sở dữ liệu của bạn, buộc quá trình thả FK phải chờ các quá trình đó kết thúc? Hãy thử chạy thả FK và sau đó kiểm tra ngay lập tức sp_who2 để chặn.
Daniel Hutmacher

Tôi quên đề cập, không có quá trình khác chạy trên cơ sở dữ liệu này. Nhưng có trên các cơ sở dữ liệu khác trên cùng một máy chủ.
carlo.borreo

Câu trả lời:


12

Việc bỏ một ràng buộc yêu cầu khóa Sch-M (Sửa đổi lược đồ) sẽ chặn những người khác truy vấn bảng trong quá trình sửa đổi. Có lẽ bạn đang chờ để có được khóa đó và phải đợi cho đến khi tất cả các truy vấn hiện đang chạy đối với bảng đó kết thúc.
Một truy vấn đang chạy có khóa Sch-S (Ổn định Schema) trên bàn và khóa đó không tương thích với khóa Sch-M.

Từ chế độ khóa, khóa Schema

Công cụ cơ sở dữ liệu sử dụng các khóa sửa đổi lược đồ (Sch-M) trong hoạt động ngôn ngữ định nghĩa dữ liệu bảng (DDL), chẳng hạn như thêm một cột hoặc thả bảng. Trong thời gian được giữ, khóa Sch-M ngăn chặn truy cập đồng thời vào bảng. Điều này có nghĩa là khóa Sch-M chặn tất cả các hoạt động bên ngoài cho đến khi khóa được giải phóng.

Một số thao tác ngôn ngữ thao tác dữ liệu (DML), chẳng hạn như cắt bảng, sử dụng khóa Sch-M để ngăn truy cập vào các bảng bị ảnh hưởng bởi các hoạt động đồng thời.

Công cụ cơ sở dữ liệu sử dụng các khóa ổn định lược đồ (Sch-S) khi biên dịch và thực hiện các truy vấn. Khóa Sch-S không chặn bất kỳ khóa giao dịch nào, kể cả khóa độc quyền (X). Do đó, các giao dịch khác, bao gồm các giao dịch có khóa X trên bảng, tiếp tục chạy trong khi truy vấn đang được biên dịch. Tuy nhiên, các hoạt động DDL đồng thời và các hoạt động DML đồng thời có được các khóa Sch-M, không thể được thực hiện trên bảng.


Đôi khi, việc làm nổi bật bảng trong SSMS sẽ tạo ra Sch-Skhóa và tôi nghi ngờ đây là nguyên nhân cốt lõi của các vấn đề của OP.
John Eisbrener

5

Tôi sẽ hướng dẫn bạn qua một ví dụ như vậy, bạn có thể thấy lý do tại sao nó mất nhiều thời gian. Tạo một cơ sở dữ liệu trống cho bài kiểm tra này.

CREATE DATABASE [TestFK]
GO

Tạo 2 bảng.

 USE [TestFK]
 GO
CREATE TABLE dbo.[Address] (
      ADDRESSID   INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       Address1    VARCHAR(50),
      City        VARCHAR(50),
      [State]     VARCHAR(10),
      ZIP     VARCHAR(10));
GO

CREATE TABLE dbo.Person (
       PersonID    INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       LastName    VARCHAR(50) NOT NULL,
     FirstName   VARCHAR(50),
      AddressID   INT);
GO

Tạo một ràng buộc khóa ngoài trên bảng Person.

 USE [TestFK]
 GO
ALTER TABLE dbo.Person ADD CONSTRAINT FK_Person_AddressID FOREIGN KEY (AddressID)
REFERENCES dbo.Address(AddressID)
GO

Chèn một số dữ liệu vào cả hai bảng.

USE [TestFK]
GO
INSERT dbo.Address (Address1,City,[State],Zip)
  SELECT '123 Easy St','Austin','TX','78701'
    UNION
 SELECT '456 Lakeview','Sunrise Beach','TX','78643'
GO
INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith','John',1
   UNION
 SELECT 'Smith','Mary',1
   UNION
 SELECT 'Jones','Max',2
GO

Mở một cửa sổ truy vấn mới và chạy nó (không đóng cửa sổ sau khi truy vấn được hoàn thành).

   USE [TestFK]
   GO
   BEGIN TRAN
   INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith1','John1',1
    UNION
    SELECT 'Smith1','Mary1',1
    UNION
    SELECT 'Jones1','Max1',2

Mở một cửa sổ truy vấn khác và chạy này.

USE [TestFK]
GO
ALTER TABLE dbo.person DROP CONSTRAINT FK_Person_AddressID

Bạn sẽ thấy bạn thả ràng buộc sẽ tiếp tục chạy (chờ) và bây giờ chạy truy vấn để xem tại sao nó chạy lâu hơn và khóa nào nó đang chờ.

SELECT * FROM sys.dm_os_waiting_tasks 
WHERE blocking_session_id IS NOT NULL; 

Khi bạn cam kết thao tác chèn của mình, ràng buộc thả sẽ hoàn thành ngay lập tức vì bây giờ câu lệnh thả có thể có được khóa yêu cầu.

Đối với trường hợp của bạn, bạn cần đảm bảo rằng không có phiên nào đang giữ khóa tương thích, điều này sẽ ngăn chặn ràng buộc thả để có được khóa / khóa cần thiết.


Không ai khác đang sử dụng cơ sở dữ liệu, nhưng mặt khác, tôi không thể loại trừ rằng tôi có một cửa sổ mở trên cơ sở dữ liệu này. Tôi sẽ làm một thí nghiệm khác.
carlo.borreo

1
Khi câu lệnh thả của bạn đang chờ kết thúc, hãy chạy truy vấn này từ một cửa sổ khác. Điều đó sẽ cung cấp cho bạn những gì bạn đang chờ đợi. Nhận truy vấn từ đây . Nó có nhiều chi tiết hơn những gì tôi đã đưa ra trong ví dụ của mình.
SqlWorldWide
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.