নন-ক্লাস্টারড ইনডেক্স সহ বিভিন্ন সারি আপডেট করার সময় ডেডলক


13

আমি যখন আমি আইডি ক্ষেত্রে ক্লাস্টারযুক্ত এবং নন-ক্লাস্টারড সূচক ব্যবহার করি তখন লক আচরণটি আলাদা হয়ে লক্ষ্য করে আমি একটি অচল সমস্যা সমাধান করছি। ক্লাস্টেড ইনডেক্স বা প্রাথমিক কী আইডি ক্ষেত্রে প্রয়োগ করা হলে অচলাবস্থার সমস্যাটি সমাধান হবে বলে মনে হচ্ছে।

আমার বিভিন্ন সারিগুলিতে এক বা একাধিক আপডেট করে বিভিন্ন লেনদেন হয়, যেমন লেনদেন এ কেবল আইডি = এ দিয়ে সারি আপডেট করবে, টিএক্স বি কেবল আইডি = বি ইত্যাদির সাথে সারিটি স্পর্শ করবে etc.

এবং আমি বুঝতে পেরেছি যে সূচি ব্যতীত আপডেটটি সমস্ত সারিগুলির জন্য আপডেট লক অর্জন করবে এবং যখন প্রয়োজন হবে তখন একচেটিয়া লকটিতে প্রচ্ছন্ন হবে যা শেষ পর্যন্ত অচলাবস্থার দিকে পরিচালিত করবে। তবে কেন নন-ক্লাস্টারড ইনডেক্সের সাহায্যে আমি ব্যর্থ হলাম, অচলাবস্থা এখনও রয়েছে (যদিও হিট রেট বাদ পড়েছে বলে মনে হচ্ছে)

ডেটা টেবিল:

CREATE TABLE [dbo].[user](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [userName] [nvarchar](255) NULL,
    [name] [nvarchar](255) NULL,
    [phone] [nvarchar](255) NULL,
    [password] [nvarchar](255) NULL,
    [ip] [nvarchar](30) NULL,
    [email] [nvarchar](255) NULL,
    [pubDate] [datetime] NULL,
    [todoOrder] [text] NULL
)

ডেডলক ট্রেস

deadlock-list
deadlock victim=process4152ca8
process-list
process id=process4152ca8 taskpriority=0 logused=0 waitresource=RID: 5:1:388:29 waittime=3308 ownerId=252354 transactionname=user_transaction lasttranstarted=2014-04-11T00:15:30.947 XDES=0xb0bf180 lockMode=U schedulerid=3 kpid=11392 status=suspended spid=57 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2014-04-11T00:15:30.953 lastbatchcompleted=2014-04-11T00:15:30.950 lastattention=1900-01-01T00:00:00.950 clientapp=.Net SqlClient Data Provider hostname=BOOD-PC hostpid=9272 loginname=getodo_sql isolationlevel=read committed (2) xactid=252354 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
executionStack
frame procname=adhoc line=1 stmtstart=62 sqlhandle=0x0200000062f45209ccf17a0e76c2389eb409d7d970b0f89e00000000000000000000000000000000
update [user] WITH (ROWLOCK) set [todoOrder]=@para0 where id=@owner
frame procname=unknown line=1 sqlhandle=0x00000000000000000000000000000000000000000000000000000000000000000000000000000000
unknown
inputbuf
(@para0 nvarchar(2)<c/>@owner int)update [user] WITH (ROWLOCK) set [todoOrder]=@para0 where id=@owner
process id=process4153468 taskpriority=0 logused=4652 waitresource=KEY: 5:72057594042187776 (3fc56173665b) waittime=3303 ownerId=252344 transactionname=user_transaction lasttranstarted=2014-04-11T00:15:30.920 XDES=0x4184b78 lockMode=U schedulerid=3 kpid=7272 status=suspended spid=58 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2014-04-11T00:15:30.960 lastbatchcompleted=2014-04-11T00:15:30.960 lastattention=1900-01-01T00:00:00.960 clientapp=.Net SqlClient Data Provider hostname=BOOD-PC hostpid=9272 loginname=getodo_sql isolationlevel=read committed (2) xactid=252344 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
executionStack
frame procname=adhoc line=1 stmtstart=60 sqlhandle=0x02000000d4616f250747930a4cd34716b610a8113cb92fbc00000000000000000000000000000000
update [user] WITH (ROWLOCK) set [todoOrder]=@para0 where id=@uid
frame procname=unknown line=1 sqlhandle=0x00000000000000000000000000000000000000000000000000000000000000000000000000000000
unknown
inputbuf
(@para0 nvarchar(61)<c/>@uid int)update [user] WITH (ROWLOCK) set [todoOrder]=@para0 where id=@uid
resource-list
ridlock fileid=1 pageid=388 dbid=5 objectname=SQL2012_707688_webows.dbo.user id=lock3f7af780 mode=X associatedObjectId=72057594042122240
owner-list
owner id=process4153468 mode=X
waiter-list
waiter id=process4152ca8 mode=U requestType=wait
keylock hobtid=72057594042187776 dbid=5 objectname=SQL2012_707688_webows.dbo.user indexname=10 id=lock3f7ad700 mode=U associatedObjectId=72057594042187776
owner-list
owner id=process4152ca8 mode=U
waiter-list
waiter id=process4153468 mode=U requestType=wait

