این خرابی‌ای است که دو بار دیده‌ام، در دو موتور متفاوت. یک صادرات در ساعت 10:00 اجرا می‌شود و بالاترین مهر زمانی آخرین تغییر را که دیده ثبت می‌کند. یک تراکنش که در 09:58 آغاز شده هنوز باز است، در 10:03 کامیت می‌شود و مهری زمانی از لحظه آغازش دارد. صادرات بعدی فقط ردیف‌های تازه‌تر از 10:00 را می‌خواهد و هرگز آن را نمی‌بیند. اندازه انتقال عالی بود و داده اشتباه.

صادراتی را دنبال کنید که یک ردیف را از دست داد

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

هیچ چیز خطایی ثبت نمی‌کند، چون هیچ چیز شکست نخورده است. همین این دسته از باگ‌ها را گران می‌کند: خوراک دلتا سریع است، شمار ردیف‌ها معقول به نظر می‌رسد، و ردیف گم‌شده هفته‌ها بعد به شکل بلیت تطبیقی ظاهر می‌شود که هیچ‌کس نمی‌تواند بازتولیدش کند.

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

پنج وعده‌ای که خوراک باید بدهد

پیش از انتخاب انتقال، از سیستم مبدأ قراردادی با پنج بند بخواهید. اگر هر بندی نباشد، شما یک ابتکاری دارید نه خوراک تغییرات.

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

یک سازوکار پشتیبانی‌شده می‌تواند هر پنج را برآورده کند. مستندات SQL Server درباره ردیابی تغییرات یک نمونه منتشرشده مشخص است: نسخه معتبر کمینه را تعریف می‌کند، حذف‌ها را همراه تغییرات ثبت می‌کند و تراکنش عکس فوری را توصیف می‌کند که اعتبارسنجی، ثبت نسخه و پرس‌وجوهای تغییر مرتبط را در بر می‌گیرد. این نمونه‌ای از چیزی است که باید از مبدأ بخواهید، نه نحوی که در موتور دیگری بچسبانید.

نقطه بازرسی را بخشی از خط لوله طراحی کنید

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

cursor  = durable_checkpoint()          # last fully applied position
batch   = extract(cursor, upper_bound)  # one consistent batch
apply(batch)                            # idempotent at the target
commit()
checkpoint(batch.upper_bound)           # only now

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

حذف‌ها به ثبت نیاز دارند، نه به نتیجه‌گیری

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

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

سپس بسنجید که آیا دلتا ارزشش را داشت

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

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

مقالات مرتبط