بازگشت به لیست مقالات

ایزولاسیون تراکنش‌ها در ASP.NET Core

IsolationTransactio asp.ner core markdown امتیاز: 8/100 مفید تأیید شده

ایزولاسیون تراکنش‌ها در ASP.NET Core

مقدمه

مدیریت تراکنش‌ها و کنترل سطح ایزولاسیون (Isolation Level) یکی از مهم‌ترین مباحث در توسعه برنامه‌های مبتنی بر پایگاه داده با ASP.NET Core است. انتخاب صحیح سطح ایزولاسیون می‌تواند تعادل مناسبی بین یکپارچگی داده‌ها و عملکرد سیستم ایجاد کند. در این مقاله به بررسی مفهوم ایزولاسیون، سطوح مختلف آن، روش‌های پیاده‌سازی در ASP.NET Core (با استفاده از EF Core و ADO.NET) و نکات کاربردی می‌پردازیم.

مفهوم تراکنش و Isolation

تراکنش (Transaction) یک واحد منطقی از کار است که شامل یک یا چند عملیات روی پایگاه داده می‌شود و باید به صورت اتمیک (Atomic) اجرا شود؛ یعنی یا همه عملیات با موفقیت انجام شوند یا هیچ‌کدام. ویژگی‌های ACID (Atomicity, Consistency, Isolation, Durability) چهار اصل بنیادین تراکنش‌ها هستند. ایزولاسیون (Isolation) مشخص می‌کند که تغییرات ایجاد شده توسط یک تراکنش، چگونه و از چه زمانی برای سایر تراکنش‌های هم‌زمان قابل مشاهده است.

درک صحیح سطوح ایزولاسیون به توسعه‌دهنده کمک می‌کند تا از بروز مشکلات رایج هم‌زمانی مانند Dirty Read، Non-Repeatable Read و Phantom Read جلوگیری کند.

سطوح ایزولاسیون (Isolation Levels)

در SQL Server و اکثر پایگاه‌های داده رابطه‌ای، پنج سطح استاندارد ایزولاسیون وجود دارد:

سطح ایزولاسیون Dirty Read Non-Repeatable Read Phantom Read
Read Uncommitted ممکن است ممکن است ممکن است
Read Committed جلوگیری می‌شود ممکن است ممکن است
Repeatable Read جلوگیری می‌شود جلوگیری می‌شود ممکن است
Serializable جلوگیری می‌شود جلوگیری می‌شود جلوگیری می‌شود
Snapshot جلوگیری می‌شود جلوگیری می‌شود جلوگیری می‌شود

توضیح مشکلات هم‌زمانی

  • Dirty Read: خواندن داده‌ای که توسط تراکنش دیگری تغییر کرده اما هنوز commit نشده است.
  • Non-Repeatable Read: اگر یک تراکنش یک ردیف را دو بار بخواند و بین این دو خواندن، تراکنش دیگری آن را تغییر داده و commit کرده باشد، مقادیر متفاوتی مشاهده می‌شود.
  • Phantom Read: وقتی یک تراکنش مجموعه‌ای از ردیف‌ها را با یک شرط خاص می‌خواند و تراکنش دیگری ردیف‌هایی را اضافه یا حذف می‌کند که شرط را برآورده می‌کنند، در خواندن مجدد، ردیف‌های جدیدی ظاهر می‌شوند.

روش‌های پیاده‌سازی تراکنش در ASP.NET Core

استفاده از EF Core

Entity Framework Core (EF Core) به عنوان ORM محبوب در ASP.NET Core، امکانات قدرتمندی برای کار با تراکنش‌ها ارائه می‌دهد. برای شروع یک تراکنش با سطح ایزولاسیون مشخص، از متد BeginTransaction روی DbContext.Database استفاده می‌کنیم.