এছাড়াও একটি আকর্ষণীয় এবং সম্ভাব্য সম্পর্কিত অনুসন্ধান হ'ল ক্লাস্টারযুক্ত এবং নন-ক্লাস্টারযুক্ত সূচকের কাছে বিভিন্ন লক আচরণ রয়েছে বলে মনে হয়

ক্লাস্টারড ইনডেক্স ব্যবহার করার সময়, কীটিতে একটি এক্সক্লুসিভ লক পাশাপাশি আরআইডি-তে একটি এক্সক্লুসিভ লক থাকে যখন আপডেট হয়; যখন ক্লাস্টারযুক্ত অ-সূচক ব্যবহার করা হয়, তবে আমাকে বিভ্রান্ত করছে এমন দুটি পৃথক আরআইডি-তে দুটি এক্সক্লুসিভ লক রয়েছে।

কেউ যদি এটির কারণও ব্যাখ্যা করতে পারে তবে সহায়ক হবে।

পরীক্ষা এসকিউএল:

use SQL2012_707688_webows;
begin transaction;
update [user] with (rowlock) set todoOrder='{1}' where id = 63501
exec sp_lock;
commit;

ক্লাস্টারড ইনডেক্স হিসাবে আইডি সহ:

spid    dbid    ObjId   IndId   Type    Resource    Mode    Status
53  5   917578307   1   KEY (b1a92fe5eed4)                      X   GRANT
53  5   917578307   1   PAG 1:879                               IX  GRANT
53  5   917578307   1   PAG 1:1928                              IX  GRANT
53  5   917578307   1   RID 1:879:7                             X   GRANT

নন-ক্লাস্টারড ইনডেক্স হিসাবে আইডি সহ

spid    dbid    ObjId   IndId   Type    Resource    Mode    Status
53  5   917578307   0   PAG 1:879                               IX  GRANT
53  5   917578307   0   PAG 1:1928                              IX  GRANT
53  5   917578307   0   RID 1:879:7                             X   GRANT
53  5   917578307   0   RID 1:1928:18                           X   GRANT

EDIT1: কোনও সূচক ছাড়াই অচলাবস্থার বিবরণ
বলুন আমার কাছে দুটি টিএক্স এ এবং বি রয়েছে, যার মধ্যে দুটি আপডেট স্টেটমেন্ট রয়েছে, অবশ্যই আলাদা আলাদা সারি
tx A

update [user] with (rowlock) set todoOrder='{1}' where id = 63501
update [user] with (rowlock) set todoOrder='{2}' where id = 63501

tx বি

update [user] with (rowlock) set todoOrder='{3}' where id = 63502
update [user] with (rowlock) set todoOrder='{4}' where id = 63502

