Gå til innhold

MySQL: Har jeg glemt å kjøre commit?


Anbefalte innlegg

Etter å ha lest noen tråder her om integriteten i MySQL databaser slo deg meg at jeg har glemt noe som er viktig og ganske pinlig å glemme, nemlig commite data. Jeg har derfor et noob spørsmål å komme med.

 

Er det auto commit i MySQL? Eller er det opp til DB-admin? Pleier dere å kjøre spørringer med commit i slutten?

 

Flau hilsen :blush:

Lenke til kommentar
Videoannonse
Annonse
Etter å ha lest noen tråder her om integriteten i MySQL databaser slo deg meg at jeg har glemt noe som er viktig og ganske pinlig å glemme, nemlig commite data. Jeg har derfor et noob spørsmål å komme med.

 

Er det auto commit i MySQL? Eller er det opp til DB-admin? Pleier dere å kjøre spørringer med commit i slutten?

 

Flau hilsen :blush:

 

Leste nettopp at det er default i InnoDB iallefall..

Lenke til kommentar
Leste nettopp at det er default i InnoDB iallefall..

jepp, du kan skru av autocommit med

 

set autocommit=0;

 

det er ofte lurt å kjøre med manuelle transaksjoner om du holder på med viktige data, da får du muligheten til å tenke deg om en gang til før du gjør noe virkelig dumt :-)

 

når det gjelder integriteten så påstås innodb å være fullstendig ACID. dette med synkron skriving av binærloggen er som det kom fram konfigurerbart, men det er også like mye et spørsmål om egenskapene ved os/filsystemet man kjører på og hvordan det er konfigurert der. noen databaser kan kjøre mot rå partisjoner slik at de har full kontroll så langt mulig i software, men problemstillingen fortsetter jo videre ned til cache i disker og kontrollere ... så hvis man skal være fullstendig bombesikker vil jeg hevde at defaultkonfigurasjonen til binlogginga i innodb er det aller, aller minste problemet man har.

Endret av quantum
Lenke til kommentar

OK, det gir svar på hvorfor jeg ikke kan kjøre rollback. Blir ofte litt for sløv når man får for mye lagt i fanget slik som autocommit.

 

All data er forsåvidt viktig, men den problemstillingen quantum kommer med er heldigvis ikke kritisk i mitt system så lenge det blir tatt tatt en regelmessig backup.

Lenke til kommentar
Leste nettopp at det er default i InnoDB iallefall..

jepp, du kan skru av autocommit med

 

set autocommit=0;

 

det er ofte lurt å kjøre med manuelle transaksjoner om du holder på med viktige data, da får du muligheten til å tenke deg om en gang til før du gjør noe virkelig dumt :-)

 

når det gjelder integriteten så påstås innodb å være fullstendig ACID. dette med synkron skriving av binærloggen er som det kom fram konfigurerbart, men det er også like mye et spørsmål om egenskapene ved os/filsystemet man kjører på og hvordan det er konfigurert der. noen databaser kan kjøre mot rå partisjoner slik at de har full kontroll så langt mulig i software, men problemstillingen fortsetter jo videre ned til cache i disker og kontrollere ... så hvis man skal være fullstendig bombesikker vil jeg hevde at defaultkonfigurasjonen til binlogginga i innodb er det aller, aller minste problemet man har.

Grunnen til å kjøre transaksjoner er at man da sørger for at alle (eller ingen data) blir skrevet til disk når du skal gjøre en operasjon.

 

La oss si at du skal opprette en ordre med deler:

 

01 INSERT INTO order ...

02 INSERT INTO order_parts ...

03 INSERT INTO order_parts ...

.... INSERT INTO order_parts ...

40 INSERT INTO order_parts ...

 

Hvis du kjører autocommit og det oppstår en feil når du kjører spørring #40 vil ordren ligge i systemet med 38 deler og se riktig ut for brukeren.

 

Hvis du kjører dette i en transaksjon vil du enten få ordren riktig inn i databasen med 39 deler, eller ikke i det hele tatt. Brukeren trenger ikke lure på om ordren er blitt lagt inn fullstendig eller ikke.

 

