Avatar billede speedpete Nybegynder
31. oktober 2007 - 12:17 Der er 10 kommentarer og
1 løsning

Transaction: IsolationLevel Serializable

Har jeg forstået det ret: Laver nedenstående kode en pessimistic locking, forstået på den måde, at den læser og låser table1, så andre processer ikke kan læse i den, derefter tager sig af table2, og så endelig låser det hele op igen? Altså har denne transaktion eksklusiv adgang til databasen sålænge den er i gang?


String connectionStringMySQL ="lalalala...";
OdbcCommand command = new OdbcCommand();
OdbcTransaction trans = null;
OdbcConnection conn = new OdbcConnection(connectionStringMySQL);
OdbcDataReader reader = null;
command.Connection = conn;

try
{
    conn.Open();
    trans = conn.BeginTransaction(IsolationLevel.Serializable);           
    command.Transaction = trans;

    command.CommandText = "SELECT * from table1 WHERE ID=1";
    reader = command.ExecuteReader();
    reader.Read();
    reader.Dispose();

    command.Parameters.Clear();
    command.CommandText = "INSERT INTO table2 (id) values (3)";
    command.ExecuteNonQuery();

    trans.Commit();
}


catch (Exception e)
{
    trans.Rollback();
    throw e;
}

finally
{
    try { conn.Close(); }
    catch (Exception) { }
}
Avatar billede arne_v Ekspert
31. oktober 2007 - 17:16 #1
Ikke noedvendigvis.

Databasen skal levere transaction isolation level serializable.

Det er op til den hvordan den goer det.

I det konkrete tilfaelde kan den:
  laase hele database
  laase hele table1
  laase alle raekker (inkl. nye) i table1 hvor id=1
Avatar billede speedpete Nybegynder
02. november 2007 - 10:54 #2
Ok, kan du med et blik på følgende:

http://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-isolation.html

se, om jeg kan forlade mig på at udføre ovenstående kode, SOM OM ingen anden proces har samtidig adgang til noget af det, jeg berører? Eksemplet kunne også være noget med "SELECT * from table1 where age < 45".
Avatar billede arne_v Ekspert
03. november 2007 - 01:56 #3
Det vil jeg mene.

Repeatable read vil gøre at ingen række der er SELECT'et kan ændres førend commit.

Serializable vil derudover sikre at der ikke kan tilføjes rækker som vil blive SELECT'et førend commit.
Avatar billede neoman Novice
03. november 2007 - 11:06 #4
For de tungnemme som mig: Hvis man har en transaction kørende, og en anden bruger forsøge at starte en transaction på et set af records som omfatter nogle af de records som den første transaction "låser" som ovenstående, så fejler transaction nr.2 med en eller anden "records locked" meddelelse ?
Avatar billede neoman Novice
03. november 2007 - 11:14 #5
Ah ok - nu har jeg lige læst lidt på arne_v's guldkorn i http://www.eksperten.dk/spm/803519 - og teknikken er,  hvis jeg har fattet det korrekt, at automatisk køre retries på transaction nr 2, indtil den lykkes. Så skal man vel sortere i de exceptions den kommer med, for at undgå en laaaaang loop for de tilfælde, hvor f.ex. hele forbindelsen er gået tabt ?
Avatar billede arne_v Ekspert
03. november 2007 - 15:06 #6
Principielt bør transktion nummer 2 vente indtil transaktion nummer 1 er færdig.

Hvis transaktion nummer 2 har ventet forgæves i tid T så giver det en timeout fejl.

Hvis databasen opdager en dead lock situation, så lader den også en af transaktionerne
få en fejl.

Det var faktisk deadlocks der drillede mig i 803519.
Avatar billede neoman Novice
03. november 2007 - 15:18 #7
Tak for inputtet arne_V. Som du nok er vant til, så leder det bare til flere spørgsmål:)

"Principielt bør transktion nummer 2 vente" Er det programmet, som skal sørge for en loop som timer ud efter et stykke tid, eller er der er en indbygget kø-mekanik i serveren med en time-out som skal sættes? Eller en hel tredje metode ? Med flere brugere har jeg ingen styr på hvem der sender en transaktion afsted eller hvornår.

En enkelt sql command er jo vel også en slags atomisk transaktion: DBMS'en tager sig vel af dem en ad gangen i et eller andet kø-system. Hvis dette er rigtigt, gælder det også de transaktioner man selv bygger sammen af flere sql-commands?


(Sorry speedpete for invasionen, men jeg gætter på, at du også er interesseret i disse svar)
Avatar billede arne_v Ekspert
03. november 2007 - 15:35 #8
Nej. Det er databasen som selv putter den i vent indtil lock bliver mulig. Timeout er
normalt konfigurerbart i databasen.

Nej du kan ikke regne med at enkelte SQL kommandoer er isolerede (vi var inde på det i
et af de andre spørgsmål).

Og slet ikke på multi CPU / multi core systemer.
Avatar billede speedpete Nybegynder
04. november 2007 - 09:50 #9
Ja, neoman, det er fint med denne diskusssion. Jeg kan tilføje, mht. hvilken transaktion der venter, at jeg har forsøgt mig med en enkelt lille tabel på min MySQL5.0, hvor jeg åbner to command-clients (de der små DOS-agtige vinduer). Så laver jeg en serializable transaction i det ene vindue, hvor jeg lader den læse i min tabel. Så skifter jeg til det andet vindue, og prøver at skrive til min tabel - så står cursoren bare og blinker. Så skifter jeg tilbage til mit første vindue og committer transaktionen. I det øjeblik jeg trykker ENTER, så vågner mit andet vindue igen. Bare lige for at illustrere, at det er jo nok default behaviour for ihvertfald MySQL, at lade andre transaktioner vente.
Avatar billede arne_v Ekspert
04. november 2007 - 23:09 #10
I default opsætning mener jeg at InnoDB venter 50 sekunder inden den laver timeout.
Avatar billede speedpete Nybegynder
06. november 2007 - 08:30 #11
Jeg samler det hele i http://www.eksperten.dk/spm/803519
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
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

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