SQL Server 2008에서 테이블을 변경하는 동안 (열 제거) 변경 스크립트 생성 단추를 클릭하고 생성 된 변경 스크립트가 열을 삭제하고 “go”라고 말한 다음 설정하는 것처럼 보이는 추가 ALTER TABLE 문을 실행하는 것을 알았습니다. 테이블의 잠금 에스컬레이션을 “TABLE”로 예:
ALTER TABLE dbo.Contract SET (LOCK_ESCALATION = TABLE)
또한 이것이 변경 스크립트가 마지막으로 수행하는 것입니다. 여기서 무엇을하고 있으며 왜 LOCK_ESCALATION을 TABLE로 설정합니까?
답변
” 잠금 에스컬레이션 “은 SQL이 대규모 업데이트에 대한 잠금을 처리하는 방법입니다. SQL이 많은 행을 변경하려는 경우 데이터베이스 엔진이 여러 작은 항목 (예 : 행 잠금)을 잠그는 대신 더 적은 수의 더 큰 잠금 (예 : 전체 테이블)을 취하는 것이 더 효율적입니다.
그러나 전체 테이블을 잠그면 다른 쿼리가 오랫동안 잠길 수 있으므로 테이블이 크면 문제가 될 수 있습니다. 즉, 많은 작은 단위 잠금이 더 적은 (또는 하나의) 세분화 된 잠금보다 느리고 테이블의 다른 부분을 잠그는 여러 쿼리가 있으면 한 프로세스가 다른 프로세스에서 대기중인 경우 교착 상태가 발생할 가능성이 있습니다.
LOCK_ESCALATION
잠금 에스컬레이션을 제어 할 수있는 SQL 2008의 새로운 테이블 레벨 옵션 이 있습니다. 기본값 인 “TABLE”을 사용하면 잠금이 테이블 수준까지 에스컬레이션 될 수 있습니다. DISABLE은 대부분의 경우 전체 테이블에 대한 잠금 에스컬레이션을 방지합니다. AUTO는 테이블이 파티션 된 경우를 제외하고 테이블 잠금을 허용하며,이 경우 잠금은 파티션 레벨까지만 이루어집니다. 자세한 내용은 이 블로그 게시물 을 참조하십시오.
SQL 2008에서는 TABLE이 기본값이므로 IDE가 테이블을 다시 만들 때이 설정을 추가 할 것으로 생각됩니다. SQL 2005에서는 LOCK_ESCALATION이 지원되지 않으므로 스크립트를 실행하려고 할 경우이를 제거해야합니다. 2005 년 사례. 또한 TABLE이 기본값이므로 스크립트를 다시 실행할 때 해당 줄을 안전하게 제거 할 수 있습니다.
또한이 설정이 적용되기 전에 SQL 2005에서 모든 잠금이 테이블 수준으로 에스컬레이션 될 수 있습니다. 즉, “TABLE”이 SQL 2005의 유일한 설정입니다.
답변
스크립트의 주요 부분을 실행하기 전후에이 값을 비교하여 스크립트에 LOCK_ESCALATION 문을 포함해야하는지 확인할 수 있습니다.
SELECT lock_escalation_desc FROM sys.tables WHERE name='yourtablename'
필자의 경우 테이블을 변경하여 제약 조건을 삭제하거나 추가 해도이 값이 수정되지 않는 것 같습니다.
답변
저스틴 그랜트 (Justin Grant)의 답변 LOCK_ESCALATION
은 일반적으로 설정이 수행하는 작업에 대해 설명 하지만 중요한 세부 사항이 누락되었으며 SSMS가 설정하는 코드를 생성하는 이유를 설명하지 않습니다. 특히 LOCK_ESCALATION
스크립트에서 마지막 명령문으로 설정되어 있다는 것은 매우 이상하게 보입니다 .
나는 몇 가지 테스트를했고 여기에서 무슨 일이 일어나고 있는지에 대한 나의 이해가 있습니다.
짧은 버전
ALTER TABLE
추가 문은 열이 암시 적으로 스키마가와는 아무 상관이없는 테이블에 (SCH-M) 잠금 수정합니다 떨어지거나 변경합니다 LOCK_ESCALATION
테이블의 설정을. LOCK_ESCALATION
DML 문 (중 잠금 동작에 영향을 미치는 INSERT
, UPDATE
, DELETE
하지 DDL 문 중, 등) ( ALTER
). SCH-M 잠금은 항상이 예에서 전체 데이터베이스 개체, 테이블의 잠금입니다.
혼란의 원인이 될 수 있습니다.
SSMS는 ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
필요하지 않더라도 모든 경우에 스크립트에 명령문을 추가합니다 . 이 명령문이 필요한 경우, 해당 스크립트에서 발생 하는 테이블 스키마로 변경하는 동안 특정 방식으로 테이블을 잠그지 않도록 테이블의 현재 설정을 유지하기 위해 추가됩니다 .
즉, 테이블 스키마를 변경하는 모든 작업이 수행되는 동안 첫 번째 명령문 에서 SCH-M 잠금으로 테이블 이 잠 깁니다 ALTER TABLE ALTER COLUMN
. 마지막 ALTER TABLE SET LOCK_ESCALATION
진술은 영향을 미치지 않습니다. 그것은 (단지 미래 DML 문에 영향을 미치는 INSERT
, UPDATE
, DELETE
그 테이블 등).
언뜻보기 SET LOCK_ESCALATION = TABLE
에 전체 테이블을 변경한다는 사실과 관련이있는 것처럼 보이지만 (여기서는 스키마를 변경하고 있음) 오해의 소지가 있습니다.
긴 버전
경우에 따라 테이블을 변경하는 경우 SSMS는 전체 테이블을 다시 생성하는 스크립트를 생성하고 일부 경우에는 열 추가 또는 삭제와 같이 스크립트가 테이블을 다시 생성하지 않습니다.
이 샘플 테이블을 예로 들어 보겠습니다.
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Col1] [nvarchar](50) NOT NULL,
[Col2] [int] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
각 테이블에는 기본적으로 LOCK_ESCALATION
설정되어 TABLE
있습니다. 여기에서 바꾸자 :
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Col1
SSMS 테이블 디자이너에서 형식 을 변경하려고하면 SSMS가 전체 테이블을 다시 만드는 스크립트를 생성합니다.
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_Test
(
ID int NOT NULL,
Col1 nvarchar(10) NOT NULL,
Col2 int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_Test SET (LOCK_ESCALATION = DISABLE)
GO
IF EXISTS(SELECT * FROM dbo.Test)
EXEC('INSERT INTO dbo.Tmp_Test (ID, Col1, Col2)
SELECT ID, CONVERT(nvarchar(10), Col1), Col2 FROM dbo.Test WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.Test
GO
EXECUTE sp_rename N'dbo.Tmp_Test', N'Test', 'OBJECT'
GO
ALTER TABLE dbo.Test ADD CONSTRAINT
PK_Test PRIMARY KEY CLUSTERED
(
ID
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
COMMIT
위에서 LOCK_ESCALATION
새로 만든 테이블에 대해 설정 한 것을 볼 수 있습니다 . SSMS는 테이블의 현재 설정을 유지합니다. 설정의 현재 값이 기본값 인 경우에도 SSMS는이 줄을 생성 TABLE
합니다. 미래 에이 기본값이 변경되면 안전하고 명시적이고 미래의 문제를 예방하기 위해. 이것은 말이됩니다.
이 예에서는 SET LOCK_ESCALATION
테이블을 새로 작성하고 해당 설정을 유지해야하므로 명령문 을 생성해야 합니다.
새 열 추가와 같은 SSMS 테이블 디자이너를 사용하여 테이블을 간단하게 변경하려고하면 SSMS가 테이블을 다시 만들지 않는 스크립트를 생성합니다.
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Test ADD
NewCol nchar(10) NULL
GO
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
GO
COMMIT
보시다시피, ALTER TABLE SET LOCK_ESCALATION
이 경우에는 전혀 필요하지 않지만 여전히 문을 추가합니다 . 첫 번째 ALTER TABLE ... ADD
는 현재 설정을 변경하지 않습니다. SSMS 개발자들은이 ALTER TABLE SET LOCK_ESCALATION
문장이 어떤 경우 에 중복 되어 있는지 확인 하고 항상 안전하게 생성 하려고 노력할 가치가 없다고 결정한 것 같습니다 . 이 문장을 추가 할 때마다 아무런 해가 없습니다.
다시 한번, 테이블 전체 LOCK_ESCALATION
설정은 관련이 없으며 테이블 스키마는 ALTER TABLE
명령문을 통해 변경됩니다 . LOCK_ESCALATION
설정은와 같은 DML 문의 잠금 동작에만 영향을줍니다 UPDATE
.
마지막으로의 인용문은 다음 ALTER TABLE
을 강조합니다.
ALTER TABLE에 지정된 변경 사항은 즉시 구현됩니다. 변경시 테이블의 행을 수정해야하는 경우 ALTER TABLE은 행을 업데이트합니다. ALTER TABLE은 테이블에서 스키마 수정 (SCH-M) 잠금을 획득하여 변경 중에 테이블의 메타 데이터를 참조하는 다른 연결이 없는지 확인합니다.끝에 매우 짧은 SCH-M 잠금이 필요한 온라인 인덱스 작업을 제외하고. ALTER TABLE… SWITCH 작업에서 소스 테이블과 대상 테이블 모두에서 잠금이 획득됩니다. 테이블에 대한 수정 사항이 기록되고 완전히 복구 가능합니다. 열 삭제 또는 일부 SQL Server 버전에서 NOT NULL 열을 기본값으로 추가하는 등 매우 큰 테이블의 모든 행에 영향을주는 변경은 많은 로그 레코드를 완료하고 생성하는 데 시간이 오래 걸릴 수 있습니다. 이러한 ALTER TABLE 문은 많은 행에 영향을주는 INSERT, UPDATE 또는 DELETE 문과 동일한주의를 기울여 실행해야합니다.