Hvis man f.eks bruker java og EJB3* så kan man få automatiske transaksjoner (ikke det samme som autocommit), som gjør at du ikke trenger å tenke på begin/commit/rollback i 99% av tilfellene. De resterende 1% må du gjøre selv fordi du f.eks vil dele opp en batch-import i flere deler.

 

*Enterprise JavaBeans, brukes sammen med en applikasjonsserver som Glassfish eller JBoss

Lenke til kommentar
Hvis man f.eks bruker java og EJB3* så kan man få automatiske transaksjoner (ikke det samme som autocommit), som gjør at du ikke trenger å tenke på begin/commit/rollback i 99% av tilfellene. De resterende 1% må du gjøre selv fordi du f.eks vil dele opp en batch-import i flere deler.

 

*Enterprise JavaBeans, brukes sammen med en applikasjonsserver som Glassfish eller JBoss

Apropos transaksjoner og det vi fant ut ang postgresql og nestede transaksjoner, vet du hva ejb-containeren gjør når den skal kjøre en ejb-metode som REQUIRES_NEW transaksjon, og den allerede er inne i en annen transaksjon ... og kjører mot postgresql? Kanskje jdbc-driveren håndterer det ved å lage savepoints? Håper igrunnen på det, og ikke at ulike ejb-containere (og jpa-rammeverk) har ulike workarounds som virker «stort sett men ikke helt» på samme måte ...

Lenke til kommentar
når det gjelder integriteten så påstås innodb å være fullstendig ACID. dette med synkron skriving av binærloggen er som det kom fram konfigurerbart, men det er også like mye et spørsmål om egenskapene ved os/filsystemet man kjører på og hvordan det er konfigurert der. noen databaser kan kjøre mot rå partisjoner slik at de har full kontroll så langt mulig i software, men problemstillingen fortsetter jo videre ned til cache i disker og kontrollere ... så hvis man skal være fullstendig bombesikker vil jeg hevde at defaultkonfigurasjonen til binlogginga i innodb er det aller, aller minste problemet man har.

 

InnoDB er full ACID ja, men det er eit par punkter i MySQL ein bør lese om dette med binærloggen. InnoDB er ikkje "safe" med standardinnstillinger.

 

Eit par utdrag frå MySQL manualen:

"By default, the binary log is not synchronized to disk at each write. So if the operating system or machine (not only the MySQL server) crashes there is a chance that the last statements of the binary log are lost. To prevent this, you can make the binary log be synchronized to disk after every Nth binary log write, with the sync_binlog global variable (1 being the safest value, but also the slowest)."

 

Men det stopper ikkje der

Even with [sync_binlog] set to 1, there is still the chance of an inconsistency between the tables content and the binary log content in case of crash. [...] This problem can be solved with the --innodb-safe-binlog option (available starting from MySQL 4.1.3), which adds consistency between the content of InnoDB tables and the binary log. For this option to really bring safety to you, the MySQL server should also be configured to synchronize to disk, at every transaction, the binary log (sync_binlog=1) and (which is true by default) the InnoDB logs.

Så kan ein skru på binlogg.

 

PostgreSQL bruker fsync() for å garantere at dataen har blitt skreve fysisk til disk, altså ingenting ligger igjen i cachen til disk eller kontroller.

http://www.postgresql.org/docs/8.4/interac...config-wal.html

Lenke til kommentar
InnoDB er full ACID ja, men det er eit par punkter i MySQL ein bør lese om dette med binærloggen. InnoDB er ikkje "safe" med standardinnstillinger.

 

...

 

PostgreSQL bruker fsync() for å garantere at dataen har blitt skreve fysisk til disk, altså ingenting ligger igjen i cachen til disk eller kontroller.

 

For å ta standardinnstillingene enda en gang; Dersom du har høye krav til at tap av data skal unngås, så kjører du ikke med standardinnstillinger uten å gå gjennom alle sammen og evt. gjøre de endringene som er nødvendige. Standardinnstillingene til de fleste databaser er også ulik i ulike forpakninger. Men generelt er det riktig at MySQL er gearet mer mot ytelse en trygghet i forhold til Postgresql. Det kan godt hende det er årsaken til MySQL's utbredelse ... til prisen av datatap.

 

Så over til det som står i postgresql-manualen, nemlig at fsync() kalles for å *forsøke* å skrive data fysisk til disk (will try to make sure that updates are physically written to disk, by issuing fsync()), grunnen til at det er formulert slik er at det er opp til filsystem, os og hardware å avgjøre om dette faktisk skjer.

 

Det databaser kan garantere er konsistent recovery, ikke total recovery, men ved å ha en konfigurasjon med redundans kan man gjøre sjansene for datatap mikroskopiske. Da er man imidlertid laaaaangt forbi det bruksområdet hvor noen standardkonfigurasjon er relevant.

Lenke til kommentar
Så over til det som står i postgresql-manualen, nemlig at fsync() kalles for å *forsøke* å skrive data fysisk til disk (will try to make sure that updates are physically written to disk, by issuing fsync()), grunnen til at det er formulert slik er at det er opp til filsystem, os og hardware å avgjøre om dette faktisk skjer.

Delvis rett, fsync() er ein unix spesifikk ting for å sikre at data blir skreve til disk. Sjølvsagt kan nokon "fjerne" den funksjonaliteten frå eit operativsystem sånn at PostgreSQL blir lurt. http://en.wikipedia.org/wiki/Sync_%28Unix%29

Det gjelder nok også Windows.

Det databaser kan garantere er konsistent recovery, ikke total recovery, men ved å ha en konfigurasjon med redundans kan man gjøre sjansene for datatap mikroskopiske. Da er man imidlertid laaaaangt forbi det bruksområdet hvor noen standardkonfigurasjon er relevant.

Det er feil, databasetap/feil skal ALDRI forekomme. Skriver du på mailinglista til PostgreSQL at du har hatt datatap som skyldes PostgreSQL så får du kjerneutviklerane til å gå amok.

 

Og for å legge til, i dei siste versjonane av PostgreSQL så har ytelsen auka så drastisk at PostgreSQL med fsync enabled er raskare enn InnoDB med Google SMP patch utan den binærlog tingen skrudd på.

Endret av siDDIs
Lenke til kommentar
Det databaser kan garantere er konsistent recovery, ikke total recovery, men ved å ha en konfigurasjon med redundans kan man gjøre sjansene for datatap mikroskopiske. Da er man imidlertid laaaaangt forbi det bruksområdet hvor noen standardkonfigurasjon er relevant.

Det er feil, databasetap/feil skal ALDRI forekomme. Skriver du på mailinglista til PostgreSQL at du har hatt datatap som skyldes PostgreSQL så får du kjerneutviklerane til å gå amok.

 

Og for å legge til, i dei siste versjonane av PostgreSQL så har ytelsen auka så drastisk at PostgreSQL med fsync enabled er raskare enn InnoDB med Google SMP patch utan den binærlog tingen skrudd på.

Hva er feil? At det kan forekomme datatap som følge av ting databasen ikke har kontroll på? Vel ...

 

Hvordan ytelsen skal være relevant i denne sammenhengen sliter jeg med å se.

Lenke til kommentar

Poenget til siDDIs er at Postgresql er ACID compliant hvis du innstallerer det på en vanlig windows/linux install out-of-the-box. Ingen ekstrakonfigurering nødvendig. At du selv kan klusse til dette ved å endre på innstillinger selv er ikke akkurat noe en databaseleverandør kan gjøre noe med.

 

siDDIs har forresten rett - hvis en transaksjon er rapportert som avsluttet så skal eneste mulige grunnen til datatap være fullstendig hardwarefailure, f.eks at begge diskene i et RAID 1 array dør samtidig. Hvis kravene dine til sikkerhet er høyere enn det så må man nok bruke en form for log-shipping e.l.

 

Ang ytelse siDDIs, så var det vel Postgresql versjon 8.3 ytelsesøkningen kom for over et år siden. Forskjellen til 8.4 tror jeg ikke var i nærheten så stor...

Lenke til kommentar
siDDIs har forresten rett - hvis en transaksjon er rapportert som avsluttet så skal eneste mulige grunnen til datatap være fullstendig hardwarefailure, f.eks at begge diskene i et RAID 1 array dør samtidig. Hvis kravene dine til sikkerhet er høyere enn det så må man nok bruke en form for log-shipping e.l.

Jepp, såvidt jeg kan se er alle vi andre helt enige om akkurat det, og det hadde du vært også om korttidsminnet ditt hadde hatt et lengre spenn enn tiden det tar deg å poste et innlegg :o)

 

Hvis du kunne formulere litt presist *akkurat* hva som er oppe til diskusjon nå, eller evt. komme med litt juicy info om postgresql og REQUIRES_NEW ejb-transaksjoner hadde det vært fint.

Lenke til kommentar
Hvis man f.eks bruker java og EJB3* så kan man få automatiske transaksjoner (ikke det samme som autocommit), som gjør at du ikke trenger å tenke på begin/commit/rollback i 99% av tilfellene. De resterende 1% må du gjøre selv fordi du f.eks vil dele opp en batch-import i flere deler.

 

*Enterprise JavaBeans, brukes sammen med en applikasjonsserver som Glassfish eller JBoss

Apropos transaksjoner og det vi fant ut ang postgresql og nestede transaksjoner, vet du hva ejb-containeren gjør når den skal kjøre en ejb-metode som REQUIRES_NEW transaksjon, og den allerede er inne i en annen transaksjon ... og kjører mot postgresql? Kanskje jdbc-driveren håndterer det ved å lage savepoints? Håper igrunnen på det, og ikke at ulike ejb-containere (og jpa-rammeverk) har ulike workarounds som virker «stort sett men ikke helt» på samme måte ...

 

Nå skal jeg ikke uttale meg skråsikkert her, men REQUIRES_NEW skulle vel tilsi nettopp det, at du får en NY transaksjon som er uavhengig av den andre transaksjonen (som du allerede er i).

 

... ikke at jeg akkurat får testet dette pga krav om en legacy JDBC driver i systemet vårt... :p

 

Ser ut som det kanskje er noen svakheter rundt det her, så hvis du har en metode A som tar lang tid å kjøre, som innimellom kaller metode B som skal kjøre en egen transaksjon (REQUIRES_NEW), så må du ha metode A og B i forskjellige Beans, eller få den til å kalle metode B gjennom en proxy/injection.

 

http://stackoverflow.com/questions/325752/...e-session-beans

http://stackoverflow.com/questions/106437/...ion-propogation

Endret av blackbrrd
Lenke til kommentar
Nå skal jeg ikke uttale meg skråsikkert her, men REQUIRES_NEW skulle vel tilsi nettopp det, at du får en NY transaksjon som er uavhengig av den andre transaksjonen (som du allerede er i).

 

Akkuart det kan vel vanskelig skje iom. at postgresql viser seg å ikke støtte nestede transaksjoner. Jeg lurer på hva workaround'en er, dvs. jeg vet hva den er, men lurer på hvor den ligger, container eller jdbc-driver.

Lenke til kommentar
Nå skal jeg ikke uttale meg skråsikkert her, men REQUIRES_NEW skulle vel tilsi nettopp det, at du får en NY transaksjon som er uavhengig av den andre transaksjonen (som du allerede er i).

 

Akkuart det kan vel vanskelig skje iom. at postgresql viser seg å ikke støtte nestede transaksjoner. Jeg lurer på hva workaround'en er, dvs. jeg vet hva den er, men lurer på hvor den ligger, container eller jdbc-driver.

Hmm.. nå er jeg ikke helt med på hva du mener...

 

"REQUIRES_NEW annotation does not create any sort of relationship between the 2 transactions, it just allows you to "pause" the current transaction, do some work in another transaction and commit/abort it, and then "resume" the original transaction."

http://forums.sun.com/thread.jspa?threadID=5407883

Lenke til kommentar
"REQUIRES_NEW annotation does not create any sort of relationship between the 2 transactions, it just allows you to "pause" the current transaction, do some work in another transaction and commit/abort it, and then "resume" the original transaction."

http://forums.sun.com/thread.jspa?threadID=5407883

 

Lurer rett og slett på hvordan det gjøres. La oss anta at vi har en session/connection, og vi holder på å eksekvere en metode m1 i en transaksjon t1. Så kaller den metoden (m1) en annen metode (m2) som må kjøre i egen transaksjon (t2) pga. REQUIRES_NEW.

 

