외래 키를 삭제하는 데 시간이 오래 걸리는 이유는 무엇입니까?


13

한 번에 하나씩 다음과 같이 데이터베이스에서 모든 외래 키를 삭제하는 스크립트를 만들었습니다.

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

놀랍게도 스크립트가 오랜 시간이 걸린다는 것입니다. 각 DROP FK 당 평균 20 초입니다. 이제 서버가 가서 FK 제약 조건이 처음부터 침해되지 않고 떨어지고 있는지 확인해야하기 때문에 FK를 만드는 것이 큰 문제 일 수 있음을 알고 있습니다. 너무 오래 걸리는 FK를 제거 할 때 서버는 무엇을합니까? 이것은 저의 호기심과 일을 더 빨리 만드는 방법이 있는지 이해하는 것입니다. FK를 제거 할 수 있으면 (단지 사용 안함) 마이그레이션 중에 훨씬 빨라져 다운 타임을 최소화 할 수 있습니다.


1
다른 프로세스가 데이터베이스에 공유 스키마 잠금을 설정하여 drop FK 프로세스가 해당 프로세스가 완료 될 때까지 기다리도록 할 수 있습니까? 드롭 FK를 실행 한 다음 즉시 sp_who2를 차단하십시오.
Daniel Hutmacher

이 데이터베이스에서 실행중인 다른 프로세스는 없습니다. 그러나 동일한 서버에 다른 데이터베이스가 있습니다.
carlo.borreo

답변:


12

제약 조건을 삭제하려면 다른 사람이 수정하는 동안 테이블을 쿼리하지 못하도록 차단하는 Sch-M (스키마 수정) 잠금이 필요합니다. 해당 잠금을 얻기 위해 대기 중일 수 있으며 해당 테이블에 대해 현재 실행중인 모든 쿼리가 완료 될 때까지 기다려야합니다.
실행중인 쿼리는 테이블에 Sch-S (스키마 안정성) 잠금이 있으며 해당 잠금은 Sch-M 잠금과 호환되지 않습니다.

에서 잠금 모드, 스키마 잠금

데이터베이스 엔진은 열 추가 또는 테이블 삭제와 같은 테이블 데이터 정의 언어 (DDL) 작업 중에 스키마 수정 (Sch-M) 잠금을 사용합니다. 유지되는 동안 Sch-M 잠금은 테이블에 대한 동시 액세스를 방지합니다. 이는 Sch-M 잠금이 잠금이 해제 될 때까지 모든 외부 작업을 차단 함을 의미합니다.

테이블 잘림과 같은 일부 DML (데이터 조작 언어) 작업은 Sch-M 잠금을 사용하여 동시 작업으로 영향을받는 테이블에 액세스하지 못하게합니다.

데이터베이스 엔진은 쿼리를 컴파일하고 실행할 때 스키마 안정성 (Sch-S) 잠금을 사용합니다. Sch-S 잠금은 배타적 (X) 잠금을 포함하여 모든 트랜잭션 잠금을 차단하지 않습니다. 따라서 테이블에 X 잠금이있는 트랜잭션을 포함한 다른 트랜잭션은 쿼리가 컴파일되는 동안 계속 실행됩니다. 그러나 동시 DDL 작업 및 Sch-M 잠금을 획득하는 동시 DML 작업은 테이블에서 수행 할 수 없습니다.


때로는 SSMS에서 테이블을 강조 표시해도 Sch-S잠금이 발생하고 이것이 OP 문제의 근본 원인이라고 생각합니다.
John Eisbrener

5

예제를 통해 설명하겠습니다. 왜 오랜 시간이 걸 렸는지 알 수 있습니다. 이 테스트를 위해 빈 데이터베이스를 만듭니다.

CREATE DATABASE [TestFK]
GO

2 개의 테이블 만들기

 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

Person 테이블에 외래 키 제약 조건 만들기

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

두 테이블에 일부 데이터를 삽입하십시오.

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

새 쿼리 창을 열고이를 실행하십시오 (쿼리가 완료되면 창을 닫지 마십시오).

   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

다른 쿼리 창을 열고 이것을 실행하십시오.

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

드롭 제약 조건이 계속 실행되는 동안 (대기 중) 이제 쿼리가 더 오래 실행되는 이유와 대기중인 잠금을 확인하기 위해 쿼리를 실행합니다.

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

삽입 작업을 커밋하면 이제 drop 문이 필요한 잠금을 획득 할 수 있으므로 드롭 제약 조건이 즉시 완료됩니다.

귀하의 경우 필요한 잠금 / 잠금을 획득하기 위해 드롭 제한을 방지하는 호환 가능한 잠금을 보유하는 세션이 없는지 확인해야합니다.


다른 사람은 데이터베이스를 사용하지 않았지만 다른 한편으로는이 데이터베이스에 열린 창이 있다는 것을 배제 할 수 없습니다. 다른 실험을하겠습니다.
carlo.borreo

1
drop 문이 완료되기를 기다리는 경우 다른 창에서이 쿼리를 실행하십시오. 그것은 당신에게 당신이 기다리고있는 것을 줄 것입니다. 에서 쿼리를 가져 오기 여기 . 예제에서 제공 한 것보다 자세한 내용이 있습니다.
SqlWorldWide
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.