যদি আমি অনুরোধটি সঠিকভাবে বুঝতে পারি তবে লক্ষ্যটি সারিগুলির ব্যাচগুলি মুছে ফেলা হয়, একই সময়ে, ডিএমএল অপারেশনগুলি সারণীতে পুরো সারিগুলিতে ঘটে থাকে। লক্ষ্যটি একটি ব্যাচ মুছে ফেলা; যাইহোক, যদি বলা ব্যাচের দ্বারা নির্ধারিত সীমার মধ্যে থাকা কোনও অন্তর্নিহিত সারিগুলি লক করা থাকে, তবে আমাদের অবশ্যই সেই ব্যাচটি এড়িয়ে গিয়ে পরবর্তী ব্যাচে চলে যেতে হবে। এরপরে আমাদের অবশ্যই এমন কোনও ব্যাচগুলিতে ফিরে যেতে হবে যা পূর্বে মুছে ফেলা হয়নি এবং আমাদের মূল মোছার যুক্তিকে আবার চেষ্টা করতে হবে। সারিগুলির সমস্ত প্রয়োজনীয় ব্যাচগুলি মোছা না হওয়া পর্যন্ত আমাদের অবশ্যই এই চক্রটি পুনরাবৃত্তি করতে হবে।
যেমনটি উল্লেখ করা হয়েছে, অবরুদ্ধ সারিগুলি থাকতে পারে এমন অতীত রেঞ্জগুলি এড়ানোর জন্য একটি READPAST ইঙ্গিত এবং রিড কমিটি (ডিফল্ট) বিচ্ছিন্নতা স্তরটি ব্যবহার করা যুক্তিসঙ্গত। আমি আরও একধাপ এগিয়ে গিয়ে সিরিয়ালিজেবল বিচ্ছিন্নতা স্তর এবং নিবিলিং মুছে ফেলা ব্যবহার করার পরামর্শ দেব।
এসকিউএল সার্ভার সিরিয়ালাইজযোগ্য লেনদেনের বিচ্ছিন্নতা স্তরটি ব্যবহার করার সময় লেনদেন-এসকিউএল বিবৃতি দ্বারা পড়া একটি রেকর্ড সেটটিতে স্পষ্টভাবে অন্তর্ভুক্ত থাকা সারিগুলির সীমাবদ্ধতার সুরক্ষার জন্য কী-রেঞ্জের লকগুলি ব্যবহার করে ... আরও এখানে সন্ধান করুন:
https://technet.microsoft.com /en-US/library/ms191272(v=SQL.105).aspx
নিবলিলিং ডিলিটগুলি সহ, আমাদের লক্ষ্য হ'ল সারিগুলির বিস্তৃতি বিচ্ছিন্ন করা এবং নিশ্চিত করা যায় যে আমরা যখন সারিগুলি মুছে ফেলছি তখন সেই সারিগুলিতে কোনও পরিবর্তন ঘটবে না, অর্থাত্ আমরা ফ্যানটম পড়ি বা সন্নিবেশ চাই না। সিরিয়ালাইজযোগ্য বিচ্ছিন্নতা স্তরটি এই সমস্যাটি সমাধান করার জন্য।
আমি আমার সমাধানটি প্রদর্শন করার আগে, আমি এটি যুক্ত করতে চাই যে আমি আপনার ডাটাবেসের ডিফল্ট বিচ্ছিন্নতা স্তরকে সিরিয়ালিজেবলের দিকে সরিয়ে দেওয়ার পরামর্শ দিচ্ছি না বা আমি প্রস্তাব দিচ্ছি না যে আমার সমাধানটি সবচেয়ে ভাল। আমি কেবল এটি উপস্থাপন করতে চাই এবং দেখতে চাই যে আমরা এখান থেকে কোথায় যেতে পারি।
কয়েকটি ঘরে রাখার নোট:
- আমি যে এসকিউএল সার্ভার সংস্করণটি ব্যবহার করছি তা হ'ল মাইক্রোসফ্ট এসকিউএল সার্ভার 2012 - 11.0.5343.0 (এক্স 64)
- আমার পরীক্ষার ডাটাবেস সম্পূর্ণ পুনরুদ্ধার মডেলটি ব্যবহার করছে
আমার পরীক্ষা শুরু করতে, আমি একটি পরীক্ষামূলক ডাটাবেস, একটি নমুনা সারণী স্থাপন করব এবং আমি সারণিটি 2,000,000 সারি দ্বারা পূরণ করব।
USE [master];
GO
SET NOCOUNT ON;
IF DATABASEPROPERTYEX (N'test', N'Version') > 0
BEGIN
ALTER DATABASE [test] SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
DROP DATABASE [test];
END
GO
-- Create the test database
CREATE DATABASE [test];
GO
-- Set the recovery model to FULL
ALTER DATABASE [test] SET RECOVERY FULL;
-- Create a FULL database backup
-- in order to ensure we are in fact using
-- the FULL recovery model
-- I pipe it to dev null for simplicity
BACKUP DATABASE [test]
TO DISK = N'nul';
GO
USE [test];
GO
-- Create our table
IF OBJECT_ID('dbo.tbl','U') IS NOT NULL
BEGIN
DROP TABLE dbo.tbl;
END;
CREATE TABLE dbo.tbl
(
c1 BIGINT IDENTITY (1,1) NOT NULL
, c2 INT NOT NULL
) ON [PRIMARY];
GO
-- Insert 2,000,000 rows
INSERT INTO dbo.tbl
SELECT TOP 2000
number
FROM
master..spt_values
ORDER BY
number
GO 1000
এই মুহুর্তে, আমাদের এক বা একাধিক সূচকের প্রয়োজন হবে যার উপর সিরিয়ালিজেবল বিচ্ছিন্নতা স্তরের লকিং প্রক্রিয়াগুলি কাজ করতে পারে।
-- Add a clustered index
CREATE UNIQUE CLUSTERED INDEX CIX_tbl_c1
ON dbo.tbl (c1);
GO
-- Add a non-clustered index
CREATE NONCLUSTERED INDEX IX_tbl_c2
ON dbo.tbl (c2);
GO
এখন, আমাদের 2000,000 সারি তৈরি হয়েছিল তা পরীক্ষা করে দেখুন to
SELECT
COUNT(*)
FROM
tbl;
সুতরাং, আমাদের আমাদের ডাটাবেস, টেবিল, সূচী এবং সারি রয়েছে। সুতরাং, আসুন নিবলিলিং মুছে ফেলার জন্য পরীক্ষাটি সেট আপ করি। প্রথমে, আমাদের অবশ্যই সিদ্ধান্ত নিতে হবে যে একটি সাধারণ নিবিলিং মুছিয়া প্রক্রিয়া কীভাবে তৈরি করা যায়।
DECLARE
@BatchSize INT = 100
, @LowestValue BIGINT = 20000
, @HighestValue BIGINT = 20010
, @DeletedRowsCount BIGINT = 0
, @RowCount BIGINT = 1;
SET NOCOUNT ON;
GO
WHILE @DeletedRowsCount < ( @HighestValue - @LowestValue )
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION
DELETE
FROM
dbo.tbl
WHERE
c1 IN (
SELECT TOP (@BatchSize)
c1
FROM
dbo.tbl
WHERE
c1 BETWEEN @LowestValue AND @HighestValue
ORDER BY
c1
);
SET @RowCount = ROWCOUNT_BIG();
COMMIT TRANSACTION;
SET @DeletedRowsCount += @RowCount;
WAITFOR DELAY '000:00:00.025';
CHECKPOINT;
END;
আপনি দেখতে পাচ্ছেন, আমি স্পষ্ট লেনদেনটি ওয়েল লুপের মধ্যে রেখেছি। আপনি যদি লগ ফ্লাশকে সীমাবদ্ধ করতে চান তবে লুপের বাইরে নির্দ্বিধায় তা অনুভব করুন। তদুপরি, যেহেতু আমরা সম্পূর্ণ পুনরুদ্ধার মডেলটিতে আছি, তাই আপনার ল্যাবিলিং অপসারণের ক্রিয়াকলাপ চালানোর সময় আপনি আরও প্রায়ই লেনদেনের লগ ব্যাকআপ তৈরি করতে ইচ্ছুক হতে পারেন যাতে আপনার লেনদেনের লগটিকে অতিমাত্রায় বাড়ার হাত থেকে রোধ করা যায়।
সুতরাং, এই সেটআপটি দিয়ে আমার বেশ কয়েকটি লক্ষ্য রয়েছে। প্রথমত, আমি আমার কী-রেঞ্জের লকগুলি চাই; সুতরাং, আমি ব্যাচগুলি যতটা সম্ভব ছোট রাখার চেষ্টা করি। আমি আমার "বিশাল" টেবিলের উপর negativeণাত্মক সামঞ্জস্যকে প্রভাবিত করতে চাই না; সুতরাং, আমি আমার লকগুলি নিতে এবং এগুলি যত দ্রুত সম্ভব ছেড়ে দিতে চাই। সুতরাং, আমি আপনাকে আপনার ব্যাচের আকার ছোট করার প্রস্তাব দিই।
এখন, আমি কার্যকরভাবে এই মোছার রুটিনের খুব সংক্ষিপ্ত উদাহরণ সরবরাহ করতে চাই। আমাদের অবশ্যই এসএসএমএসের মধ্যে একটি নতুন উইন্ডো খুলতে হবে এবং আমাদের টেবিল থেকে একটি সারি মুছে ফেলতে হবে। আমি এটি ডিফল্ট READ COMMITTED বিচ্ছিন্নতা স্তরটি ব্যবহার করে নিখুঁত লেনদেনের মধ্যে করব।
DELETE FROM
dbo.tbl
WHERE
c1 = 20005;
এই সারিটি কি আসলে মুছে ফেলা হয়েছিল?
SELECT
c1
FROM
dbo.tbl
WHERE
c1 BETWEEN 20000 AND 20010;
হ্যাঁ, এটি মুছে ফেলা হয়েছিল।
এখন, আমাদের লকগুলি দেখতে, এসএসএমএসের মধ্যে একটি নতুন উইন্ডো খুলুন এবং একটি বা দুটি কোড স্নিপেট যুক্ত করুন add আমি অ্যাডাম মেকানিকের এসপি_জয়েটিসটিভ ব্যবহার করছি, যা এখানে পাওয়া যাবে: sp_Woisactive
SELECT
DB_NAME(resource_database_id) AS DatabaseName
, resource_type
, request_mode
FROM
sys.dm_tran_locks
WHERE
DB_NAME(resource_database_id) = 'test'
AND resource_type = 'KEY'
ORDER BY
request_mode;
-- Our insert
sp_lock 55;
-- Our deletions
sp_lock 52;
-- Our active sessions
sp_whoisactive;
এখন, আমরা শুরু করতে প্রস্তুত। একটি নতুন এসএসএমএস উইন্ডোতে আসুন আমরা একটি স্পষ্ট লেনদেন শুরু করি যা আমরা মুছে ফেলা এক সারিটি পুনরায় toোকানোর চেষ্টা করবে। একই সাথে, আমরা আমাদের নিবিলিং মুছুন অপারেশন বন্ধ করব।
সন্নিবেশ কোড:
BEGIN TRANSACTION
SET IDENTITY_INSERT dbo.tbl ON;
INSERT INTO dbo.tbl
( c1 , c2 )
VALUES
( 20005 , 1 );
SET IDENTITY_INSERT dbo.tbl OFF;
--COMMIT TRANSACTION;
আসুন inোকানো দিয়ে শুরু করে আমাদের মোছার পরে দুটি ক্রিয়াকলাপ শুরু করি। আমরা কী-রেঞ্জের লক এবং একচেটিয়া লক দেখতে পারি।
সন্নিবেশ এই লকগুলি উত্পন্ন:
নিবলিং ডিলিট / সিলেক্ট করা এই লকগুলি ধারণ করে:
আমাদের সন্নিবেশ প্রত্যাশার মতো আমাদের মুছতে বাধা দিচ্ছে:
এখন আসুন, সন্নিবেশ লেনদেন প্রতিশ্রুতিবদ্ধ এবং দেখুন কি হয়।
এবং যেমন প্রত্যাশা করা হয়েছে, সমস্ত লেনদেন সম্পূর্ণ। এখন, আমাদের অবশ্যই সন্নিবেশটি ভুত ছিল কিনা তা মুছে ফেলা উচিত বা মুছে ফেলা অপারেশনটি এটিও সরিয়ে দিয়েছে কিনা তা দেখতে।
SELECT
c1
FROM
dbo.tbl
WHERE
c1 BETWEEN 20000 AND 20015;
আসলে, সন্নিবেশটি মোছা হয়েছে; সুতরাং, কোনও ভ্যান্ট inোকানোর অনুমতি দেওয়া হয়নি।
সুতরাং, উপসংহারে, আমি মনে করি যে এই অনুশীলনের আসল উদ্দেশ্যটি প্রতিটি একক সারি, পৃষ্ঠা, বা টেবিল-স্তরের লকটি চেষ্টা এবং ট্র্যাক করা এবং কোনও ব্যাচের উপাদানকে লক করা আছে কিনা তা নির্ধারণ করার চেষ্টা করা এবং তাই আমাদের মুছে ফেলা অপারেশনটির প্রয়োজন হবে অপেক্ষা করুন। এটাই হতে পারে প্রশ্নকারীদের অভিপ্রায়; তবে, সেই কাজটি অসম্ভব এবং অসম্ভব যদি না হয় তবে মূলত অবৈজ্ঞানিক। আসল লক্ষ্য হ'ল এটি নিশ্চিত করা যে কোনও বার আমরা আমাদের ব্যাচের পরিসরকে আমাদের নিজস্ব তালা দিয়ে আলাদা করে ফেলেছি এবং তারপরে ব্যাচটি মুছে ফেলার আগে কোনও অনাকাঙ্ক্ষিত ঘটনা না ঘটে। গুরুতর বিচ্ছিন্নতা স্তর এই লক্ষ্য অর্জন করে। মূলটি হ'ল আপনার নিবলগুলি ছোট রাখা, আপনার লেনদেনের লগ নিয়ন্ত্রণে রাখা এবং অযাচিত ঘটনাগুলি নির্মূল করা।
আপনি যদি গতি চান, তবে বিশালাকার মতো গভীর সারণীগুলি তৈরি করবেন না যা পার্টিশন করা যায় না এবং তাই দ্রুত ফলাফলের জন্য পার্টিশন স্যুইচিং ব্যবহার করতে অক্ষম হন। গতির মূল কথাটি পার্টিশন এবং সমান্তরালতা; ভোগান্তির মূল চাবিকাঠিটি হ'ল নিমক এবং লাইভ লকিং।
আপনি কী মনে করেন দয়া করে আমাকে জানান।
আমি ক্রিয়াকলাপের বিচ্ছিন্নতা স্তরের আরও কয়েকটি উদাহরণ তৈরি করেছি। সেগুলি নীচের লিঙ্কগুলিতে পাওয়া উচিত।
অপারেশন মুছুন
অপারেশন sertোকান
ইক্যুয়ালিটি অপারেশনস - পরবর্তী মূল মানগুলিতে কী-রেঞ্জের লক
ইক্যুয়ালিটি অপারেশনস - বিদ্যমান ডেটাগুলির একক ফলক
ইক্যুয়ালিটি অপারেশনস - অস্তিত্বহীন ডেটার একক সংগ্রহ
বৈষম্য অপারেশনস - রেঞ্জ এবং পরবর্তী কী মানগুলিতে কী-রেঞ্জ লক