جداسازی و سریال‌سازی تراکنش

این صفحه رقابت داده‌های تراکنشی، سریال‌پذیری، و جداسازی را شرح می‌دهد. برای نمونه‌های کد تراکنش، تراکنش‌ها و نوشتن‌های دسته‌ای را ببینید.

تراکنش‌ها و رقابت داده‌ها

برای اینکه تراکنش موفقیت‌آمیز باشد، اسناد بازیابی‌شده توسط عملیات خواندن آن باید توسط عملیات خارج از تراکنش بدون تغییر باقی بماند. اگر عملیات دیگری تلاش کند یکی از آن اسناد را تغییر دهد، آن عملیات با تراکنش وارد حالت رقابت داده می‌شود.

رقابت داده‌ها
وقتی دو یا چند عملیات برای کنترل یک سند با هم رقابت می‌کنند. برای مثال، یک تراکنش ممکن است نیاز داشته باشد که یک سند ثابت بماند درحالی‌که یک عملیات هم‌زمان تلاش می‌کند مقادیر فیلد آن سند را به‌روز کند.

Cloud Firestore با به‌تأخیر انداختن یا ناموفق کردن یکی از عملیات‌ها، مشکل رقابت داده را حل می‌کند. کتابخانه‌های مشتری Cloud Firestore تراکنش‌هایی را که به‌دلیل رقابت داده‌ها ناموفق بوده‌اند به‌طور خودکار دوباره امتحان می‌کنند. پس‌از تعداد محدودی تلاش مجدد، عملیات تراکنش ناموفق می‌شود و پیام خطا برمی‌گرداند:

ABORTED: Too much contention on these documents. Please try again.

هنگام تصمیم‌گیری درباره اینکه کدام عملیات ناموفق باشد یا به‌تأخیر بیفتد، رفتار به نوع کنترل‌های هم‌زمانی بستگی دارد.

کنترل‌های همزمانی

حالت همزمانی یک گزینه پایگاه داده قابل‌پیکربندی است. ‫Cloud Firestore از حالت‌های هم‌زمانی زیر پشتیبانی می‌کند:

  • PESSIMISTIC: کنترل‌های همزمانی بدبینانه فرض می‌کنند که احتمال رقابت داده‌ها وجود دارد. تراکنش‌های بدبینانه از قفل‌های پایگاه داده برای جلوگیری از تغییر داده‌ها توسط عملیات دیگر استفاده می‌کنند.

    با کنترل‌های همزمانی بدبینانه، تراکنش‌ها روی اسنادی که می‌خوانند قفل می‌گذارند. قفل تراکنش روی سند، تراکنش‌های دیگر، نوشتن‌های دسته‌ای، و نوشتن‌های غیرتراکنشی را از تغییر آن سند مسدود می‌کند. تراکنش قفل‌های سند را در زمان ثبت آزاد می‌کند. همچنین اگر زمانش تمام شود یا به هر دلیلی ناموفق باشد، قفل‌هایش را آزاد می‌کند.

    وقتی تراکنشی سندی را قفل می‌کند، سایر عملیات نوشتن باید منتظر بمانند تا تراکنش قفل خود را آزاد کند. تراکنش‌ها قفل‌هایشان را به‌ترتیب زمانی دریافت می‌کنند.

  • OPTIMISTIC: کنترل‌های همزمانی خوش‌بینانه فرض می‌کنند که رقابت داده‌ها محتمل نیست یا اینکه نگه‌داشتن قفل‌های پایگاه داده کارآمد نیست. تراکنش‌های خوش‌بینانه از قفل‌های پایگاه داده برای مسدود کردن سایر عملیات از تغییر داده‌ها استفاده نمی‌کنند

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

پیش‌فرض‌های حالت هم‌رس‌ها

پیش‌فرض برای نسخه Standard PESSIMISTIC است. پیش‌فرض برای نسخه Enterprise‏ OPTIMISTIC است. اما این رفتار به نوع کتابخانه کارخواه نیز بستگی دارد:

  • کیت‌های توسعه نرم‌افزار تلفن همراه / وب از کنترل‌های هم‌زمانی خوش‌بینانه استفاده می‌کنند. کیت‌های توسعه نرم‌افزار وب و تلفن همراه مستقل از این تنظیم رفتار می‌کنند زیرا همیشه همزمانی خوش‌بینانه را شبیه‌سازی می‌کنند.
  • کتابخانه‌های کارخواه سرور از کنترل‌های همزمانی تنظیمات پایگاه داده استفاده می‌کنند.

حالت همزمانی نما

فرمان gcloud firestore databases describe را اجرا کنید تا حالت همزمانی سمت سرور پایگاه داده‌تان را مشاهده کنید:

gcloud firestore databases describe \
  --project=PROJECT_ID \
  --database=DATABASE_ID

تغییر حالت همزمانی

فرمان gcloud firestore databases update را اجرا کنید تا حالت همزمانی سمت سرور پایگاه داده‌تان را تغییر دهید:

gcloud firestore databases update \
  --project=PROJECT_ID \
  --database=DATABASE_ID \
  --concurrency-mode=CONCURRENCY_MODE

مکان:

  • ‫CONCURRENCY_MODE PESSIMISTIC یا OPTIMISTIC است.
  • PROJECT_ID شناسه پروژه Google Cloud شما است.
  • ‫DATABASE_ID شناسه پایگاه داده Cloud Firestore شما است.

رقابت داده در کیت‌های توسعه نرم‌افزار تلفن همراه/وب

