Domanda

Sembra che ci siano opinioni molto diverse sull'uso delle transazioni per la lettura da un database.

Citazione dell'articolo DeveloperWorks Strategie di transazione: modelli e panoramica delle strategie :

  

Perché avresti bisogno di una transazione se   stai solo leggendo i dati? La risposta   è che non lo fai. Avvio a   transazione per eseguire una sola lettura   operazione aggiunge al sovraccarico del   elaborazione thread e può causare condivisi   leggere i blocchi sul database (a seconda   su quale tipo di database stai utilizzando   e quale livello di isolamento è impostato   a).

Come opinione contraria c'è la seguente citazione dalla documentazione di Hibernate Accesso ai dati non transazionali e auto-commit modalità

  

La nostra raccomandazione è di non usare il   modalità autocommit in un'applicazione e   applicare solo transazioni di sola lettura   quando c'è una prestazione ovvia   beneficio o quando il codice futuro cambia   sono altamente improbabili. Preferisco sempre   regolari transazioni ACID da raggruppare   le tue operazioni di accesso ai dati,   indipendentemente dal fatto che tu abbia letto o   scrivere dati.

C'è anche un dibattito simile sulla mailing list di EclipseLink qui .

Allora, dove sta la verità? Le transazioni sono per la lettura delle migliori pratiche o no? Se entrambe sono soluzioni praticabili, quali sono i criteri per l'utilizzo delle transazioni?

Per quanto posso vedere, fa la differenza solo se il livello di isolamento è superiore a "read commit". È corretto?

Quali sono le esperienze e le raccomandazioni?

È stato utile?

Soluzione

Steven Devijver ha fornito alcuni buoni motivi per avviare le transazioni anche se le operazioni stanno andando a leggere solo il database:

  • Imposta i timeout o le modalità di blocco
  • Imposta livello di isolamento

L'SQL standard richiede che anche una query debba avviare una nuova transazione se non è in corso alcuna transazione. Esistono DBMS in cui questo non è ciò che accade, ad esempio quelli con una modalità autocommit (l'istruzione avvia una transazione e la commette immediatamente al completamento dell'istruzione). Altri DBMS rendono le dichiarazioni atomiche (effettivamente autocommit) per impostazione predefinita, ma avviano una transazione esplicita con un'istruzione come 'BEGIN WORK', annullando l'autocommit fino al prossimo COMMIT o ROLLBACK (IBM Informix Dynamic Server è uno di questi - quando il database non è MODE ANSI).

Non sono sicuro del consiglio di non tornare mai indietro. Non fa alcuna differenza per la transazione di sola lettura e, nella misura in cui infastidisce i tuoi DBA, è meglio evitare ROLLBACK. Ma se il tuo programma esce senza eseguire un COMMIT, il DBMS dovrebbe fare un ROLLBACK sulla tua transazione incompleta - certamente se ha modificato il database e (per semplicità) anche se hai selezionato solo dati.

Nel complesso, se si desidera modificare il comportamento predefinito di una serie di operazioni, utilizzare una transazione, anche se la transazione è di sola lettura. Se sei soddisfatto del comportamento predefinito, non è fondamentale utilizzare una transazione. Se il tuo codice deve essere trasferibile tra DBMS, è meglio presumere che tu abbia bisogno di una transazione.

Altri suggerimenti

Prima di tutto, sembra un'ottimizzazione prematura. Come ha sottolineato Steven, la maggior parte dei database sani di mente ti metterà comunque in una transazione, e tutto ciò che stanno realmente facendo è chiamare commit dopo ogni dichiarazione. Quindi, da quel punto di vista, autocommit potrebbe essere meno performante poiché ogni istruzione deve iniziare una nuova transazione. O forse no. Solo il benchmarking lo dirà e scommetto che non fa alcuna differenza per la tua applicazione.

Uno dei motivi per cui si desidera utilizzare sempre una transazione è la coerenza della protezione. Se inizi a giocherellare con la dichiarazione manuale di una transazione solo quando hai bisogno di " allora ti dimenticherai in un momento critico. O quel gruppo di operazioni apparentemente di sola lettura improvvisamente non lo è, sia perché un programmatore successivo non si è reso conto che dovrebbe essere o perché il tuo codice chiama una funzione che ha una scrittura nascosta. Ad esempio, configuro i miei client del database della riga di comando in modo che non si autocommit. Ciò significa che posso eseguire il finger finger di una query di eliminazione e comunque eseguire il rollback.

C'è il livello di isolamento, come sottolineato. Questo ti permette di fare diverse letture senza preoccuparti se qualche altro processo ha scritto tra i tuoi dati tra loro rendendo le letture effettivamente atomiche. Questo ti risparmierà da molte ore il debug di una condizione di gara.

E, infine, puoi spesso impostare una transazione in sola lettura. Ciò verifica la tua ipotesi e si risolverà in errore se qualcosa tenta di scrivere.

Ecco un bell'articolo che riassume tutto . I dettagli sono specifici di Oracle, ma i concetti sono generici.

Le transazioni sono necessarie per le operazioni di sola lettura se si desidera impostare un timeout specifico per query diverse dal timeout predefinito o se si desidera modificare il livello di isolamento.

Inoltre, ogni database - non si conoscono le eccezioni - avvierà internamente una transazione per ogni query. È generalmente considerato non fatto alle transazioni di rollback quando tale rollback non è richiesto.

I DBA potrebbero monitorare l'attività di rollback e qualsiasi comportamento di rollback predefinito li infastidirà in quel caso.

Quindi, le transazioni vengono utilizzate comunque sia che tu le avvii o meno. Se non ti servono, non avviarli, ma non eseguire mai il rollback delle operazioni di sola lettura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top