Databasesystemer har mandat til at garantere datakonsistens og integritet, især når der er tale om kritiske data. Disse aspekter håndhæves gennem ACID-transaktioner i MongoDB. En ACID-transaktion bør opfylde nogle definerede regler for datavaliditet, før der foretages opdateringer til databasen, ellers bør den afbrydes, og der skal ikke foretages ændringer i databasen. Alle databasetransaktioner betragtes som en enkelt logisk operation, og i løbet af udførelsestiden sættes databasen i en inkonsistent tilstand, indtil ændringerne er blevet gennemført. Operationer, der med succes ændrer databasens tilstand, betegnes som skrivetransaktioner, mens de, der ikke opdaterer databasen, men kun henter data, omtales som skrivebeskyttede transaktioner. ACID er et akronym for Atomicitet, Konsistens, Isolation og Holdbarhed.
En database er en delt ressource, der kan tilgås af forskellige brugere på forskelligt eller på samme tid. Af denne grund kan der forekomme samtidige transaktioner, og hvis de ikke administreres godt, kan de resultere i systemnedbrud, hardwarefejl, dødvande, langsom databaseydeevne eller gentagelse i udførelsen af den samme transaktion.
Hvad er ACID-regler?
Alle databasesystemer skal opfylde ACID-egenskaberne for at garantere dataintegritet.
Atomicitet
En transaktion betragtes som en enkelt operationsenhed, der enten kan lykkes fuldstændigt eller mislykkes fuldstændigt. En transaktion kan ikke udføres delvist. Hvis en tilstand, der konsulterer en transaktion, mislykkes, vil hele transaktionen mislykkes fuldstændigt, og databasen forbliver uændret. Hvis du f.eks. ønsker at overføre midler fra konto X til Y, er der to transaktioner, den første er at fjerne midler fra X og den anden er at registrere midlerne i Y. Hvis den første transaktion mislykkes, vil hele transaktionen vil blive afbrudt
Konsistens
Når en operation er udstedt, før udførelse, er databasen i en konsistent tilstand, og det bør den forblive efter hver transaktion. Selvom der er en opdatering, bør transaktionen altid bringe databasen til en gyldig tilstand, idet databasens invarianter bevares. For eksempel kan du ikke slette en primær nøgle, der er blevet refereret til som en fremmed nøgle i en anden samling. Alle data skal opfylde de definerede begrænsninger for at forhindre datakorruption fra en ulovlig transaktion.
Isolering
Flere transaktioner, der kører samtidigt, udføres uden at påvirke hinanden, og deres resultat skulle være det samme, hvis de skulle udføres sekventielt. Når to eller flere transaktioner ændrer de samme dokumenter i MongoDB, kan der være en konflikt. Databasen vil opdage en konflikt umiddelbart før den bliver begået. Den første handling for at opnå en lås på dokumentet vil fortsætte, mens den anden vil mislykkes, og der vises en konfliktfejlmeddelelse.
Holdbarhed
Dette dikterer, at når transaktionen er gennemført, skal ændringerne opretholdes til enhver tid, selv i tilfælde af systemfejl, f.eks. på grund af strømafbrydelser eller internetafbrydelse.
MongoDB ACID-transaktioner
MongoDB er en dokumentbaseret NoSQL-database med et fleksibelt skema. Transaktioner er ikke operationer, der skal udføres for hver skrivehandling, da de medfører en større ydeevne i forhold til at skrive et enkelt dokument. Med en dokumentbaseret struktur og denormaliseret datamodel vil der være et minimeret behov for transaktioner. Da MongoDB tillader dokumentindlejring, behøver du ikke nødvendigvis at bruge en transaktion for at opfylde en skriveoperation.
MongoDB version 4.0 giver kun multi-dokument transaktionsunderstøttelse til replikasæt-implementeringer, og version 4.2 vil sandsynligvis udvide understøttelsen af sharded-implementeringer (ifølge deres udgivelsesbemærkninger).
Eksempel på en transaktion:
Sørg for, at du først har et replikasæt på plads. Forudsat at du har en database kaldet app og en samling brugere i Mongo Shell kører følgende kommandoer:
$mongos, og du skulle se noget som brugernavn:PRIMARY>
$use app
$db.users.insert([{_id:1, name: ‘Brian’}, {_id:2, name: ‘Sheila’}, {_id:3, name: ‘James’}])
Vi skal starte en session for vores transaktion:
$db.getMongo().startSession() and you should see something like
session { "id" : UUID("dcfa8de5-627d-3b1c-a890-63c9a355520c") }
Ved at bruge denne session kan vi tilføje flere brugere ved hjælp af en transaktion med følgende kommandoer
$session.startTransaction()
session.getDatabase(‘app’).users.insert({_id:4, name: ‘Hitler’})
Du vil blive præsenteret for WriteResult({“nInsterted”:2})
Transaktionen er endnu ikke blevet forpligtet, og den normale $db.users.find({}) vil kun give os de tidligere gemte brugere. Men hvis vi kører
$session.getDatabase(“app”).users.find()
den sidst tilføjede post vil være tilgængelig i de returnerede resultater. For at udføre denne transaktion kører vi kommandoen nedenfor
$session.commitTransaction()
Transaktionsændringen er gemt i hukommelsen, og det er grunden til, at selv efter fejl, vil dataene være tilgængelige ved gendannelse.
ACID-transaktioner i flere dokumenter i MongoDB
Dette er operationer med flere sætninger, der skal udføres sekventielt uden at påvirke hinanden. For eksemplet ovenfor kan vi oprette to transaktioner, en for at tilføje en bruger og en anden for at opdatere en bruger med et aldersfelt. Dvs.
$session.startTransaction()
db.users.insert({_id:6, name “Ibrahim”})
db.users.updateOne({_id:3 , {$set:{age:50}}})
session.commit_transaction()
Transaktioner kan anvendes på operationer mod flere dokumenter indeholdt i en eller flere samlinger/databaser. Eventuelle ændringer på grund af dokumenttransaktion påvirker ikke ydeevnen for arbejdsbelastninger, der ikke er relaterede eller kræver dem ikke. Indtil transaktionen er forpligtet, replikeres ikke-forpligtede skrivninger hverken til de sekundære knudepunkter, og de kan heller ikke læses uden for transaktionerne.
Bedste praksis for MongoDB-transaktioner
Transaktioner med flere dokumenter understøttes kun i WiredTiger-lagringsmotoren. Som nævnt før vil meget få applikationer kræve transaktioner, og hvis det er tilfældet, bør vi forsøge at gøre dem korte. Ellers, for en enkelt ACID-transaktion, hvis du prøver at udføre et for stort antal operationer, kan det resultere i højt tryk på WiredTiger-cachen. Cachen er altid dikteret til at opretholde tilstanden for alle efterfølgende skrivninger, siden det ældste snapshot blev oprettet. Dette betyder, at nye skrivninger vil akkumulere i cachen under hele transaktionens varighed og kun tømmes efter transaktioner, der i øjeblikket kører på gamle snapshots, er begået eller afbrudt. For den bedste databaseydeevne på transaktionen bør udviklere overveje:
- Rediger altid et lille antal dokumenter i en transaktion. Ellers bliver du nødt til at opdele transaktionen i forskellige dele og behandle dokumenterne i forskellige batches. Behandle højst 1000 dokumenter ad gangen.
- Midlertidige undtagelser som f.eks. at vente på at vælge primære og forbigående netværkshikke kan resultere i afbrydelse af transaktionen. Udviklere bør etablere en logik for at prøve transaktionen igen, hvis de definerede fejl præsenteres.
- Konfigurer optimal varighed for udførelsen af transaktionen fra standard 60 sekunder fra MongoDB. Anvend desuden indeksering, så det kan tillade hurtig dataadgang inden for transaktionen. Du har også fleksibiliteten til at finjustere transaktionen i forhold til timeouts ved at opdele den i batches, der tillader dens udførelse inden for tidsfristerne.
- Dekomponér din transaktion i et lille sæt operationer, så den passer til begrænsningerne på 16 MB størrelse. Ellers, hvis operationen sammen med oplog-beskrivelsen overskrider denne grænse, vil transaktionen blive afbrudt.
- Alle data relateret til en enhed skal gemmes i en enkelt, rig dokumentstruktur. Dette er for at reducere antallet af dokumenter, der skal cachelagres, når forskellige felter skal ændres.
Begrænsninger af transaktioner
- Du kan ikke oprette eller slette en samling i en transaktion.
- Transaktioner kan ikke skrive til en begrænset samling
- Transaktioner tager masser af tid at udføre, og på en eller anden måde kan de bremse databasens ydeevne.
- Transaktionsstørrelsen er begrænset til 16 MB, hvilket kræver, at man opdeler enhver, der har tendens til at overskride denne størrelse, i mindre transaktioner.
- At udsætte et stort antal dokumenter for en transaktion kan lægge et overdrevent pres på WiredTiger-motoren, og da den er afhængig af snapshot-kapaciteten, vil der være en fastholdelse af store ikke-skyllede operationer i hukommelsen. Dette giver nogle ydelsesomkostninger på databasen.
Konklusion
MongoDB version 4.0 introducerede multi-dokument transaktionsunderstøttelse for replikasæt som en funktion til at forbedre dataintegritet og konsistens. Der er dog meget få applikationer, der vil kræve transaktioner, når du bruger MongoDB. Der er begrænsninger i forhold til denne funktion, der gør den betydeligt lidt umoden, hvad angår transaktionskonceptet. For eksempel understøttes transaktioner for en fragmenteret klynge ikke, og de kan ikke være større end 16 MB størrelsesgrænse. Datamodellering giver en bedre struktur til at reducere transaktioner i din database. Medmindre du har at gøre med særlige tilfælde, vil det være en bedre praksis at undgå transaktioner i MongoDB.