Hvorfor det er behov for transaksjoner

Svært ofte, når du arbeider med en database, oppstår det en situasjon når du trenger å utføre mange forskjellige handlinger, men de gir bare mening sammen.

For eksempel skriver vi bankprogramvare som skal gjøre tre ting:

  • Ta ut penger fra kundens konto
  • Legg til penger på mottakerens konto
  • Registrer postingsdataene i "posteringsloggen"

Hvis det oppstår en feil under utførelsen av noen av disse handlingene, må de to andre også kanselleres. Er det umulig å avskrive penger fra klienten og ikke legge dem til mottakeren? Vel, eller legge til mottakeren, men ikke avskrive fra klienten?

Så en slik logisk gruppering av forskjellige handlinger i én kalles en transaksjon . Med andre ord er en transaksjon en gruppe handlinger som bare må utføres samlet . Hvis en handling mislyktes eller ble utført med en feil, må alle andre handlinger kanselleres.

En transaksjon har vanligvis tre tilstander:

  • initial state - tilstanden til systemet før en gruppe handlinger utføres
  • suksesstilstand - tilstand etter at aksjonsgruppen er fullført
  • mislykket tilstand - noe gikk galt

I dette tilfellet er det vanligvis tre kommandoer:

  • start/start - utført før starten av den logiske gruppen av handlinger
  • commit - utføres etter transaksjonshandlingsgruppen
  • rollback - starter prosessen med å returnere systemet fra mislykket tilstand til initial tilstand

Det fungerer slik.

Først må du åpne en transaksjon - kall start()- eller start()- metoden . Å kalle denne metoden indikerer tilstanden til systemet som vi vil prøve å gå tilbake til hvis noe går galt.

Deretter utføres alle handlinger, som kombineres til en logisk gruppe - en transaksjon.

Deretter kalles commit ()- metoden . Oppfordringen markerer slutten på en logisk gruppe handlinger, og starter også vanligvis prosessen med å sette disse handlingene ut i livet.

Husk hvordan vi skrev noe i FileWriter: Først lagres alt vi skrev i minnet, og så når flush () -metoden kalles , blir alle dataene fra bufferen i minnet skrevet til disken. Denne flush() er transaksjonsbekreftelsen.

Vel, hvis det oppstod en feil under operasjonen av transaksjonen, må du starte prosessen med å gå tilbake til starttilstanden. Denne prosessen kalles rollback() , og metoden med samme navn er vanligvis ansvarlig for den.

Grovt sett er det 2 måter å fullføre en transaksjon på:

  • FORBINDELSE – vi bekrefter alle endringer som er gjort
  • ROLLBACK - rulle tilbake alle endringer som er gjort

Transaksjoner i JDBC

Nesten alle DBMS kan jobbe med transaksjoner. Så JDBC har også støtte for denne saken. Alt er implementert veldig enkelt.

Først blir hvert kall til execute () -metoden til Statement-objektet utført i en separat transaksjon. For å gjøre dette har Connection en AutoCommit- parameter . Hvis den er satt til true , vil commit() bli kalt etter hvert kall til execute()- metoden .

For det andre, hvis du vil utføre flere kommandoer i en transaksjon, kan du gjøre det slik:

  • deaktiver AutoCommit
  • kaller våre kommandoer
  • kall commit()- metoden eksplisitt

Det ser veldig enkelt ut:

connection.setAutoCommit(false);

Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");

connection.commit();

Hvis det oppstår en feil på serveren mens commit() -metoden kjører , vil SQL-serveren avbryte alle tre handlingene.

Men det er situasjoner når feilen fortsatt oppstår på klientsiden, og vi kom aldri til commit() -metodekallet :

connection.setAutoCommit(false);

Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");

connection.commit();

Hvis det oppstår en feil under kjøringen av en executeUpdate() , vil ikke commit()- metoden bli kalt. For å rulle tilbake alle handlinger som er utført, må du kalle opp rollback() -metoden . Det ser vanligvis slik ut:

try{
  	connection.setAutoCommit(false);

  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");

	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Lagre punkter

Med bruken av JDBC 3.0 ble det mulig å jobbe mer effektivt med tilbakeføring av transaksjoner. Nå kan du angi lagre poeng - lagre poeng, og når du kaller tilbakerulling () operasjonen , rulle tilbake til et spesifikt lagre punkt.

For å lagre må du opprette et lagringspunkt, dette gjøres med kommandoen:

Savepoint save = connection.setSavepoint();

Å gå tilbake til et lagringspunkt gjøres med kommandoen:

connection.rollback(save);

La oss prøve å legge til et lagringspunkt før vår problematiske kommando:

try{
  	connection.setAutoCommit(false);

  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");

  	Savepoint save = connection.setSavepoint();
 	 try{
      	int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");
 	 }
 	 catch (Exception e) {
    	   connection.rollback(save);
 	 }

	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Vi organiserte nestede transaksjoner ved å legge til et lagringspunkt før vi kaller den problematiske metoden, og returnerer til den lagrede tilstanden ved å kalle tilbakerulling(lagre) -metoden .

Ja, det er veldig likt å lagre/laste i spill.