Jen fiasko, kiun mi vidis okazi dufoje, en du malsamaj motoroj. Eksporto ruliĝas je 10:00 kaj registras la plej altan lastmodifitan tempostampon, kiun ĝi vidis. Unu transakcio, kiu komenciĝis je 09:58, estas ankoraŭ malfermita, commitiĝas je 10:03 kaj portas tempostampon el la momento de sia komenco. La sekva eksporto petas nur vicojn pli novajn ol 10:00 kaj neniam vidas ĝin. La transiga grando estis bonega kaj la datumoj malĝustaj.

Sekvu la eksporton, kiu perdis vicon

Spuru la ordon de la eventoj anstataŭ la SQL-on. La aplikaĵo skribas la modifan tempon de la vico kiam la transakcio komenciĝas, ne kiam ĝi commitiĝas. La eksportilo legas murhorloĝan akvomarkon dum tiu transakcio estas ankoraŭ malfermita. Poste la transakcio commitiĝas kun modifa tempo pli malnova ol la konservita akvomarko. La sekva aro de la konsumanto komenciĝas post la akvomarko, do la vico restas malantaŭ la kursoro kaj neniam plu estos elektita.

Nenio registras eraron, ĉar nenio fiaskis. Tio faras ĉi tiun klason de cimoj multekosta: la delta-fluo estas rapida, la vickalkuloj ŝajnas kredindaj, kaj la mankanta vico aperas semajnojn poste kiel egaliga bileto, kiun neniu povas reprodukti.

Sekvencaj numeroj havas la saman formon de difekto pro alia kialo. Monotona ID diras al vi la ordon, en kiu valoroj estis asignitaj, ne la ordon, en kiu transakcioj commitiĝis. Transakcio, kiu prenis malaltan numeron, povas commitiĝi post tiu, kiu prenis altan, do kursoro bazita sur asignordo ankaŭ povas lasi truon.

Kvin promesoj, kiujn la fluo devas plenumi

Antaŭ ol elekti transporton, petu de la fonta sistemo kontrakton kun kvin kondiĉoj. Se iu kondiĉo mankas, vi havas heŭristikon, ne fluon de ŝanĝoj.

  • Kovro: enmetoj, ĝisdatigoj kaj forigoj, ĉiu kun la stabila ŝlosilo necesa por apliki ĝin.
  • Limo: kion signifas kursora valoro kaj kion enhavas kohera aro.
  • Kohereco: kiel rilataj tabeloj estas legitaj sen miksi nekongruajn fontajn statojn.
  • Reteno: kiom longe malkonektita konsumanto povas rekomenci de sia konservita pozicio.
  • Rekomencigo: subtenata plena momenta kopio por kiam tiu pozicio ne plu validas.

Subtenata mekanismo povas plenumi ĉiujn kvin. La dokumentaro de SQL Server pri ŝanĝa spurkonstato estas unu konkreta publikigita ekzemplo: ĝi difinas minimuman validan version, registras forigojn same kiel ŝanĝojn, kaj priskribas momentan transakcion, kiu kovras validigon, versionregistradon kaj la rilatajn ŝanĝdemandojn. Ĝi estas ekzemplo de tio, kion postuli de fonto, ne sintakso, kiun vi povas enmeti en alian motoron.

Projektu la kontrolpunkton kiel parton de la ĉenfaro

La konservita pozicio de la konsumanto estas la efektiva statomaŝino, do skribu ĝin kiel tian. La kursoro rajtas antaŭeniĝi nur per la laborfluo, kiu jam aplikis la aron kaj commitigis la celan transakcion.

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

Se liverado fiaskas duonvoje, egaligu tiun saman aron anstataŭ elpensi novan fontan pozicion. Reeltiri kun pli freŝa supra limo estas kiel parta aplikado fariĝas daŭra breĉo. La spegula regulo validas ankaŭ aliflanke: idempota aplikado ĉe la celo malhelpas duplikatojn kaj faras nenion por ŝanĝo, kiun la eltiro neniam vidis.

Forigoj bezonas registrojn, ne konkludojn

Kompari vicojn, kiuj ankoraŭ ekzistas, ne povas diri al konsumanto, kiuj ŝlosiloj malaperis. Fonto, kiu neniam registras forigojn, lasas al vi du neperfektajn eblojn: teni ŝlosilan historion sufiĉe longe por diff aŭ ruli eksplicitan plenan egaligon laŭ horaro. Ambaŭ estas projektaj decidoj kun kosto, kaj neniu ekzistas krom se iu posedas ĝin.

Reteno estas la sama speco de decido. Ĉiu subtenata ŝanĝfluo havas fenestron; deklaru ĝin en la kontrakto kaj avertu, kiam la kontrolpunkto de konsumanto alproksimiĝas al ĝi. Konsumanto, kiu vekiĝas post du-semajna interrompo, devus legi klaran eraron "rekomencigo necesas" anstataŭ silente ricevi partan aron.

Poste mezuru, ĉu la delta indis la penon

Reiri al komparado de ĉiu ŝlosilo kaj haketaĵo foje estas ĝuste, kaj indas scii, kiom ĝi kostas. Vi ankoraŭ transdonas informojn pri ĉiu vico, haketaĵoj ne donas al vi koheran momentan kopion trans tabeloj, kaj haketa skemo alportas proprajn demandojn pri reprezentado kaj kolizioj. Malpli da bajtoj kun kontrolebla limo estas la celo; malpli da bajtoj, kiuj silente perdas commititan ŝanĝon, tute ne estas delta.

Kolumno de lasta modifo estas signo. Kursoro, kiu postvivas malfruan commiton, forigon kaj longan interrompon, estas kontrakto.

Rilataj artikoloj