È una cattiva pratica creare sempre una transazione?


88

È una cattiva pratica creare sempre una transazione?

Ad esempio, è una buona pratica creare una transazione per nient'altro che semplice SELECT?

Qual è il costo di creazione di una transazione quando non è realmente necessario?

Anche se stai usando un livello di isolamento come READ UNCOMMITTED, è una cattiva pratica?


1
Guardando l'impatto del BEGIN TRAN SELECT ... COMMITvs solo SELECTsembra esserci una differenza di prestazioni estremamente minore .
Martin Smith,

Risposte:


100

È sempre una cattiva pratica creare una transazione?

Dipende dal contesto in cui stai parlando qui. Se si tratta di un aggiornamento, consiglio vivamente di utilizzare esplicitamente TRANSAZIONI. Se è un SELEZIONA, NO (esplicitamente).

Ma aspetta che ci sia altro da capire prima: tutto in SQL Server è contenuto in una transazione.

Quando l'opzione di sessione IMPLICIT_TRANSACTIONSè OFFe si specifica esplicitamente begin trane commit/rollbackquindi questo è comunemente noto come Transazione esplicita . Altrimenti si ottiene una transazione con autocommit.

Quando IMPLICIT_TRANSACTIONSè ONuna transazione implicita viene avviata automaticamente quando si esegue uno dei tipi di dichiarazione documentati nell'articolo di libri online (ad es. SELECT/ UPDATE/ CREATE) E deve essere commessa o ripristinata esplicitamente. L'esecuzione di un BEGIN TRANin questa modalità aumenterebbe @@TRANCOUNTe avvierebbe un'altra transazione "nidificata")

Per cambiare la modalità in cui ti trovi, dovrai usare

SET IMPLICIT_TRANSACTIONS ON

o

SET IMPLICIT_TRANSACTIONS OFF

select @@OPTIONS & 2

se sopra restituisce 2, sei in modalità di transazione implicita. Se restituisce 0, sei in autocommit.

quanto costa la creazione di una transazione quando non è realmente necessario?

Le transazioni sono necessarie per portare il database da uno stato coerente a un altro stato coerente. Le transazioni non hanno costi in quanto non esistono alternative alle transazioni. Fare riferimento a: Utilizzo dei livelli di isolamento basati su Versioning di riga

Anche se stai usando un livello di isolamento read_uncomitted. È una cattiva pratica? perché non dovrebbe avere problemi con il blocco.

Il livello di isolamento READ_UNCOMMITED consentirà letture sporche per definizione, ad esempio una transazione sarà in grado di vedere le modifiche non confermate apportate da un'altra transazione. Ciò che fa questo livello di isolamento è che rilassa il sovraccarico di blocco - metodo di acquisizione dei blocchi per proteggere la concorrenza del database.

È possibile utilizzarlo a livello di connessione / query, in modo che non influisca su altre query.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Ho trovato un interessante articolo di Jeff Atwood che descrive Deadlocks dovuti a Dining Philosophers Puzzle e descrive il livello di isolamento dell'istantanea in lettura .

MODIFICARE:

Per curiosità, ho fatto alcuni test per misurare l'impatto su T-log con contatori Perfmon come Log Bytes Flushed / Sec, Log Flush Waits / Sec (Numero di commit al secondo che attendono che il flush di LOG si verifichi) come sotto grafico:

inserisci qui la descrizione dell'immagine

Codice d'esempio :

create table testTran (id int, Name varchar(8))
go

-- 19 sec
-- Autocommit transaction
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
---------------------------------------------------
-- 2 sec
-- Implicit transaction
SET IMPLICIT_TRANSACTIONS ON
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
COMMIT;
SET IMPLICIT_TRANSACTIONS OFF


----------------------------------------------------
-- 2 sec
-- Explicit transaction
declare @i int
set @i = 0
BEGIN TRAN
WHILE @i < 100000
Begin
INSERT INTO testTran values (1,'Kin Shah')
set @i = @i+1
End
COMMIT TRAN

Transazioni di autocommit : (modificato come evidenziato da @TravisGan)

  • L'inserimento ha richiesto 19 secondi.
  • Ogni Autocommit scaricherà il buffer T-log sul disco a causa di autocomit (dopo che @TravisGan è stato evidenziato e me ne sono perso la menzione).
  • Il processo CHECKPOINT si completerà rapidamente poiché la quantità di buffer di registro sporco da scaricare sarà inferiore poiché si esegue spesso in modalità silenziosa.

IMPLICIT & Transazione esplicita:

  • L'inserimento ha richiesto 2 secondi.
  • Per la transazione EXPLICIT, i buffer di registro verranno scaricati solo quando sono pieni.
  • Contrariamente alla transazione Autocommit, nella transazione EXPLICIT, il processo CHECKPOINT richiederà una durata maggiore poiché avrà più buffer di registro da scaricare (ricordare che i buffer di registro vengono scaricati solo quando sono pieni).

Esiste un DMV sys.dm_tran_database_transactions che restituirà informazioni sulle Transazioni a livello di database.

Ovviamente, questo è più una specie di test semplicistico per mostrare l'impatto. Altri fattori come il sottosistema del disco, le impostazioni di crescita automatica del database, le dimensioni iniziali del database, altri processi in esecuzione sullo stesso server \ database, ecc. Avranno anch'essi influenza.

Dai test di cui sopra, non vi è quasi alcuna differenza tra transazioni implicite ed esplicite.

Grazie a @TravisGan per aver contribuito ad aggiungere altro alla risposta.


35

Un'istruzione SQL viene sempre eseguita in una transazione. Se non ne avvii uno esplicitamente, ogni istruzione SQL verrà eseguita in una transazione autonoma.

L'unica scelta è se raggruppare più istruzioni in una transazione. Le transazioni che si estendono su più istruzioni lasciano blocchi che danneggiano la concorrenza. Quindi "sempre" creare una transazione non è una buona idea. È necessario bilanciare il costo con il vantaggio.


1

Il problema è se un gruppo di operazioni deve essere trattato come una singola azione. In altre parole, tutte le operazioni devono essere completate e impegnate correttamente o nessuna delle operazioni può essere impegnata. Se si dispone di uno scenario che richiede la lettura di dati preliminari e quindi l'esecuzione di aggiornamenti basati su tali dati, la lettura iniziale dovrebbe probabilmente far parte della transazione. Nota: sto evitando di selezionare / inserire / aggiornare di proposito. L'ambito della transazione può effettivamente essere a livello di applicazione e coinvolgere più operazioni di database. Pensa a modelli classici come la prenotazione del posto in aereo o la richiesta / il prelievo del saldo bancario. È necessario adottare una visione più ampia del problema per garantire che l'intera applicazione produca dati affidabili e coerenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.