حسین احمدی
بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

کاربرد NoLock و ReadPast در SQL Server چیست؟

زمانی که شما در کوئری های SQL Server اقدام به خواندن یا تغییر اطلاعات می کنید، SQL Server از یک مکانیزم کنترلی به نام Lock استفاده می کند تا از صحت داده ها در بانک اطلاعاتی و خروجی نمایش داده شده اطمینان حاصل کند. در حقیقت کار Lock اطمینان از این است که رکورد های درگیر در یک Transaction نمی توانند توسط یک transaction دیگر تغییر کنند تا زمانی که در transaction اول عملیات commit انجام شود.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
سرفصل های این مطلب
  1. کاربرد NOLOCK
  2. کاربرد READPAST

اما ممکن است در برخی مواقع نیاز باشد که نحوه lock را در جداول به صورت دستی مدیریت کنیم، زیرا این کار به صورت پیش فرض توسط SQL Server انجام می شود و در اکثر مواقع نیازی به دخالت ما نیست. برای اینکار باید با مفهومی به نام Table Hints آشنا شویم که این کار را برای ما انجام می دهند. در این مطلب قصد داریم تا با دو Table Hint به نام های NOLOCK و READPAST آشنا شویم. در این مطلب از یک جدول نمونه برای اینکار استفاده می کنیم. برای تست کوئری های این مطلب جدول زیر را در یک بانک دلخواه ایجاد کنید:

CREATE TABLE [dbo].[Customers](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nvarchar](max) NULL,
	[LastName] [nvarchar](max) NULL,
	[Email] [nvarchar](max) NULL,
 CONSTRAINT [PK_dbo.Customers] 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] TEXTIMAGE_ON [PRIMARY]

GO

کاربرد NOLOCK

کاربرد NOLOCK یا با نام دیگر READUNCOMMITED تنها بر روی عبارات SELECT قابل استفاده است. بوسیله NOLOCK می توانیم در زمان باز بودن یک Transaction به رکورد های درگیر در یک Transaction که هنوز عملیات Commit بر روی آن انجام نشده دسترسی داشته باشیم. برای مثال، Transaction زیر را در نظر بگیرید که داخل آن یک رکورد را درج می کنیم، اما عملیات Commit را انجام نمی دهیم:

BEGIN TRANSACTION
	INSERT INTO Customers VALUES (N'Hossein',N'Ahmadi',N'address@company.com')
	COMMIT

بعد از اجرای Transaction بالا، یک پنجره کوئری جدید باز کرده و کوئری زیر را بر روی جدول Customers اجرا می کنیم:

select count(*) from Customers

خروجی ما عدد 0 خواهد بود، زیرا هنوز Transaction ما COMMIT نشده است، همان کوئری بالا را به صورت زیر اجرا می کنیم:

select count(*) from Customers with(nolock)

این بار کوئری ما خروجی 1 را بر میگرداند، زیرا بوسیله nolock گفتیم رکوردهای درگیر transaction ها که عملیات lock بر روی آن ها اعمال شده را نیز در نظر بگیر. حال کافیست دستور زیر را بر گرداندن Transaction اجرا کنیم:

rollback transaction

در صورت اجرای کوئری select که شامل nolock بود، خروجی ما 0 خواهد بود، زیرا transaction را rollback کردیم.یکی از مزیت های استفاده از nolock این است که می توان database engine را از عملیات lock باز داشت که این باعث بالا رفتن Performance کوئری می شود و از طرفی به دلیل در نظر گرفتن رکورد های نامطئن در کوئری در نظر گرفته شود.

کاربرد READPAST

کاربرد READPAST در زمانی است که می خواهیم هیچ رکورد Lock شده ای در نتایج کوئری نمایش داده نشود! برای درک این مطلب رکوردی به صورت زیر در جدول Customers درج می کنیم:

INSERT INTO Customers VALUES (N'Hossein',N'Ahmadi',N'address@company.com')

کوئری زیر را اجرا می کنیم:

select count(*) from Customers

خروجی ما عدد 1 می باشد که نشان می دهد یک رکورد در جدول درج شده است. حال Transaction زیر که رکورد موجود در جدول Customers را به روز رسانی می کند را اجرا می کنیم:

BEGIN TRANSACTION
	update Customers set LastName = N'nasiri' where LastName = N'Ahmadi'

بعد از اجرای دستورات بالا، در یک پنجره کوئری جدید کوئری زیر را اجرا می کنیم:

select count(*) from Customers

خروجی ما عدد 1 می باشد، در صورتی که رکورد موجود در جدول در Transaction باز استفاده شده است. حال مجدد کوئری بالا را بوسیله READPAST اجرا می کنیم:

select count(*) from Customers with(readpast,updlock,rowlock)

این بار تعداد رکورد های ما 0 می باشد، زیرا بوسیله readpast گفتیم رکورد هایی که در transaction درگیر هستند را در نظر نگیر، اما در صورت rollback کردن یا commit کردن transaction مجدد عدد 1 برای ما برگردانده می شود. مزیت استفاده از readpast این است که عملیات lock در زمان اجرای کوئری اعمال نشده و همچنین رکورد هایی که در حال به روز رسانی یا حذف یا ... هستند در کوئری نمایش داده نمی شوند، حتی در صورتی که commit اعمال نشده باشد، از معایب استفاده از readpast هم می توان به این مورد اشاره کرد که ممکن است در نتیجه نهایی رکورد های lock شده در نظر گرفته نمی شوند و نمی شود زیاد بر روی خروجی کوئری اطمینان کرد.


حسین احمدی
حسین احمدی

بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ...

نظرات