Avatar billede mercutio Nybegynder
02. november 2004 - 18:18 Der er 17 kommentarer og
1 løsning

Transaktioner i java.

Hej Eksperter.
Vi har opfundet vores eget framework og lige nu er vi ved at kigge den måde hvorpå vi hånterer transaktioner igennem i sømmene.
Programmet skal kunne håntere flere brugere.

Til at tilgå databasen bruger vi:
java.sql.Connection
java.sql.PreparedStatement

Hvis man skal rette i nogle oplysninger selecter vi en række fra en tabel. Så kan man ellers rette løs på sit skærmbillede. Når man så er færdig med at rette og vil gemme selecter vi den samme række ud igen og tjekker om et tidsfælt er blevet ændret siden sidst, hvis det er det er der en bruger der har ændret rækken siden vi selv selectede den ud.

Problemet er bare at hvis to brugere trykker på gem på nøjagtig samme tid så kan det ske at den select vi laver før vi gemmer bliver gjort på samme tid og derfor vil vi ikke kunne se at tidsfeltet er ændret af en anden bruger og sidst til mølle får så malet da sidste update overskriver den første. Det vi godt kunne tænke os er at når vi laver den select lige før der tjekkes på tiden og der gemmes at den så kan låse rækken så andre ikke kan læse den. Kan man styre det på en smart måde?

Alle forslag er velkomne.

På forhånd tak.
Merc.
Avatar billede arne_v Ekspert
02. november 2004 - 18:24 #1
Transaction Isolation Level Serializable
Avatar billede arne_v Ekspert
02. november 2004 - 18:25 #2
SELECT
...
BEGIN
SELECT
UPDATE
COMMIT
Avatar billede mercutio Nybegynder
02. november 2004 - 18:27 #3
Den første kommentar er jeg med på det er et parameter jeg kan sætte på min connection men det med BEGIN.... vil du forklare det?
Avatar billede arne_v Ekspert
02. november 2004 - 18:30 #4
Når du sætter transaction isolation level serializable så vil alle transaktioner foregå
som om de var serialiserede altså at den næste først startede når den nuværende
var færdig.
Avatar billede arne_v Ekspert
02. november 2004 - 18:31 #5
Default så er hver SQL sætning i sin egen transaktion d.v.s. at der er en
implcit commit efter hver.

Så får den sidste skal du:

slå auto commit fra
begin ny transaktion
lave de 2 SQL sætninger
committe transaktionen
Avatar billede mercutio Nybegynder
02. november 2004 - 18:32 #6
ok så hvis jeg laver en select og en anden retter i databasen så bliver det han har rettet opdateret i mit resultset?
Avatar billede arne_v Ekspert
02. november 2004 - 18:33 #7
Connection har følgende metoder:

setAutoCommit
commit

tilsyneladende er begin implicit i JDBC (????)
Avatar billede arne_v Ekspert
02. november 2004 - 18:35 #8
Det er sådan set databasens problem hhvordan den vil opnå effekten.

I praksis sker der nok det at databasen putter en LOCK på den row
du SELECT'er. Den LOCK bliver så frigjordt ved COMMIT. Og den anden
transaktion står derfor og venter på at få LOCK indtil den første har
COMMIT'et.
Avatar billede mercutio Nybegynder
02. november 2004 - 18:35 #9
Vi sætter setAutoCommit(false) for at den ikke skal autocommitte.. Når vi så er færdige med at update committer vi. Begin bruger vi ikke så jeg vil tro det sker automatisk.
Avatar billede arne_v Ekspert
02. november 2004 - 18:37 #10
Ja.

Husk at den allerførste SELECT skal ikke med i transaktionen !
Avatar billede mercutio Nybegynder
02. november 2004 - 18:38 #11
Det jeg har brug for er en måde hvorpå jeg kan låse rækken så andre der vil læse den for senere at update den ikke vil kunne læse den før den første der har læst den har committet den.

Dvs. først select for at vise det til brugeren skal ikke låse rækken
anden select der bruges for at hente rækken fra tabellen den skal låse rækken så andre ikke kan selecte den før der er committet.
Avatar billede arne_v Ekspert
02. november 2004 - 18:40 #12
Det er det som du opnår ved at sætte transaction isolation level til serializable !
Avatar billede mercutio Nybegynder
02. november 2004 - 18:46 #13
hmm men hvordan ved den om jeg vil læse for at ændre eller læse for bare at læse?
Så skal jeg sætte transaction isolation level hver gang alt efter hvad jeg skal bruge min connection til?
Avatar billede arne_v Ekspert
02. november 2004 - 18:50 #14
Det gør den selvfølgelig heller ikke.

I det level så låser den alt det du SELECT'er indtil du committer.

Medmindre du har meget høje performance krav kan du godt køre med det
level.

Du skal bare sikre dig at der bliver COMMIT'et (eller ROLLBACK'et) rimeligt
hurtigt.

SELECT
UPDATE
COMMIT

uden noget imellem er helt OK.

Og skal du lave mange SELECT som du ikke skal bruge til opdateringer, så
slå auto commit til mens du laver det.
Avatar billede mercutio Nybegynder
02. november 2004 - 18:53 #15
Hmm ok. Jeg prøver det lige af så vender jeg tilbage. Problemet er bare vi har høj performance krav =)
Avatar billede arne_v Ekspert
02. november 2004 - 18:58 #16
Det skal være meget høje krav for at det her er et problem.

Mne hvsi det er et problem, så kan I overveje en database specifik
løsning.

Mange database understøtter:

SELECT ... FROM ... FOR UPDATE

som så laver en eksplicit LOCK på det man selecter.

Den releases implicit ved UPDATE.
Avatar billede arne_v Ekspert
03. november 2004 - 18:19 #17
OK ?
Avatar billede mercutio Nybegynder
15. november 2004 - 18:13 #18
Jeg valgte at løse problemet ved at huske det jeg havde selectet ud og så bruge det i min where sætning. Men tak for foreslagene.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester