Jawaban oleh Justin Grant menjelaskan apa yang LOCK_ESCALATION
dilakukan pengaturan secara umum, tetapi melewatkan satu detail penting dan tidak menjelaskan mengapa SSMS menghasilkan kode yang menetapkannya. Terutama, terlihat sangat aneh bahwa LOCK_ESCALATION
disetel sebagai pernyataan terakhir dalam skrip.
Saya melakukan beberapa tes dan inilah pemahaman saya tentang apa yang terjadi di sini.
Versi pendek
The ALTER TABLE
pernyataan yang menambahkan, tetes atau alter kolom implisit mengambil skema memodifikasi (SCH-M) kunci di atas meja, yang tidak ada hubungannya dengan LOCK_ESCALATION
pengaturan meja. LOCK_ESCALATION
mempengaruhi mengunci perilaku selama laporan DML ( INSERT
, UPDATE
, DELETE
, dll), tidak selama laporan DDL ( ALTER
). Kunci SCH-M selalu merupakan kunci dari seluruh objek database, tabel dalam contoh ini.
Sepertinya dari sinilah kebingungan itu berasal.
SSMS menambahkan ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
pernyataan tersebut ke skripnya dalam semua kasus, bahkan jika tidak diperlukan. Dalam kasus ketika pernyataan ini diperlukan, itu ditambahkan untuk mempertahankan pengaturan tabel saat ini, bukan untuk mengunci tabel dengan cara tertentu selama perubahan pada skema tabel yang terjadi dalam skrip itu.
Dengan kata lain, meja yang terkunci dengan kunci SCH-M pada pertama ALTER TABLE ALTER COLUMN
pernyataan sementara semua pekerjaan mengubah skema tabel dilakukan. ALTER TABLE SET LOCK_ESCALATION
Pernyataan terakhir tidak mempengaruhinya. Ini mempengaruhi hanya pernyataan DML masa depan ( INSERT
, UPDATE
, DELETE
, dll) untuk meja itu.
Pada pandangan pertama, ini terlihat seolah-olah SET LOCK_ESCALATION = TABLE
ada hubungannya dengan fakta bahwa kami mengubah seluruh tabel (kami mengubah skema di sini), tetapi menyesatkan.
Versi panjang
Saat mengubah tabel dalam beberapa kasus, SSMS menghasilkan skrip yang membuat ulang seluruh tabel dan dalam beberapa kasus yang lebih sederhana (seperti menambahkan atau menghapus kolom) skrip tidak membuat ulang tabel.
Mari kita ambil tabel contoh ini sebagai contoh:
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
Setiap tabel memiliki LOCK_ESCALATION
pengaturan, yang diatur TABLE
secara default. Mari kita ubah di sini:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Sekarang, jika saya mencoba mengubah Col1
tipe di desainer tabel SSMS, SSMS menghasilkan skrip yang membuat ulang seluruh tabel:
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
Anda dapat melihat di atas yang ditetapkan LOCK_ESCALATION
untuk tabel yang baru dibuat. SSMS melakukannya untuk mempertahankan pengaturan tabel saat ini. SSMS membuat baris ini, meskipun nilai setelan saat ini adalah nilai default TABLE
. Hanya untuk aman dan eksplisit dan mencegah kemungkinan masalah di masa depan jika di masa depan default ini berubah, saya rasa. Ini masuk akal.
Dalam contoh ini sangat diperlukan untuk menghasilkan SET LOCK_ESCALATION
pernyataan, karena tabel dibuat baru dan pengaturannya harus dipertahankan.
Jika saya mencoba membuat perubahan sederhana ke tabel menggunakan desainer tabel SSMS, seperti menambahkan kolom baru, maka SSMS menghasilkan skrip yang tidak membuat ulang tabel:
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
Seperti yang Anda lihat, itu masih menambahkan ALTER TABLE SET LOCK_ESCALATION
pernyataan, meskipun dalam hal ini tidak diperlukan sama sekali. Yang pertama ALTER TABLE ... ADD
tidak mengubah pengaturan saat ini. Saya kira, pengembang SSMS memutuskan bahwa tidak sepadan dengan upaya untuk mencoba menentukan dalam kasus apa ALTER TABLE SET LOCK_ESCALATION
pernyataan ini berlebihan dan selalu menghasilkannya, hanya untuk amannya. Tidak ada salahnya menambahkan pernyataan ini setiap saat.
Sekali lagi, LOCK_ESCALATION
pengaturan seluruh tabel tidak relevan sementara skema tabel berubah melalui ALTER TABLE
pernyataan. LOCK_ESCALATION
pengaturan hanya mempengaruhi perilaku penguncian pernyataan DML, seperti UPDATE
.
Akhirnya, kutipan dari ALTER TABLE
, tekankan milik saya:
Perubahan yang ditentukan dalam ALTER TABLE segera diimplementasikan. Jika perubahan memerlukan modifikasi baris dalam tabel, ALTER TABLE memperbarui baris. ALTER TABLE memperoleh kunci modifikasi skema (SCH-M) pada tabel untuk memastikan tidak ada koneksi lain yang mereferensikan bahkan metadata untuk tabel selama perubahan., kecuali operasi indeks online yang memerlukan kunci SCH-M yang sangat pendek di bagian akhir. Dalam operasi ALTER TABLE… SWITCH, kunci diperoleh pada tabel sumber dan target. Modifikasi yang dilakukan pada tabel dicatat dan dapat dipulihkan sepenuhnya. Perubahan yang memengaruhi semua baris dalam tabel yang sangat besar, seperti menghapus kolom atau, pada beberapa edisi SQL Server, menambahkan kolom NOT NULL dengan nilai default, dapat memakan waktu lama untuk menyelesaikan dan menghasilkan banyak catatan log. Pernyataan ALTER TABLE ini harus dijalankan dengan hati-hati seperti pernyataan INSERT, UPDATE, atau DELETE yang memengaruhi banyak baris.