È 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
è OFF
e si specifica esplicitamente begin tran
e commit/rollback
quindi questo è comunemente noto come Transazione esplicita . Altrimenti si ottiene una transazione con autocommit.
Quando IMPLICIT_TRANSACTIONS
è ON
una 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 TRAN
in questa modalità aumenterebbe @@TRANCOUNT
e 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:
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.
BEGIN TRAN SELECT ... COMMIT
vs soloSELECT
sembra esserci una differenza di prestazioni estremamente minore .