আমার এমন পরিস্থিতি রয়েছে যেখানে আমি অচলাবস্থা পাচ্ছি এবং আমি মনে করি যে আমি অপরাধীদের সংকুচিত করেছি, তবে আমি এটি ঠিক করতে আমি কী করতে পারি তা আমি নিশ্চিত নই।
এটি এসকিউএল সার্ভার ২০০৮ আর 2 চালাচ্ছে এমন একটি পরিবেশ পরিবেশে।
আপনাকে পরিস্থিতি সম্পর্কে কিছুটা সরলীকৃত দর্শন দিতে:
নীচে সংজ্ঞায়িত হিসাবে আমার কাছে 3 টি টেবিল রয়েছে:
TABLE activity (
id, -- PK
...
)
TABLE member_activity (
member_id, -- PK col 1
activity_id, -- PK col 2
...
)
TABLE follow (
id, -- PK
follower_id,
member_id,
...
)
member_activity
টেবিল একটি যৌগ প্রাথমিক কী হিসাবে সংজ্ঞায়িত করা হয়েছে member_id, activity_id
, কারণ আমি শুধুমাত্র কখনও যে টেবিল যে ভাবে ডেটা সন্ধান করার প্রয়োজন।
আমার এতে একটি অবিবাহিত সূচকও রয়েছে follow
:
CREATE NONCLUSTERED INDEX [IX_follow_member_id_includes]
ON follow ( member_id ASC ) INCLUDE ( follower_id )
অতিরিক্তভাবে, আমার কাছে স্কিমা-সীমাবদ্ধ দৃষ্টিভঙ্গি রয়েছে network_activity
যা নীচে সংজ্ঞায়িত হয়েছে:
CREATE VIEW network_activity
WITH SCHEMABINDING
AS
SELECT
follow.follower_id as member_id,
member_activity.activity_id as activity_id,
COUNT_BIG(*) AS cb
FROM member_activity
INNER JOIN follow ON follow.member_id = member_activity.member_id
INNER JOIN activity ON activity.id = member_activity.activity_id
GROUP BY follow.follower_id, member_activity.activity_id
যার একটি অনন্য ক্লাস্টারড সূচকও রয়েছে:
CREATE UNIQUE CLUSTERED INDEX [IX_network_activity_unique_member_id_activity_id]
ON network_activity
(
member_id ASC,
activity_id ASC
)
এখন, আমি দুটি ডেডলকড সঞ্চিত পদ্ধতি রয়েছে। তারা নিম্নলিখিত প্রক্রিয়াটি অতিক্রম করে:
-- SP1: insert activity
-----------------------
INSERT INTO activity (...)
SELECT ... FROM member_activity WHERE member_id = @a AND activity_id = @b
INSERT INTO member_activity (...)
-- SP2: insert follow
---------------------
SELECT follow WHERE member_id = @x AND follower_id = @y
INSERT INTO follow (...)
এই 2 টি পদ্ধতি দুটিই রিড কমিটিকেটেড বিচ্ছিন্নতায় চালিত হয়। আমি 1222 বর্ধিত ইভেন্ট আউটপুট জিজ্ঞাসা করতে পরিচালিত করেছি, এবং ডেডলকগুলি সম্পর্কে নিম্নলিখিতটি ব্যাখ্যা করেছি:
এসপি 1 সূচকে
RangeS-S
কী লকের জন্য অপেক্ষা করছেIX_follow_member_id_includes
যখন এসপি 2 একটি বিবাদযুক্ত (এক্স) লক ধরেএসপি 2 একটি
S
মোড লকের জন্য অপেক্ষা করছেPK_member_activity
যখন এসপি 1 একটি বিরোধী (এক্স) লক ধরে
অদলবদল প্রতিটি ক্যোয়ারির (অন্তর্ভুক্তি) শেষ লাইনে ঘটছে বলে মনে হচ্ছে। আমার কাছে যা অস্পষ্ট তা এই কারণেই এসপি 1 IX_follow-member_id_includes
সূচীতে লক চাইছে । আমার কাছে কেবলমাত্র লিঙ্কটিই এই সূচীকৃত ভিউ থেকে মনে হচ্ছে যার কারণে আমি এটি অন্তর্ভুক্ত করেছি।
এই অচলাবস্থা যাতে না ঘটে সে জন্য আমার পক্ষে সর্বোত্তম উপায় কী হবে? কোন সাহায্যের অনেক প্রশংসা হবে। অচলাবস্থার সমস্যা সমাধানে আমার খুব বেশি অভিজ্ঞতা নেই।
আমি সরবরাহ করতে পারেন যে আরও কিছু তথ্য আছে যে সাহায্য করতে পারেন দয়া করে আমাকে জানান!
আগাম ধন্যবাদ.
সম্পাদনা 1: অনুরোধ অনুযায়ী আরও কিছু তথ্য যুক্ত করা হচ্ছে।
এই অচলাবস্থা থেকে এখানে 1222 আউটপুট:
<deadlock>
<victim-list>
<victimProcess id="process4c6672748" />
</victim-list>
<process-list>
<process id="process4c6672748" taskpriority="0" logused="332" waitresource="KEY: 8:72057594104905728 (25014f77eaba)" waittime="581" ownerId="474698706" transactionname="INSERT" lasttranstarted="2014-07-03T17:03:12.287" XDES="0x298487970" lockMode="RangeS-S" schedulerid="1" kpid="972" status="suspended" spid="79" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-07-03T17:03:12.283" lastbatchcompleted="2014-07-03T17:03:12.283" lastattention="2014-07-03T10:25:00.283" clientapp=".Net SqlClient Data Provider" hostname="WIN08CLYDESDALE" hostpid="4596" loginname="TechPro" isolationlevel="read committed (2)" xactid="474698706" currentdb="8" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="" line="7" stmtstart="1194" stmtend="1434" sqlhandle="0x02000000a26bb72a2b220406876cad09c22242e5265c82e6" />
<frame procname="" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000" />
</executionStack>
<inputbuf> <!-- SP 1 --> </inputbuf>
</process>
<process id="process6cddc5b88" taskpriority="0" logused="456" waitresource="KEY: 8:72057594098679808 (89013169fc76)" waittime="567" ownerId="474698698" transactionname="INSERT" lasttranstarted="2014-07-03T17:03:12.283" XDES="0x30c459970" lockMode="S" schedulerid="4" kpid="4204" status="suspended" spid="70" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-07-03T17:03:12.283" lastbatchcompleted="2014-07-03T17:03:12.283" lastattention="2014-07-03T15:04:55.870" clientapp=".Net SqlClient Data Provider" hostname="WIN08CLYDESDALE" hostpid="4596" loginname="TechPro" isolationlevel="read committed (2)" xactid="474698698" currentdb="8" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
<executionStack>
<frame procname="" line="18" stmtstart="942" stmtend="1250" sqlhandle="0x03000800ca458d315ee9130100a300000100000000000000" />
</executionStack>
<inputbuf> <!-- SP 2 --> </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594104905728" dbid="8" objectname="" indexname="" id="lock33299fc00" mode="X" associatedObjectId="72057594104905728">
<owner-list>
<owner id="process6cddc5b88" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process4c6672748" mode="RangeS-S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594098679808" dbid="8" objectname="" indexname="" id="lockb7e2ba80" mode="X" associatedObjectId="72057594098679808">
<owner-list>
<owner id="process4c6672748" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process6cddc5b88" mode="S" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
এক্ষেত্রে,
যুক্তঅবজেক্টআইড 72057594098679808 এর সাথে সম্পর্কিত member_activity, PK_member_activity
যুক্তঅবজেক্টআইড 72057594104905728 এর সাথে সম্পর্কিত follow, IX_follow_member_id_includes
এছাড়াও, এসপি 1 এবং এসপি 2 কী করছে তার আরও সূক্ষ্ম চিত্র এখানে
-- SP1: insert activity
-----------------------
DECLARE @activityId INT
INSERT INTO activity (field1, field2)
VALUES (@field1, @field2)
SET @activityId = SCOPE_IDENTITY();
IF NOT EXISTS(
SELECT TOP 1 member_id
FROM member_activity
WHERE member_id = @m1 AND activity_id = @activityId
)
INSERT INTO member_activity (member_id, activity_id, field1)
VALUES (@m1, @activityId, @field1)
IF NOT EXISTS(
SELECT TOP 1 member_id
FROM member_activity
WHERE member_id = @m2 AND activity_id = @activityId
)
INSERT INTO member_activity (member_id, activity_id, field1)
VALUES (@m2, @activityId, @field1)
এছাড়াও এসপি 2:
-- SP2: insert follow
---------------------
IF NOT EXISTS(
SELECT TOP 1 1
FROM follow
WHERE member_id = @memberId AND follower_id = @followerId
)
INSERT INTO follow (member_id, follower_id)
VALUES (@memberId, @followerId)
সম্পাদনা 2: মন্তব্যগুলি পুনরায় পড়ার পরে, আমি ভেবেছিলাম যে কী কলামগুলি বিদেশী কী তা নিয়ে কিছু তথ্য যুক্ত করব ...
member_activity.member_id
একটিmember
টেবিলের জন্য একটি বিদেশী কীmember_activity.activity_id
activity
টেবিলের জন্য একটি বিদেশী কীfollow.member_id
একটিmember
টেবিলের জন্য একটি বিদেশী কীfollow.follower_id
একটিmember
টেবিলের জন্য একটি বিদেশী কী
আপডেট 1:
আমি বেশ কয়েকটি পরিবর্তন করেছি যা আমি ভেবেছিলাম যে কোনও অভাগা ছাড়াই অচলাবস্থা রোধ করতে সহায়তা করবে।
আমি যে পরিবর্তনগুলি করেছি তা নিম্নরূপ:
-- SP1: insert activity
-----------------------
DECLARE @activityId INT
INSERT INTO activity (field1, field2)
VALUES (@field1, @field2)
SET @activityId = SCOPE_IDENTITY();
MERGE member_activity WITH ( HOLDLOCK ) as target
USING (SELECT @m1 as member_id, @activityId as activity_id, @field1 as field1) as source
ON target.member_id = source.member_id
AND target.activity_id = source.activity_id
WHEN NOT MATCHED THEN
INSERT (member_id, activity_id, field1)
VALUES (source.member_id, source.activity_id, source.field1)
;
MERGE member_activity WITH ( HOLDLOCK ) as target
USING (SELECT @m2 as member_id, @activityId as activity_id, @field1 as field1) as source
ON target.member_id = source.member_id
AND target.activity_id = source.activity_id
WHEN NOT MATCHED THEN
INSERT (member_id, activity_id, field1)
VALUES (source.member_id, source.activity_id, source.field1)
;
এবং এসপি 2 সহ:
-- SP2: insert follow
---------------------
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION
IF NOT EXISTS(
SELECT TOP 1 1
FROM follow WITH ( UPDLOCK )
WHERE member_id = @memberId AND follower_id = @followerId
)
INSERT INTO follow (member_id, follower_id)
VALUES (@memberId, @followerId)
COMMIT
এই দুটি পরিবর্তন সহ, আমি এখনও অচলাবস্থার মনে হচ্ছে।
যদি আমি সরবরাহ করতে পারি অন্য কিছু থাকে তবে দয়া করে আমাকে জানান। ধন্যবাদ।
SERIALIZABLE
(এটির চেয়ে আরও কিছুটা বেশি, তবে এটি একটি উত্তর নয় :)