Rrjedha jote delta humb commit-et e vonuara: ndërto një kursor të besueshëm
Një rresht mbërriti vonë sepse shenja e ujit nuk ishte kufi commit-i. Ndiqu dështimin, pastaj përcakto mbulimin, kufirin, mbajtjen dhe një rifillim të sigurt.
Ja një dështim që e kam parë dy herë, në dy motorë të ndryshëm. Një eksport ekzekutohet në 10:00 dhe regjistron vulën kohore më të lartë të modifikimit të fundit që pa. Një transaksion që filloi në 09:58 është ende i hapur, bën commit në 10:03 dhe mban një vulë kohore nga momenti kur filloi. Eksporti i radhës kërkon vetëm rreshta më të reja se 10:00 dhe nuk e sheh kurrë. Madhësia e transferimit ishte e shkëlqyer dhe të dhënat ishin të gabuara.
Ndiqe eksportin që humbi një rresht
Ndiqe rendin e ngjarjeve, jo SQL-në. Aplikacioni shkruan kohën e modifikimit të rreshtit kur transaksioni fillon, jo kur bën commit. Eksportuesi lexon një shenjë uji me orë muri ndërsa transaksioni është ende i hapur. Pastaj transaksioni bën commit me një kohë modifikimi më të vjetër se shenja e ujit e ruajtur. Grupi i radhës i konsumatorit fillon pas shenjës së ujit, kështu që rreshti mbetet pas kursorit dhe nuk do të zgjidhet kurrë më.
Asgjë nuk regjistron një gabim, sepse asgjë nuk dështoi. Kjo është ajo që e bën këtë klasë defektesh të kushtueshme: rrjedha delta është e shpejtë, numrat e rreshtave duken të besueshëm dhe rreshti që mungon del javë më vonë si një biletë rakordimi që askush nuk mund ta riprodhojë.
Numrat e sekuencës kanë të njëjtën formë defekti për një arsye tjetër. Një ID monotonik të tregon rendin e alokimit të vlerave, jo rendin e commit-imit të transaksioneve. Një transaksion që mori një numër të ulët mund të bëjë commit pas një që mori një numër të lartë, prandaj një kursor i bazuar në rendin e alokimit mund të lërë gjithashtu një vrimë.
Pesë premtime që rrjedha duhet të mbajë
Para se të zgjidhni një transport, kërkoni nga sistemi burim një kontratë me pesë klauzola. Nëse mungon ndonjë klauzolë, keni një heuristikë dhe jo një rrjedhë ndryshimesh.
- Mbulimi: futjet, përditësimet dhe fshirjet, secila me çelësin e qëndrueshëm të nevojshëm për ta aplikuar.
- Kufiri: çfarë do të thotë një vlerë kursori dhe çfarë përmban një grup konsistent.
- Konsistenca: si lexohen tabelat e lidhura pa përzier gjendje burimi të papajtueshme.
- Mbajtja: sa kohë mund të vazhdojë një konsumator i shkëputur nga pozicioni i ruajtur.
- Rifillimi: një snapshot i plotë i mbështetur kur ai pozicion nuk është më i vlefshëm.
Një mekanizëm i mbështetur mund t'i plotësojë të pesë. Dokumentacioni i SQL Server për gjurmimin e ndryshimeve është një shembull konkret i botuar: përcakton një version minimal të vlefshëm, regjistron fshirjet si dhe ndryshimet dhe përshkruan një transaksion snapshot që përfshin validimin, kapjen e versionit dhe pyetjet e ndryshimeve të lidhura. Është një shembull i asaj që duhet të kërkoni nga një burim, jo sintaksë që ngjitni në një motor tjetër.
Projekto pikën e kontrollit si pjesë e pipeline-it
Pozicioni i ruajtur i konsumatorit është makina e vërtetë e gjendjeve, prandaj shkruaje si të tillë. Kursori mund të përparojë vetëm përmes rrjedhës së punës që e ka aplikuar tashmë grupin dhe ka bërë commit transaksionin e synuar.
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
Nëse dorëzimi dështon në gjysmë të rrugës, rakordo të njëjtin grup në vend që të shpikësh një pozicion të re burimi. Riekstraktimi me një kufi të sipërm më të freskët është rruga me të cilën një aplikim i pjesshëm bëhet një boshllëk i përhershëm. Rregulli i pasqyrës vlen edhe në anën tjetër: aplikimi idempotent në destinacion parandalon dublikatat dhe nuk bën asgjë për një ndryshim që ekstraktimi nuk e pa kurrë.
Fshirjet kërkojnë regjistrime, jo përfundime
Krahasimi i rreshtave që ekzistojnë ende nuk mund t'i tregojë konsumatorit cilët çelësa u zhdukën. Një burim që nuk regjistron kurrë fshirjet të lë dy opsione të papërsosura: të mbash një histori çelësash mjaft të gjatë për diff, ose të ekzekutosh një rakordim të plotë eksplicit sipas një plani. Të dyja janë vendime projektimi me kosto dhe asnjëra nuk ekziston nëse askush nuk e zotëron.
Mbajtja është i njëjti lloj vendimi. Çdo rrjedhë ndryshimesh e mbështetur ka një dritare; deklaroje në kontratë dhe paralajmëro kur pika e kontrollit e një konsumatori i afrohet. Një konsumator që zgjohet pas një ndërprerjeje dy javësh duhet të lexojë një gabim të qartë "kërkohet rifillim" në vend që të marrë në heshtje një grup të pjesshëm.
Pastaj mat nëse delta ia vlejti
Kthimi te krahasimi i çdo çelësi dhe hash-i është ndonjëherë i saktë dhe ia vlen të dish sa kushton. Ju ende transferoni informacion për çdo rresht, hash-et nuk ju japin një snapshot konsistent mes tabelave dhe një skemë hash sjell pyetjet e veta për paraqitjen dhe përplasjet. Më pak bajt me një kufi të verifikueshëm është qëllimi; më pak bajt që në heshtje hedhin një ndryshim të commit-uar nuk është fare delta.
Një kolonë e modifikimit të fundit është një e dhënë. Një kursor që i mbijeton një commit-i të vonuar, një fshirjeje dhe një ndërprerjeje të gjatë është një kontratë.