using (var context = new ApplicationDbContext())
{
    using (var transaction = await context.Database.BeginTransactionAsync(IsolationLevel.Serializable))
    {
        try
        {
            // عملیات اول
            var product = await context.Products.FindAsync(1);
            product.Stock -= 10;
            await context.SaveChangesAsync();

            // عملیات دوم
            context.Orders.Add(new Order { ProductId = 1, Quantity = 10 });
            await context.SaveChangesAsync();

            await transaction.CommitAsync();
        }
        catch (Exception)
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}

نکات مهم در EF Core

  • سطح پیش‌فرض ایزولاسیون در SQL Server معمولاً ReadCommitted است.
  • برای استفاده از IsolationLevel.Snapshot باید ابتدا گزینه ALLOW_SNAPSHOT_ISOLATION را در پایگاه داده فعال کنید.
  • در EF Core 6 به بعد می‌توانید از تراکنش‌های ضمنی با ExecutionStrategy برای مدیریت خطاهای گذرا استفاده کنید.

استفاده از ADO.NET

اگر به کنترل بیشتری روی تراکنش نیاز دارید یا از EF Core استفاده نمی‌کنید، می‌توانید از کلاس‌های ADO.NET مانند SqlConnection و SqlTransaction استفاده کنید.

using (var connection = new SqlConnection(connectionString))
{
    await connection.OpenAsync();
    using (var transaction = connection.BeginTransaction(IsolationLevel.RepeatableRead))
    {
        try
        {
            var command1 = new SqlCommand("UPDATE Products SET Stock = Stock - 10 WHERE Id = 1", connection, transaction);
            await command1.ExecuteNonQueryAsync();

            var command2 = new SqlCommand("INSERT INTO Orders (ProductId, Quantity) VALUES (1, 10)", connection, transaction);
            await command2.ExecuteNonQueryAsync();

            await transaction.CommitAsync();
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}

مقایسه سطوح ایزولاسیون

انتخاب سطح مناسب به نیازمندی‌های برنامه بستگی دارد:

  • Read Uncommitted: بالاترین کارایی، اما ریسک بالای خواندن داده‌های ناپایدار. فقط در سناریوهایی مانند گزارش‌گیری که دقت کم‌اهمیت است، استفاده شود.
  • Read Committed: پیش‌فرض اکثر سیستم‌ها. از Dirty Read جلوگیری می‌کند و برای اکثر کاربردهای عمومی مناسب است.
  • Repeatable Read: برای مواقعی که نیاز است یک تراکنش داده‌های یکسانی را در طول اجرای خود ببیند. قفل‌های بیشتری نگه می‌دارد و می‌تواند باعث کاهش هم‌زمانی شود.
  • Serializable: قوی‌ترین سطح ایزولاسیون که تمام مشکلات هم‌زمانی را برطرف می‌کند، اما هزینه بالایی از نظر قفل‌گذاری و احتمال بن‌بست دارد.
  • Snapshot: از نسخه‌های قبلی ردیف‌ها در tempdb استفاده می‌کند و بدون قفل‌گذاری طولانی، ایزولاسیون قوی فراهم می‌کند. مناسب برای برنامه‌های با خواندن زیاد و نوشتن کم.

نکات مهم و سناریوهای استفاده

  • سیستم‌های بانکی و مالی: معمولاً از Serializable یا Snapshot برای جلوگیری از هرگونه ناسازگاری استفاده می‌کنند.
  • فروشگاه‌های آنلاین با ترافیک بالا: بهتر است از ReadCommitted یا Snapshot استفاده شود تا هم‌زمانی حفظ شود.
  • گزارش‌گیری تحلیلی: گاهی ReadUncommitted با احتیاط قابل قبول است، اما Snapshot گزینه امن‌تری است.
  • مدیریت بن‌بست (Deadlock): سطوح ایزولاسیون بالاتر احتمال بن‌بست را افزایش می‌دهند. همیشه سعی کنید تراکنش‌ها را کوتاه نگه دارید و ترتیب دسترسی به منابع را یکسان کنید.
  • آزمایش و پایش: قبل از استقرار نهایی، سطح ایزولاسیون را تحت بار واقعی آزمایش کنید و با ابزارهایی مانند SQL Profiler یا Extended Events رفتار قفل‌ها را بررسی کنید.

جمع‌بندی

ایزولاسیون تراکنش‌ها یکی از ارکان اصلی یکپارچگی داده‌ها در برنامه‌های ASP.NET Core است. با شناخت دقیق سطوح مختلف و انتخاب آگاهانه آن‌ها بر اساس نیازمندی‌های کسب‌وکار، می‌توانید هم از صحت داده‌ها اطمینان حاصل کنید و هم عملکرد سیستم را در سطح مطلوب نگه دارید. استفاده از EF Core یا ADO.NET هر دو امکان کنترل کامل سطح ایزولاسیون را فراهم می‌کنند، اما توصیه می‌شود در پروژه‌های واقعی ابتدا با سطح پیش‌فرض شروع کرده و در صورت نیاز به تدریج به سطوح قوی‌تر حرکت کنید.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.