پرهام درویشی
پرهام درویشی
خواندن ۴ دقیقه·۴ سال پیش

Deadlock در SqlServer

خوب در مرحله اول ببینیم deadlock چیه ؟

مفهوم deadlock یکی از مباحثی هستش که بچه های کامپیوتر زیاد میشنون و البته از اون دست کلمه هاست که شاید سایر توی سایر علوم هم زیاد به کار بیاد برای مثال ما این مفهوم رو هم در سیستم عامل و هم در دیتابیس و .. داریم اما تعریفی که الان از بنده می شنوید با تمرکز و دید SQL یی گفته میشه و شاید این عبارت در جاهای دیگه به صورت عمومی درست باشه اما به صورت تخصصی قابل دفاع نیست..
در SQL SERVER این مفهوم(یعنی deadlock) یک مشکل همزمانی خاص تلقی میشه وقتی که دو تراکنش (transaction) عملیات های همدیگر رو بلاک میکنن حالا این بلاک شدن یعنی چی ؟ یعنی برای مثال تراکنش اول یکی از آبجکت های دیتابیس رو لاک میکنه و در همین حال تراکنش دوم میخواد به این آبجکت لاک شده دسترسی داشته باشه و برعکس ..

انتخاب نحوه برخورد SQL با deadlock رو شما میتونید با دستور DEADLOCK_PRIORITY مشخص کنید که الویت شما با کدام تراکنش هستش اما اگر این موضع رو بزارید به عهده دیتابیس بمونه دیتابیس اون تراکنشی که در حلقه درخواست ها باعث این اتفاق شده رو انتخاب میکنه و اون رو اصطلاحا Rollback میکنه(منظور از rollback به این معنی هست که به حالت ابتدایی برمیگردونه .. البته خود این مفهوم یک مفهوم خیلی مهم هست که در بخش تراکنش ها میتونید اون رو دسته بندی کنید و راجع بهش بخونید ..) و عملیات تراکنش دیگر رو انجام میده ..

حالا که مفهموم deadlockرو فهمیدیم باید بدونیم چه کارهایی باید کنیم که deadlock صورت نگیره و در مرحله بعد اگر صورت گرفت چطور اون رو حل کنیم ..

یکسری کارا هست که اگر انجام بدید احتمال اینکه کمتر به deadlock بخورید بیشتر میشه:

  • نرمال سازی درست دیتابیس
  • توسعه نرم فزار به صورتی که دسترسی به آبجکت های دیتابیس با ترتیب درست صورت بگیره
  • کاربر اجازه وارد کردن دیتا در هنگام تراکنش را نداشته باشه
  • از دستور cursors استفاده نکنید
  • تراکنش ها رو تا جایی که امکان داره کوتاه در نظر بگیرید
  • تعداد بارهایی که یه دیتایی رو میخونید کم کنید. برای مثال در داخل یه پراسیجر به جای این که چن بار بخونید یکبار بخونیدش و در داخل متغیر یا جدول موقت یا .. بریزید
  • رفت آمد بین برنامه شما و دیتابیس هزینه بر است پس سعی کنید با استفاده از پراسیجر ها این کار رو به حداقل برسونید

تا اینجا میشه تیترهای کلی را گفتیم..

میشه گفت اولین توصیه یا بهتر بگیم پایه ای ترین توصیه که به برنامه نویسان SQL SERVER گفته میشه اینه که در بیشتر select هایی که میزنید دستور nolock داشته باشه ..

البته موضوعی که بالا گفتم یک مقدار ابهام داره(چون گفتم بیشتر select ها) حالا چه select هایی ؟ بستگی به شرایط داره و ان هم اینه که در سیستمی که میخوایم روش عملیات select رو بزنیم کدوم بدتره :

  • deadlock
  • wrong value

اگر برای سیستم شما در گزارش گیری عملیات deadlock مهم تر است که اتفاق نیافند پس حتما از nolock استفاده میکنیم اما اگر صحت اطلاعات اهمیت داره ترجیحا nolock نزنید. حالا اینکه کدوم برای شما مهم تره دیگه بستگی به ساختار دیتابیس و نیازمندی و شکل دیتا و حجم دیتاتون داره ..

اما اگر بخوام به صورت کلی بگم باید خدمتتون عرض کنم که در دیتابیس های مالی ( یا حتی جداول مالی) deadlock اصلا مفهوم و موضوع قابل قبولی نیست پس بهتره از nolock استفاده کنید.

تا ایتجا تکلیفمون با select و تراکنش ها مشخص شد حالا اگر پراسیجری داشته باشید که در داخل اون ممکن هست که کارهایی دیگه ای هم صورت بدیم ولی شک داریم یا میترسیم که اون تیکه کد به deadlock بخوره باید چه کار کنیم ؟ تیکه کد زیر دقیقا برای رفع این مشکل یا شک یا ترس هستش..


DECLARE @RetryNo Int = 1,@RetryMaxNo Int = 5;

WHILE @RetryNo < @RetryMaxNo

BEGIN

BEGIN TRY

--در این قسمت تیکه کدی که ممکن است دچار deadlock شود را مینویسیم ..

SELECT @RetryNo = @RetryMaxNo;

END TRY

BEGIN CATCH

IF ERROR_NUMBER() IN (1204, 1205, 1222)

BEGIN

SET @RetryNo += 1;

--در این قسمت 10 ثانیه صبر میکنیم و سپس سعی در انجام عملیات میکنیم..

WAITFOR DELAY '00:00:10';

END

ELSE

THROW;

END CATCH

END

دیتابیسبرنامه نویسیsqlserver
دانشجو،برنامه نویس
شاید از این پست‌ها خوشتان بیاید