জাস্টিন গ্রান্টের উত্তরটি LOCK_ESCALATION
সেটিংটি সাধারণভাবে কী করে তা ব্যাখ্যা করে তবে একটি গুরুত্বপূর্ণ বিবরণ মিস করে এবং এসএসএমএস কেন সেট করে যে কোডটি উত্পন্ন করে তা ব্যাখ্যা করে না। বিশেষত, এটি খুব আশ্চর্যজনক দেখাচ্ছে যে LOCK_ESCALATION
স্ক্রিপ্টের সর্বশেষ বিবৃতি হিসাবে সেট করা আছে।
আমি কয়েকটি পরীক্ষা করেছি এবং এখানে কী ঘটছে তা আমার বোঝার জন্য।
সংক্ষিপ্ত সংস্করণ
যে ALTER TABLE
বিবৃতিটি স্পষ্টভাবে একটি কলাম যুক্ত করে, ড্রপ করে বা পরিবর্তিত করে তা টেবিলে একটি স্কিমা সংশোধন (এসসিএইচ-এম) লক নেয়, যার LOCK_ESCALATION
কোনও টেবিলের সেটিংয়ের সাথে কোনও সম্পর্ক নেই । LOCK_ESCALATION
DML বিবৃতি (সময় আচরণ লক প্রভাবিত INSERT
, UPDATE
, DELETE
, ইত্যাদি), DDL বিবৃতি সময় নয় ( ALTER
)। এসসিএইচ-এম লক হ'ল সর্বদা পুরো ডাটাবেস অবজেক্টের একটি লক, এই উদাহরণে সারণী।
এই কারণেই বিভ্রান্তি আসে।
এসএসএমএস ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
সমস্ত স্ক্রিপ্টে বিবৃতি যুক্ত করে , এমনকি যখন এটি প্রয়োজন হয় না। যখন এই বিবৃতিটির প্রয়োজন হয়, তখন এটি টেবিলের বর্তমান সেটিংস সংরক্ষণের জন্য যুক্ত করা হয়, সেই স্ক্রিপ্টে টেবিল স্কিমায় পরিবর্তনের সময় কোনও নির্দিষ্ট উপায়ে টেবিলটি লক না করা ।
অন্য কথায়, টেবিল হয় প্রথম SCH-এম লক দিয়ে লক ALTER TABLE ALTER COLUMN
যখন সব টেবিল স্কিমা পরিবর্তন কাজ সম্পন্ন করা হয় বিবৃতি। শেষ ALTER TABLE SET LOCK_ESCALATION
বিবৃতি এটি প্রভাবিত করে না। এটা শুধুমাত্র ভবিষ্যতে DML বিবৃতি (প্রভাবিত INSERT
, UPDATE
, DELETE
, ইত্যাদি) যে টেবিল জন্য।
প্রথম নজরে এটি দেখে মনে SET LOCK_ESCALATION = TABLE
হচ্ছে যেন আমরা পুরো টেবিলটি পরিবর্তন করছি (আমরা এখানে এর স্কিমাটি পরিবর্তন করছি) এর সাথে কিছু করার আছে তবে এটি বিভ্রান্তিকর।
দীর্ঘ সংস্করণ
কিছু ক্ষেত্রে টেবিলটি পরিবর্তন করার সময় এসএসএমএস একটি স্ক্রিপ্ট তৈরি করে যা পুরো টেবিলটি পুনরায় তৈরি করে এবং কিছু সহজ ক্ষেত্রে (কোনও কলাম যুক্ত বা বাদ দেওয়ার মতো) স্ক্রিপ্টটি টেবিলটি পুনরায় তৈরি করে না।
আসুন উদাহরণ হিসাবে এই নমুনা সারণীটি নেওয়া যাক:
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
যদি এসএসএমএস টেবিল ডিজাইনারের টাইপটি পরিবর্তন করার চেষ্টা করি , এসএসএমএস একটি স্ক্রিপ্ট তৈরি করে যা পুরো টেবিলটি পুনরায় তৈরি করে:
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
তৈরি সারণীর জন্য সেট করে তা উপরে দেখতে পারেন । এসএসএমএস টেবিলের বর্তমান সেটিংস সংরক্ষণের জন্য এটি করে। এসএসএমএস এই লাইনটি জেনারেট করে, সেটিংয়ের বর্তমান মান ডিফল্ট TABLE
মান হলেও । ভবিষ্যতে যদি এই ডিফল্টটি পরিবর্তিত হয় তবে কেবল নিরাপদ এবং স্পষ্ট থাকতে এবং ভবিষ্যতের সম্ভাব্য সমস্যাগুলি প্রতিরোধ করার জন্য আমার ধারণা। এইবার বুঝতে পারছি.
এই উদাহরণে এটি SET LOCK_ESCALATION
বিবৃতি উত্পন্ন করার জন্য সত্যই প্রয়োজন , কারণ সারণীটি নতুনভাবে তৈরি হয়েছিল এবং এর সেটিংসটি সংরক্ষণ করতে হবে।
আমি যদি এসএসএমএস টেবিল ডিজাইনার যেমন একটি নতুন কলাম যুক্ত করার সাথে টেবিলে একটি সাধারণ পরিবর্তন করার চেষ্টা করি, তবে এসএসএমএস একটি স্ক্রিপ্ট তৈরি করে যা টেবিলটি পুনরায় তৈরি করে না:
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
বর্তমান সেটিংস পরিবর্তন করে না। আমার অনুমান, এসএসএমএস বিকাশকারীরা সিদ্ধান্ত নিয়েছিলেন যে এই ALTER TABLE SET LOCK_ESCALATION
বিবৃতিটি কীভাবে অপ্রয়োজনীয় তা নির্ধারণ করার চেষ্টা করার চেষ্টা করা উপযুক্ত নয় এবং কেবল নিরাপদ থাকার জন্য এটি সর্বদা উত্পন্ন করে। প্রতিবার এই বিবৃতি যুক্ত করার কোনও ক্ষতি নেই।
আবারও, টেবিল-প্রশস্ত LOCK_ESCALATION
সেটিংস অপ্রাসঙ্গিক যখন টেবিলের স্কিমা ALTER TABLE
বিবৃতিতে পরিবর্তন হয় । LOCK_ESCALATION
সেটিং কেবলমাত্র ডিএমএল স্টেটমেন্টের লকিং আচরণকেই প্রভাবিত করে, যেমন UPDATE
।
অবশেষে, আমার একটি বক্তব্য ALTER TABLE
, আমার উপর জোর দিন:
ALTER TABLE এ উল্লিখিত পরিবর্তনগুলি তত্ক্ষণাত্ কার্যকর করা হবে। পরিবর্তনগুলি যদি সারণীতে সারিগুলির পরিবর্তনগুলির প্রয়োজন হয় তবে ALTER TABLE সারিগুলি আপডেট করে। পরিবর্তনের সময় টেবিলের জন্য অন্য কোনও সংযোগ এমনকি টেবিলে মেটাডেটা উল্লেখ না করে তা নিশ্চিত করার জন্য টেবিলে টেবিলের স্কিমা মডিফাই (SCH-M) লকটি অর্জন করে, অনলাইন সূচক অপারেশনগুলি বাদে শেষের দিকে খুব ছোট SCH-M লক প্রয়োজন। অলটার টেবিলে ... সুইচ অপারেশনে লকটি উত্স এবং লক্ষ্য টেবিল উভয়তেই অর্জিত হয়। টেবিলটিতে করা পরিবর্তনগুলি লগ এবং সম্পূর্ণ পুনরুদ্ধারযোগ্য। যে পরিবর্তনগুলি খুব বড় সারণীতে সমস্ত সারিগুলিকে প্রভাবিত করে, যেমন একটি কলাম কমানো বা এসকিউএল সার্ভারের কয়েকটি সংস্করণে, একটি ডিফল্ট মান সহ একটি নট কলাম যুক্ত করা অনেকগুলি লগ রেকর্ডগুলি সম্পূর্ণ করতে এবং তৈরি করতে দীর্ঘ সময় নিতে পারে। এই অল্টার টেবিলের বিবৃতিগুলি যে কোনও INSERT, আপডেট, বা অনেকগুলি সারিগুলিকে প্রভাবিত করে এমন বিবৃতি মুছে ফেলার মতো একই যত্নের সাথে সম্পাদন করা উচিত।