Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

di il
19 risposte

19 Risposte - Pagina 2

  • Re: Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

    iBaffiPro ha scritto:


    Serializable è usato dal database SQL di Microsoft ma in effetti si dice che è molto scarso in termini di performance.
    Non ho capito questa affermazione.
    Serializable è supportato da pressoché tutti i maggiori DBMS, non solo da SQL Server: MySQL, MariaDB, PostgreSQL.

    Il default usato da SQL Server è "READ COMMITTED": https://docs.microsoft.com/it-it/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15
  • Re: Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

    andbin ha scritto:


    iBaffiPro ha scritto:


    Read Committed: non garantisce che un dato letto continui ad essere presente oppure assente dopo il commit;
    Repeatable Read: garantisce che i record letti restino invariati dopo il commit ma gli altri record della tabella possono cambiare
    Serializable: garantisce che la tabella nella quale si legge il record resti invariata dopo il commit
    NOO. Leggi bene le spiegazioni che trovi online sulle 3 "anomalie": Dirty reads, Non-repeatable reads e Phantom reads.
    Non stare, per ora, a guardare COSA viene usato (snapshot, lock, ecc...) per impedire queste anomalie, perché DBMS differenti potrebbero usare tecniche o approcci (leggermente) differenti.
    È importante invece capire COSA avviene in ciascuna anomalia. Poi banalmente c'è la tabellina che ti dice quali anomalie sono permesse e non permesse per ciascun livello di isolamento.

    P.S. ma il Dirty reads l'ho spiegato prima! .. e credo pure bene ....

    iBaffiPro ha scritto:


    Quello che mi stai dicendo e che dovrei dedicare più tempo ed attenzione a questo aspetto e scegliere @Transaction diverse per @Service diverse e non generalizzare come sto facendo? Giusto?
    Per me, puoi anche mettere Serializable su tutte le tue transazioni .... l'importante è che concludi queste esercitazioni prima possibile ...
    Mi sono sbagliato a scrivere, volevo usare "uncommitted". Approfondisco il discorso con un esempio:
    BEGIN TRANSACTION;
    SELECT * FROM Tabella_A;
    SELECT * FROM Tabella_A;
    COMMIT;
    Questo è quello che ho capito:
    Read uncommitted: le 2 select possono fornire dati diversi e dopo il commit i dati possono essere diversi dalla seconda select (la transazione non fallisce mai);
    Read committed: la seconda select può fornire dati diversi dalla prima e dopo il commit i dati devono essere gli stessi della seconda select, in caso contrario la transazione fallisce e non fornisce nulla. Tra la prima e la seconda select si possono aggiungere, modificare o rimuovere record alla tabella.
    Repeatable read: come read committed la seconda select deve essere rispettata, dopo il commit i dati letti devono essere presenti a DB, ma rispetto a read committed garantisce che i dati letti nella prima select siano presenti anche nella seconda. Nella seconda select possono esserci più dati rispetto alla prima ma non in meno e i dati della prima select devono essere presenti anche nella seconda;
    Serializable: garantisce che i dati della prima select, della seconda e dopo il commit siano identici.
    Il livello di isolamento chiamato read uncommitted permette i dirty reads mentre invece l'isolamento chiamato read committed non li permette.
    In PostgreSQL il read uncommitted non è gestito e, se settato, si comporta come read committed. Questo significa che in PostgreSQL i dirty reads non sono mai possibili. Su altri database invece il read uncommitted è gestito e settabile.
    In merito all'isolation level nelle transazioni su DB ci sono 3 tipi di "anomalie" che possono avvenire. Sono denominate:
    - Dirty reads (letture sporche): la transazione A legge dei record inseriti da una transazione B non ancora conclusa che fallendo lancia un rollback e cancella gli stessi record letti dalla transazione A. In sostanza la transazione A fornisce dei record che a DB non esistono. Ovviamente la problematica si verifica non solo per nuovi inserimenti ma anche per nuove modifiche o cancellazioni di record;
    - Non-repeatable reads (letture non ripetibili): Una lettura non ripetibile si verifica quando, nel corso di una transazione, una riga viene recuperata due volte e i valori all'interno della riga differiscono tra le letture. Come spiegato sopra read uncommitted (non supportato in PostgreSQL), read committed, repeatable read e serializable forniscono soluzioni diverse.
    - Phantom reads (letture fantasma): Una lettura fantasma si verifica quando, nel corso di una transazione, nuove righe vengono aggiunte o rimosse da un'altra transazione ai record letti. Come spiegato sopra read uncommitted (non supportato in PostgreSQL), read committed, repeatable read e serializable forniscono soluzioni diverse.
    Ritornando al mio esempio:
    Dirty reads non ne posso avere perché uso PostgreSQL, non-repeatable reads e phantom reads neppure perché ho solo 1 select quindi qualunque transazione (la meno bloccante, onerosa, ecc... ovviamente) può andare bene, quindi la seguente:
    @Transactional(
            isolation = Isolation.READ_COMMITTED,
            propagation = Propagation.REQUIRED,
            rollbackFor = Exception.class,
            readOnly=false
    )
    a mio avviso può andare bene. Ho messo Propagation.REQUIRED perché in realtà ho scoperto di avere una transazione in più interna alla fase di registrazione che mi era sfuggita. In pratica una transazione che si occupa di verificare se la fase di registrazione è resa possibile oppure no.
    Concordi su tutto? Ho più o meno capito e posso dedicarmi alle altre @Service oppure no?
    P.S.: Avevo letto che SQL Server usava di default serializable ma evidentemente ho letto una stupidaggine.
  • Re: Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

    Se uso @Transactional la mia applicazione non si velocizza neppure di un secondo.
    Un Test di JUnit, in particolare, mi lascia molto perplesso perché passa da 1 minuto ad 1 ora. E' un test che lancia tante volte un metodo X di una classe @Service Y e qualche query di verifica del risultato. In X ci sono 4 o 5 query ed io pensavo che senza l'uso di @Transaction sulla classe Y ciascuna di queste query generasse una transazione indipendente rendendo il test lento ma in realtà non è così.
    Se lo schema del DB è ben scritto, ci sono tutti i vincoli giusti e nel posto giusto, non ci sono casi particolari come l'esempio dell'e-commerce, a mio avviso questo @Transactional serve a poco.
  • Re: Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

    iBaffiPro ha scritto:


    Questo è quello che ho capito:
    Read uncommitted: le 2 select possono fornire dati diversi e dopo il commit i dati possono essere diversi dalla seconda select (la transazione non fallisce mai);
    Read committed: la seconda select può fornire dati diversi dalla prima e dopo il commit i dati devono essere gli stessi della seconda select, in caso contrario la transazione fallisce e non fornisce nulla. Tra la prima e la seconda select si possono aggiungere, modificare o rimuovere record alla tabella.
    [......]
    Secondo me continui a fare (molta!) confusione. Alcune cose che hai scritto sono giuste ma non ben contestualizzate.
    Allora: ci sono le tre ben note "anomalie", che sono specificate dallo standard SQL: Dirty reads / Non-repeatable reads / Phantom reads
    Se prendiamo il livello Read uncommitted NON è una sola cosa! Quindi non puoi scrivere banalmente e solamente:

    Read uncommitted: le 2 select possono fornire dati diversi e dopo il commit i dati possono essere diversi dalla seconda select (la transazione non fallisce mai)

    perché non sarebbe completamente corretto. Nel livello Read uncommitted tutte le tre anomalie sono possibili!! Non una sola.

    Ti è chiaro questo?

    iBaffiPro ha scritto:


    Se uso @Transactional la mia applicazione non si velocizza neppure di un secondo.
    Il @Transactional NON serve per andare "più veloce" !! Te lo ripeto: serve per garantire quel comportamento che si dice con l'espressione "o tutto o niente" (oltre ovviamente a poter specificare isolation ecc...).

    Concludi l'esercitazione. Più continui, più sprechi tempo.
  • Re: Come si esegue "BEGIN TRANSACTION ... COMMIT" in jdbcTemplate?

    Ok tutto chiaro, grazie
Devi accedere o registrarti per scrivere nel forum
19 risposte