کیت‌های توسعه نرم‌افزار وب و تلفن همراه تراکنش‌های همزمانی خوش‌بینانه را بااستفاده از پیش‌شرط‌های نوشتن در نسخه‌های سند شبیه‌سازی می‌کنند. این شبیه‌سازی بدون درنظر گرفتن تنظیم حالت همزمانی پایگاه داده رخ می‌دهد. کیت‌های توسعه نرم‌افزار وب و تلفن همراه از ویژگی تراکنش‌های داخلی استفاده نمی‌کنند، بنابراین حتی اگر حالت همزمانی پایگاه داده برای PESSIMISTIC پیکربندی شده باشد، کارخواه‌های تلفن همراه همچنان به‌صورت خوش‌بینانه رفتار می‌کنند.

کیت‌های توسعه نرم‌افزار وب/تلفن همراه از کنترل‌های همزمانی خوش‌بینانه استفاده می‌کنند، زیرا می‌توانند در محیط‌هایی با تأخیر بالا و اتصال شبکه غیرقابل‌اعتماد کار کنند. قفل کردن اسناد در محیطی با تأخیر بالا باعث ایجاد خطاهای زیادی در رقابت داده‌ها می‌شود.

رقابت داده‌ها در کتابخانه‌های کارخواه سرور

کتابخانه‌های کارخواه سرور (C#‎،‏ Go،‏ Java،‏ Node.js،‏ PHP،‏ Python،‏ Ruby) از ویژگی تراکنش‌های داخلی استفاده می‌کنند. این تراکنش‌ها از تنظیم حالت همزمانی سطح پایگاه داده استفاده می‌کنند و پیش‌فرض به نسخه بستگی دارد:

  • نسخه Enterprise به‌طور پیش‌فرض از کنترل‌های همزمانی خوش‌بینانه برای پشتیبانی از عملیاتی که کل مجموعه‌ها را اسکن می‌کنند استفاده می‌کند. کنترل‌های همزمانی خوش‌بینانه به جلوگیری از عملیات اسکن که تعداد زیادی سند را قفل می‌کند کمک می‌کند.

  • نسخه استاندارد از کنترل‌های همزمانی بدبینانه استفاده می‌کند و تأخیر کم و اتصال مطمئن به پایگاه داده را فرض می‌کند.

جداسازی سریال‌سازی‌شدنی

رقابت داده‌ها بین تراکنش‌ها ارتباط نزدیکی با سطوح جداسازی پایگاه داده دارد. سطح جداسازی پایگاه داده نشان می‌دهد که سیستم چقدر خوب تداخل‌های بین عملیات هم‌زمان را مدیریت می‌کند. تداخل ناشی از الزامات پایگاه داده زیر است:

  • تراکنش‌ها به داده‌های دقیق و یکپارچه نیاز دارند.
  • برای استفاده کارآمد از منابع، پایگاه‌های داده عملیات را به‌طور هم‌زمان اجرا می‌کنند.

در سیستم‌هایی با سطح جداسازی پایین، عملیات خواندن در یک تراکنش ممکن است داده‌های نادرست را از تغییرات تأییدنشده در یک عملیات هم‌زمان بخواند.

جداسازی سریال‌سازی بالاترین سطح جداسازی را تعریف می‌کند. جداسازی سریال‌سازی یعنی:

  • می‌توانید فرض کنید که پایگاه داده تراکنش‌ها را به‌صورت سری اجرا می‌کند.
  • تراکنش‌ها تحت تأثیر تغییرات تأییدنشده در عملیات هم‌زمان قرار نمی‌گیرند.

این تضمین باید حتی زمانی که پایگاه داده چندین تراکنش را به‌طور موازی اجرا می‌کند، برقرار باشد. پایگاه داده باید کنترل‌های همزمانی را برای حل تعارض‌هایی که این تضمین را نقض می‌کنند اجرا کند.

‫Cloud Firestore جداسازی سریال‌سازی تراکنش‌ها را تضمین می‌کند. تراکنش‌ها در Cloud Firestore سریالی و براساس زمان ثبت جدا می‌شوند.

جداسازی سریال‌سازی براساس زمان ثبت

Cloud Firestore به هر تراکنش یک زمان ثبت اختصاص می‌دهد که نشان‌دهنده یک نقطه زمانی واحد است. وقتی Cloud Firestore تغییرات تراکنش را به پایگاه داده ارسال می‌کند، می‌توانید فرض کنید که همه خواندن‌ها و نوشتن‌ها در تراکنش دقیقاً در زمان ارسال انجام می‌شوند.

اجرای واقعی تراکنش به مدتی زمان نیاز دارد. اجرای تراکنش قبل‌از زمان ثبت شروع می‌شود و اجرای چند عملیات ممکن است هم‌پوشانی داشته باشد. Cloud Firestore از جداسازی سریال‌سازی‌شده پشتیبانی می‌کند و تضمین می‌کند که:

  • ‫Cloud Firestore تراکنش‌ها را به‌ترتیب زمان ثبت، ثبت می‌کند.
  • ‫Cloud Firestore تراکنش‌ها را از عملیات هم‌زمان با زمان ثبت بعدی جدا می‌کند.

درصورت وجود رقابت داده بین عملیات هم‌زمان، Cloud Firestore از کنترل‌های هم‌زمانی خوش‌بینانه و بدبینانه برای حل رقابت استفاده می‌کند.

جداسازی در تراکنش

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

مشکلات مربوط به رقابت داده‌ها

برای اطلاعات بیشتر درباره تداخل داده‌ها و نحوه حل‌وفصل آن‌ها، صفحه عیب‌یابی را بررسی کنید.