যেহেতু {1} এবং} 4 এর অচলাবস্থার সুযোগ থাকবে

lock 1} এ, ইউ লকটি সারি 63502-র জন্য অনুরোধ করা হয়েছে কারণ এটি একটি টেবিল স্ক্যান করা দরকার, এবং এক্স লকটি সারিটি 63501 ধরে রাখা যেহেতু এটি শর্তের সাথে মেলে matches

{4 at এ, ইউ লকটি 63501 সারিটির জন্য অনুরোধ করা হয়েছে এবং এক্স লকটি ইতিমধ্যে 63502 এর জন্য ধারণ করেছে

সুতরাং আমাদের কাছে txA রয়েছে 50 63৫০১ এবং 63৩৫০২ অপেক্ষা করছে যখন টিএক্সবি 63৩৫০২ ধরে 63৩50০১ এর জন্য অপেক্ষা করছে যা একটি অচলাবস্থা

সম্পাদনা 2: আমার পরীক্ষার কেসটির একটি বাগটি এখানে একটি তাত্পর্যপূর্ণ পরিস্থিতি তৈরি করেছে বিভ্রান্তির জন্য দুঃখিত তবে বাগটি একটি পৃথক পরিস্থিতি তৈরি করে এবং শেষ পর্যন্ত অচলাবস্থার কারণ বলে মনে হচ্ছে।

যেহেতু পলের বিশ্লেষণ সত্যিই আমাকে এই ক্ষেত্রে সাহায্য করেছে তাই আমি এটিকে একটি উত্তর হিসাবে গ্রহণ করব।

আমার পরীক্ষার কেসটি বাগের কারণে, দুটি লেনদেন txA এবং txB নীচের মতো একই সারিটি আপডেট করতে পারে:

tx এ

update [user] with (rowlock) set todoOrder='{1}' where id = 63501
update [user] with (rowlock) set todoOrder='{2}' where id = 63501

tx বি

update [user] with (rowlock) set todoOrder='{3}' where id = 63501

{2} এবং {3 এ অচলাবস্থার সুযোগ থাকবে যখন:

TXA RID- এ X লক ধরে রাখার সময় কীটিতে ইউ লকটির অনুরোধ করে ({1 of আপডেটের কারণে) টিএক্সবি আরআইডিতে ইউ লক অনুরোধ করে যখন কীটিতে ইউ লক ধরে


1
আমি বুঝতে পারি না কেন কোনও লেনদেনের জন্য একই সারিতে দু'বার আপডেট করা দরকার।
ypercubeᵀᴹ

@ ইপারকিউব ভাল কথা, এটিই আমার উন্নতি করা উচিত। তবে এই ক্ষেত্রে আমি লক আচরণগুলি সম্পর্কে আরও ভাল ধারণা পেতে চাই
বুড

@ অধ্যাপক আরও চিন্তাভাবনার পরে আমি মনে করি জটিল যুক্তিযুক্ত একটি অ্যাপ্লিকেশন একই টিএক্সে একই সারির দু'বার আপডেট করতে হবে, উদাহরণস্বরূপ বিভিন্ন কলাম হতে পারে
বুদ

উত্তর:


16

... কেন গোষ্ঠী সূচক সহ, অচলাবস্থা এখনও আছে (যদিও হিট রেট বাদ পড়েছে)

প্রশ্নটি যথাযথভাবে পরিষ্কার নয় (উদাহরণস্বরূপ id, প্রতিটি লেনদেনে কতগুলি আপডেট এবং কোন মানগুলি হয়) তবে একটি স্পষ্ট ডেডলক দৃশ্যের উদ্ভব ঘটে একক লেনদেনের মধ্যে একাধিক একক সারির আপডেটের সাথে, যেখানে [id]মানগুলির একটি ওভারল্যাপ থাকে এবং আইডিগুলি হয় একটি ভিন্ন [id]ক্রমে আপডেট হয়েছে :

[T1]: Update id 2; Update id 1;
[T2]: Update id 1; Update id 2;

ডেডলক ক্রম: টি 1 (u2), টি 2 (u1), টি 1 (u1) অপেক্ষা , টি 2 (u2) অপেক্ষা

এই অচলাবস্থা ক্রম প্রতিটি লেনদেনের মধ্যে আইডি ক্রমে কঠোরভাবে আপডেট করে এড়ানো হতে পারে (একই পথে একই ক্রমে লকগুলি অর্জন))

ক্লাস্টারড ইনডেক্স ব্যবহার করার সময়, কীটিতে একটি এক্সক্লুসিভ লক পাশাপাশি আরআইডি-তে একটি এক্সক্লুসিভ লক থাকে যখন আপডেট হয়; যখন ক্লাস্টারযুক্ত অ-সূচক ব্যবহার করা হয়, তবে আমাকে বিভ্রান্ত করছে এমন দুটি পৃথক আরআইডি-তে দুটি এক্সক্লুসিভ লক রয়েছে।

অনন্য ক্লাস্টারড ইনডেক্স চালু থাকলে id, ইন-সারি ডেটাতে লেখাগুলি রক্ষা করতে ক্লাস্টারিং কীতে একটি অনন্য লক নেওয়া হয়। RIDএলওবি textকলামে লেখাটি রক্ষা করতে একটি পৃথক একচেটিয়া লক প্রয়োজন , যা ডিফল্টরূপে একটি পৃথক ডেটা পৃষ্ঠায় সঞ্চিত থাকে।

যখন টেবিলটি কেবল একটি নন-ক্ল্লাস্টার্ড সূচক চালু থাকে id, তখন দুটি জিনিস ঘটে। প্রথমত, একটি RIDএক্সক্লুসিভ লক হিপ-ইন-সারি ডেটার সাথে সম্পর্কিত, এবং অন্যটি আগের মতো এলওবি ডেটাতে থাকা লক। দ্বিতীয় প্রভাবটি হ'ল আরও জটিল বাস্তবায়ন পরিকল্পনা প্রয়োজন।

একটি ক্লাস্টারড ইনডেক্স এবং একটি সাধারণ একক মানের সমতা প্রিনিকেট আপডেটের সাথে, ক্যোয়ারী প্রসেসর একটি অপ্টিমাইজেশন প্রয়োগ করতে পারে যা একটি একক পথ ব্যবহার করে একটি একক অপারেটরে আপডেট (পড়ুন এবং লিখুন) সম্পাদন করে:

একক অপারেটর আপডেট

সারিটি একক অনুসন্ধানের অপারেশনে অবস্থিত এবং আপডেট করা হয়েছে, কেবলমাত্র একচেটিয়া লক প্রয়োজন (কোনও আপডেট লক প্রয়োজন হয় না)। আপনার নমুনা টেবিলটি ব্যবহার করে লকিংয়ের একটি উদাহরণ উদাহরণ:

acquiring IX lock on OBJECT: 6:992930809:0 -- TABLE
acquiring IX lock on PAGE: 6:1:59104 -- INROW
acquiring X lock on KEY: 6:72057594233618432 (61a06abd401c) -- INROW
acquiring IX lock on PAGE: 6:1:59091 -- LOB
acquiring X lock on RID: 6:1:59091:1 -- LOB

releasing lock reference on PAGE: 6:1:59091 -- LOB
releasing lock reference on RID: 6:1:59091:1 -- LOB
releasing lock reference on KEY: 6:72057594233618432 (61a06abd401c) -- INROW
releasing lock reference on PAGE: 6:1:59104 -- INROW

কেবল একটি অবিচ্ছিন্ন সূচক দিয়ে, একই অপ্টিমাইজেশন প্রয়োগ করা যায় না কারণ আমাদের একটি বি-ট্রি কাঠামো থেকে পড়তে হবে এবং অন্যটি লিখতে হবে। মাল্টি-পাথ পরিকল্পনার পৃথক পঠন এবং লেখার পর্যায় রয়েছে:

মাল্টি-ইটারেটর আপডেট

এই সারিটি যোগ্যতা অর্জন করে যদি একচেটিয়া লকগুলিতে রূপান্তর করে, পড়ার সময় আপডেট লকগুলি অর্জন করে। প্রদত্ত স্কিমা সহ লক ক্রম উদাহরণ:

acquiring IX lock on OBJECT: 6:992930809:0 -- TABLE
acquiring IU lock on PAGE: 6:1:59105 -- NC INDEX
acquiring U lock on KEY: 6:72057594233749504 (61a06abd401c) -- NC INDEX
acquiring IU lock on PAGE: 6:1:59104 -- HEAP
acquiring U lock on RID: 6:1:59104:1 -- HEAP
acquiring IX lock on PAGE: 6:1:59104 -- HEAP convert to X
acquiring X lock on RID: 6:1:59104:1 -- HEAP convert to X
acquiring IU lock on PAGE: 6:1:59091 -- LOB
acquiring U lock on RID: 6:1:59091:1 -- LOB

releasing lock reference on PAGE: 6:1:59091 
releasing lock reference on RID: 6:1:59091:1
releasing lock reference on RID: 6:1:59104:1
releasing lock reference on PAGE: 6:1:59104 
releasing lock on KEY: 6:72057594233749504 (61a06abd401c)
releasing lock on PAGE: 6:1:59105 

নোট করুন LOB ডেটাটি টেবিল আপডেট পুনরুদ্ধারে পাঠানো এবং লিখিত হয়। আরও জটিল পরিকল্পনা এবং একাধিক পড়ার ও লেখার পথগুলি অচলাবস্থার সম্ভাবনা বাড়িয়ে তোলে।

শেষ অবধি, আমি সাহায্য করতে পারছি না তবে টেবিল সংজ্ঞাতে ব্যবহৃত ডেটা ধরণের লক্ষ্য করব। আপনার textনতুন কাজের জন্য অবহেলিত ডেটা প্রকার ব্যবহার করা উচিত নয় ; বিকল্প, যদি আপনার এই কলামে 2 জিবি পর্যন্ত ডেটা সঞ্চয় করার দক্ষতার প্রয়োজন হয় তবে তা varchar(max)। মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য textএবং varchar(max)যে textডেটা বন্ধ সারি ডিফল্টরূপে সংরক্ষিত হয়, যখন varchar(max)ইন-সারি ডিফল্টরূপে দোকানে।

আপনার যদি সেই নমনীয়তার প্রয়োজন হয় তবেই ইউনিকোড প্রকারগুলি ব্যবহার করুন (যেমন, কোনও আইপি ঠিকানার কেন ইউনিকোডের প্রয়োজন হবে তা দেখা শক্ত)। এছাড়াও, আপনার বৈশিষ্ট্যের জন্য উপযুক্ত দৈর্ঘ্যের সীমাটি চয়ন করুন - 255 সর্বত্রই সঠিক হতে পারে বলে মনে হচ্ছে।

অতিরিক্ত পঠন:
ড্যাডলক এবং লাইভলক সাধারণ প্যাটার্নগুলি বার্ট ডানকের
ডেডলক সমস্যা সমাধান সিরিজ

তালাবদ্ধ ট্র্যাকিং বিভিন্ন উপায়ে করা যেতে পারে। উন্নত পরিষেবাদিগুলির সাথে এসকিউএল সার্ভার এক্সপ্রেস ( কেবলমাত্র 2014 এবং 2012 এসপি 1 ) কেবলমাত্র প্রোফাইলার সরঞ্জাম রয়েছে , যা লক অধিগ্রহণ এবং প্রকাশের বিশদটি দেখার একটি সমর্থিত উপায়।


দুর্দান্ত উত্তর। আপনি কীভাবে লগ / ট্রেসকে আউটপুট দিচ্ছেন যা "অধিগ্রহণ ... লক" এবং "লক রেফারেন্স প্রকাশ করছে" বার্তা রয়েছে?
সানজিভ জীবন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.