Her er en feil jeg har sett skje to ganger, i to forskjellige motorer. En eksport kjører klokken 10:00 og registrerer det høyeste tidsstempelet for siste endring den så. Én transaksjon som begynte klokken 09:58 er fortsatt åpen, committer klokken 10:03 og bærer et tidsstempel fra da den startet. Den neste eksporten ber bare om rader nyere enn 10:00 og ser den aldri. Overføringsstørrelsen var utmerket, og dataene var feil.

Følg eksporten som mistet en rad

Følg rekkefølgen av hendelser i stedet for SQL-en. Applikasjonen skriver radens endringstid når transaksjonen begynner, ikke når den committer. Eksportøren leser et veggur-vannmerke mens transaksjonen fortsatt er åpen. Deretter committer transaksjonen med en endringstid som er eldre enn det lagrede vannmerket. Forbrukerens neste batch starter etter vannmerket, så raden ligger bak cursoren og vil aldri bli valgt igjen.

Ingenting logger en feil, fordi ingenting feilet. Det er dette som gjør denne feilklassen dyr: delta-feeden er rask, radantallet ser rimelig ut, og den manglende raden dukker opp uker senere som en avstemmingsbillett ingen kan gjenskape.

Sekvensnumre har samme form for feil av en annen grunn. En monoton ID forteller deg rekkefølgen verdiene ble tildelt i, ikke rekkefølgen transaksjonene committet i. En transaksjon som tok et lavt nummer kan committe etter en som tok et høyt nummer, så en cursor basert på tildelingsrekkefølge kan også etterlate et hull.

Fem løfter feeden må gi

Før du velger transport, be kildesystemet om en kontrakt med fem klausuler. Mangler noen klausul, har du en heuristikk og ikke en endringsfeed.

  • Dekning: innsettinger, oppdateringer og slettinger, hver med den stabile nøkkelen som trengs for å anvende den.
  • Grense: hva en cursorverdi betyr og hva en konsistent batch inneholder.
  • Konsistens: hvordan relaterte tabeller leses uten å blande inkompatible kildetilstander.
  • Oppbevaring: hvor lenge en frakoblet forbruker kan gjenoppta fra sin lagrede posisjon.
  • Reinitialisering: et støttet fullt øyeblikksbilde for når den posisjonen ikke lenger er gyldig.

En støttet mekanisme kan oppfylle alle fem. SQL Servers dokumentasjon om endringssporing er ett konkret publisert eksempel: den definerer en minste gyldig versjon, registrerer slettinger så vel som endringer og beskriver en øyeblikksbilde-transaksjon som spenner over validering, versjonsfangst og de relaterte endringsspørringene. Det er et eksempel på hva du bør kreve av en kilde, ikke syntaks du kan lime inn i en annen motor.

Design sjekkpunktet som en del av pipelinen

Forbrukerens lagrede posisjon er den egentlige tilstandsmaskinen, så skriv den som det. Cursoren kan bare avansere gjennom arbeidsflyten som allerede har anvendt batchen og committet måltransaksjonen.

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

Hvis leveringen feiler halvveis, avstem den samme batchen i stedet for å finne opp en ny kildeposisjon. Å trekke ut på nytt med en friskere øvre grense er måten en delvis anvendelse blir et permanent hull. Speilregelen gjelder også på den andre siden: idempotent anvendelse ved målet forhindrer duplikater og gjør ingenting for en endring som uttrekket aldri så.

Slettinger trenger registreringer, ikke konklusjoner

Å sammenligne rader som fortsatt finnes kan ikke fortelle en forbruker hvilke nøkler som forsvant. En kilde som aldri registrerer slettinger, lar deg sitte med to ufullkomne valg: holde en nøkkelhistorikk lenge nok til å diffe mot, eller kjøre en eksplisitt full avstemming etter en plan. Begge er designvalg med en kostnad, og ingen av dem finnes med mindre noen eier den.

Oppbevaring er samme slags beslutning. Hver støttet endringsfeed har et vindu; oppgi det i kontrakten og varsle når en forbrukers sjekkpunkt nærmer seg det. En forbruker som våkner etter et avbrudd på to uker, bør lese en tydelig feil "reinitialisering kreves" i stedet for stille å motta en delvis batch.

Mål deretter om deltaen var verdt det

Å falle tilbake på å sammenligne hver nøkkel og hash er noen ganger riktig, og det er verdt å vite hva det koster. Du overfører fortsatt informasjon om hver rad, hasher gir deg ikke et konsistent øyeblikksbilde på tvers av tabeller, og et hashskjema bringer sine egne spørsmål om representasjon og kollisjoner. Færre byte med en verifiserbar grense er målet; færre byte som stille slipper en committet endring er ikke noen delta i det hele tatt.

En kolonne for siste endring er et hint. En cursor som overlever en sen commit, en sletting og et langt avbrudd, er en kontrakt.

Relaterte artikler