Siden vi alt er i en transaksjon (t1) antar jeg at det har vært eksevert en BEGIN TRANSACTION på connection'en allerede. Så kalles m2 og da kommer en t2 BEGIN TRANSACTION til før t1 er commitet. Men det går jo ikke, så da lurer jeg på hva som skjer isteden.

 

Først tenkte jeg at man laget et savepoint for å «simulere» t2, men har googlet litt, og det ser ut som man alternativt kanskje kjører t2 i en ny connection.

 

PS, tar her for gitt at man løser dette med nestede transaksjoner der hvor databasen støtter dette, men det er kanskje ikke tilfellet. Det må ihvertfall være fordelaktig å slippe å opprette flere connections.

Endret av quantum
Lenke til kommentar

Ser ikke helt hvorfor det er en fordel med nestede transaksjoner? REQUIRES_NEW vil jo si at du vil ha en ny transaksjon med en enhet arbeid som skal lagres hvis den enheten blir gjort ferdig. Mao ikke rollbackes hvis det skjer noe i f.eks metoden som kallte denne metoden.

 

Postgres sin løsning med en prosess pr connection er relativt uvanlig. Det vanlige er at en prosess har mange tråder og en connection pr tråd. Da skal det ikke spille noe særlig rolle at du har svært mange connections åpne...

 

Det skal også sies at EJB jo har et connection pool å ta i fra, så å koble til en ny connection fra connection poolet er ikke akkurat en krevende operasjon.

 

Min teori er mao at man løser dette med nye transaksjoner, ikke nestede. (Som jeg ikke helt ser poenget med - da kunne du jo liksågodt brukt savepoints e.l.)

Lenke til kommentar
...

Det skal også sies at EJB jo har et connection pool å ta i fra, så å koble til en ny connection fra connection poolet er ikke akkurat en krevende operasjon.

 

Min teori er mao at man løser dette med nye transaksjoner, ikke nestede. (Som jeg ikke helt ser poenget med - da kunne du jo liksågodt brukt savepoints e.l.)

Connections er ofte ressurskrevende (på databasesiden), derfor man har pool. Og dersom man lager et system som krever to connections for en session istedenfor én, så kan man ha nøyaktig halvparten så mange samtidige brukere.

 

Ellers får man jo til akkurat det samme med savepoints (trur eg), så jeg ser heller ikke problemet. Men fant en posting på et forum som antyda at det opprettes en connection til i sånne tilfeller.

Lenke til kommentar
Ellers får man jo til akkurat det samme med savepoints (trur eg), så jeg ser heller ikke problemet. Men fant en posting på et forum som antyda at det opprettes en connection til i sånne tilfeller.

Savepoints kan ikke brukes til å emulere flere transaksjoner, det brukes til avansert feilhåndtering...

 

Hvis du har en transaksjon A som henter ut data fra databasen. Disse dataene skal så prosessesres og en endringslogg skrives tilbake, med en transaksjon pr objekt. La oss si at hvert objekt er en bil. Du er mao interessert i å vite hvor mange deler som er brukt før du er ferdig med å gjøre ferdig alle bilene. Du bruker derfor en transaksjon pr bil.

 

Med nested transaksjoner/savepoints vil du ikke ved Serializable transaksjonsnivået se hva som skjer i hver nested transaksjon/savepoint utenfor denne nestede transaksjonen. Når du så prøver å lage et bestillingsforslag i en helt annen transaksjon ser det mao ikke ut som du har brukt noen deler, for bil nr 10.000 som er den siste i batchen er ikke ferdig.

 

Andre problemer med lange nestede transaksjoner er at ACID compliance gjelder pr transaksjon. Mao, får du en hw/sw failure midt i en transaksjon så SKAL du "miste" dataene.

 

REQUIRES_NEW er måten du får en NY transaksjon til dette bruket - ikke et savepoint e.l.

 

http://en.wikipedia.org/wiki/Savepoint

"Savepoints are useful for implementing complex error recovery in database applications — if an error occurs in the midst of a multiple-statement transaction, the application may be able to recover from the error (by rolling back to a savepoint) without needing to abort the entire transaction."

Endret av blackbrrd
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...