Newsgroup: it.comp.java
Titolo: [JDBC] cnn.setAutocommit(false)... TRUE!

Non so se vi e' mai capitato ma segnalo
strano comportamento.
 
Setto autocommit a false, quindi faccio
cose tipo:
 
connection.execute('INSERT bla bla bla');
connection.execute('UPDATE bla bla bla');
 
poi ad un certo punto devo spegnere dei
triggers:
 
connection.execute('ALTER TABLE pippo DISABLE ALL TRIGGERS');
 
Oh, se per qualche motivo faccio rollback,
ebbene... e' gia' tutto commitato, anche se
autocommit e' false.
 
In pratica quell'alter table, non so perche', 
e' come se mettesse a true l'autocommit.
 
Buffo.
 
 
 
 
-- 
Se fossi io a testimoniare di me stesso, la mia testimonianza non sarebbe
vera. C'e' un altro che da' testimonianza di me, e so che la testimonianza
che egli da di me e' vera.
 
 
 
 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it
 
 
 

 Buffo.
Non tutti gli statement sql sono committabili, eventualmente fai 
riferimento alla documentazione del DB.
 

 riferimento alla documentazione del DB.
 
Si, tuttavia la cosa che mi colpisce e' che gli
statement (nel veloce esempio fornito) dati nella 
connection con autocommit = false non subiscono 
il rollback! Quindi il problema non e' la non 
committabilita', ma l'opposto: si committano
da se' nonostante l'esplicitazione di non farlo!
 
Grazie


 da se' nonostante l'esplicitazione di non farlo!
 
Mi sono espresso male.
Intendevo dire che alcuni statement non possono far parte di una 
unit-of-work, quindi di una transazione, per cui non possono essere 
assoggettati ne' a commit ne' a rollback.
Da cui l'effetto "buffo" simile all'autocommit, in realta' vengono 
eseguiti e basta, per tornare indietro e' necessario eseguire 
l'operazione opposta, sempre che esista.
Prendi ad esempio una CALL ad una stored procedure che fa un calcolo e 
restituisce un valore, magari in modo non deterministico, come faresti a 
farne il roll-back?


Non ho capito neppure io cosa stai dicendo. Se una SP fa un calcolo non 
c'è nulla di cui fare rollback o commit, ma se scrive su db si. Non si 
capisce perche' uno dovrebbe aspettarsi un commit di una procedura che 
non ha effetto sulla base dati.
 
Per il probblema del OP, è possibile che qualche trigger stia 
effettuando un commit. Controlla tutti i trigger e SP invocate.

 non ha effetto sulla base dati.
E' quello che sto dicendo, perche' dovrebbe aspettarsi di fare rollback 
per lo statement alter table disable all triggers?

 autocommit e' false.
 
eh lo fanno, lo fanno... (cit.)
http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
 
"Statements That Cause an Implicit Commit" (alter table, create index,
drop index, etc...)
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_1001.htm#sthref3207
 
"Oracle Database implicitly commits the current transaction before and
after every DDL statement."
 

 Buffo.
 
Quello da te lanciato non e` un DML, ma un DDL che, nella quasi totalita` 
dei database, e` una tipologia di comandi autocommittante. Quindi, il 
comportamento da te riscontrato non e` buffo, ma corretto
 
Enrico

 comportamento da te riscontrato non e` buffo, ma corretto
 
Vero, ma dovrebbe esserlo della sola,
o delle sole, DDL.
 
Il punto e' che se eseguo delle DML e dell
DDL sulla stessa connessione succede che 
*tutte* le DML sono committate!
 
<g>


 per lo statement alter table disable all triggers?
 
Infatti, spero di spiegarmi meglio:
 
Uso una connessione, gli metto autocommit a false.
Su questa connessione eseguo delle DML *e* delle
DDL. Se per qualche motivo devo fare il rollback
delle DML, beh e' inutile farlo perche' l'uso di
anche solo una DML ha committato *tutto*, anche
le DML. Rootkit ha gentilmente riportato la documentazione
del fenomeno.


 (...) perche' l'uso di anche solo una DDL 


 eh lo fanno, lo fanno... (cit.)
 
Anvedi. 
 
Grazie!


 farne il roll-back?
 
Hai perfettamente ragione, sono io che mi sono 
espresso confusamente.
 
Non voglio fare il rollback di statement che non 
possono avere il rollback.
 
Per fartela brevissima: ho fatto una classe dove
esegue in sequenza degli statement, in pratica e'
un "esecutore" di script sql. 
 
Tra questi ci sono le classiche operazioni DML e 
delle DDL "ALTER TABLE" (per spegnere ed accendere 
triggers). 
 
Tutti gli statement vengono eseguiti attraverso la 
stessa connessione con setAutoCommitt(false).
 
Ora, se per qualche motivo uno statement DML
fallisce la classe fa il rollback di tutto.
 
Tuttavia il rollback non ha alcun effetto perche'
tutte le DML sono state implicitamente committate 
dall'uso di anche un solo statement DDL(!)
 
Invece, eseguendo gli statement DDL su un'altra 
connessione, l'unita' transazionale degli statement
DML funziona.


 o delle sole, DDL.
 
non ha senso quello che dici. la commit si riferisce alla transazione
in cui viene eseguito il comando e non al singolo comando.
in ogni caso è intuitivo che mischiare istruzioni transazionali e
istruzioni che alterano la struttura del db nella stessa transazione
porti a situazioni poco controllabili.
 

 porti a situazioni poco controllabili.
 
Questo e' il punto: non ho intuito che 
sulla stessa connessione un'istruzione
"non transazionale" influenza quelle
"transazionali".
 
Grazie


 "transazionali".
A scanso di equivoci, potresti testare 
dataDefinitionCausesTransactionCommit() di DatabaseMetaData se ritorna true.
 

 *tutte* le DML sono committate!
 
Quindi, vediamo se ho capito bene. Tu hai due connessioni, c1 e c2, 
impostate ad autocommit(false). Nella connessione c1 apri un cursore in cui:
 
 - Esegui una una INSERT (DML);
 - Esegui un DELETE (DML);
 - Esegui ALTER TABLE (DDL).
 
Nel frattempo, prima di fare c1.commit(), esegui da c2 una SELECT sulle 
tabelle coinvolte nei tre comandi eseguiti in c1. Ora, il risultato da te 
attesto e` che c2 trova i dati inalterati, mentre il risultato effettivo e` 
che c2 trova le modifiche effettutate in c1, giusto? Beh, e` il risultato 
corretto. Questo perche` le istruzioni DDL non vanno a modificare il dato, 
ma la struttura su cui esso si appoggia. Per fare un esempio estemporaneo, 
e` come se tu volessi modificare i piedi di una sedia (DDL) mentre c'e` 
seduto sopra qualcuno (DML). Fare questo tipo di modifiche senza avere una 
situazione consistente equivale a creare problemi a dir poco catastrofici, 
di conseguenza e` normale che siano eseguiti in un contesto non 
transazionale
 
Enrico
P.S. tutto questo senza entrare in merito al discorso del livello di 
isolamento della transazione...

 isolamento della transazione...
 
ovviamente.


 Ho risolto la faccenda così
 
Che e` il metodo giusto per gestire queste situazioni
 
Enrico