انتقال میان‌پایگاهی زمانی که VPN قطع می‌شود از کار می‌افتد، و «دوباره اجرایش کن» یک طرح بازیابی نیست. استخراج از مبدأ ممکن است کامل شده باشد، مقصد ممکن است از قبل commit کرده باشد، یا پاسخ به‌سادگی در راه بازگشت گم شده باشد. این سه وضعیت به اقدام‌های متفاوتی نیاز دارند، و کلاینتی که تنها «خطا» را می‌شناسد نمی‌تواند آن‌ها را از هم تشخیص دهد.

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

پایگاه داده در واقع چه چیزی را تضمین می‌کند

SQL Server و Oracle هر دو اتمیک‌بودن را درون یک تراکنش فراهم می‌کنند. هیچ‌کدام اتمیک‌بودن میان آن دو را به شما نمی‌دهند. یک اتصال گمشده پایگاه داده را خراب نمی‌کند و بازگردانی دستی را هم تحمیل نمی‌کند، چون سرور تراکنش خودش را بدون شما حل می‌کند. چیزی که می‌شکند دانش فراخواننده از نتیجه است.

commit جداگانه یعنی commit جداگانه. VPNی که هر دو اتصال را حمل می‌کند دو commit را در یک واحد کار ادغام نمی‌کند.

commitی که هرگز درباره‌اش نشنیدید

یک حالت شکست منطق ساده‌لوحانه تلاش مجدد را مجازات می‌کند: سرور commit می‌کند و تأییدیه هرگز به فراخواننده نمی‌رسد. Oracle این را مسئله نتیجه ناشناخته مستند می‌کند و Transaction Guard را برای آن در مستندات تراکنش فراهم می‌کند. خطای ارتباطی شاهدی بر شکست یک commit ارسال‌شده نیست، و برخورد با آن به‌عنوان شاهد همان روشی است که یک دسته دو بار ارسال می‌شود. این تمایز بیشترین اهمیت را در مسیر تلاش مجدد دارد، جایی که اپراتور یک پیام خطا دارد و هیچ نشانه دیگری برای اقدام.

بنابراین گام بازیابی باید نتیجه را از مقصد بخواند، نه اینکه آن را از متن خطا استنتاج کند.

به انتقال یک هویت دسته بدهید

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

  1. استخراج یک دسته مبدأ شناسایی‌شده و تغییرناپذیر با شمای و مرز ثبت‌شده.
  2. انتقال آن به ناحیه آماده‌سازی مقصد و کشف محتوای ناقص یا متناقض پیش از اعلام آمادگی.
  3. اعمال آن بر اساس قواعد یکتایی یا قفل خود مقصد و ثبت تکمیل در همان تراکنش محلی.
  4. تطبیق نتیجه پایدار از طریق پروتکل پشتیبانی‌شده پیش از تأیید یا تلاش مجدد.

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

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

دسته را تصاحب کنید، سپس اعمال کنید

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

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

برای آن سریال‌سازی از سازوکار پشتیبانی‌شده پایگاه داده استفاده کنید، نه از حلقه بررسی-و-تکرار در کد برنامه.

چیزی که طراحی هنوز نمی‌تواند وعده دهد

آماده‌سازی کار را قابل‌راه‌اندازی مجدد می‌کند و وابستگی به یک نشست طولانی‌مدت را کاهش می‌دهد. اما commit اتمیک واحدی در سراسر SQL Server، Oracle و هر اثر جانبی خارجی که کار انجام می‌دهد ایجاد نمی‌کند. اگر کسب‌وکار واقعاً به آن نیاز دارد، یک تراکنش توزیع‌شده پشتیبانی‌شده یا فرایند تطبیق طراحی و واجد شرایط کنید، از جمله اینکه کار با نتیجه نامعلوم متعلق به کیست. هر چیزی ضعیف‌تر از آن جایگاهش در دستنامه تطبیق است، نه در کد انتقال.

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

مقالات مرتبط