É uma prática ruim criar sempre uma transação?
Depende do contexto em que você está falando aqui. Se for uma atualização, eu recomendo usar TRANSACTIONS explicitamente. Se for um SELECT, NÃO (explicitamente).
Mas espere, há mais para entender primeiro: tudo no servidor sql está contido em uma transação.
Quando a opção de sessão IMPLICIT_TRANSACTIONS
é OFF
e você explicitamente especificar begin tran
e commit/rollback
, em seguida, este é comumente conhecido como uma transação explícita . Caso contrário, você obterá uma transação de confirmação automática.
Quando IMPLICIT_TRANSACTIONS
é ON
uma transação implícita é iniciado automaticamente ao executar um dos tipos de declaração documentada nos livros artigo on-line (por exemplo, SELECT
/ UPDATE
/ CREATE
) e deve ser confirmada ou revertida de forma explícita. A execução de um BEGIN TRAN
nesse modo aumentaria @@TRANCOUNT
e iniciaria outra transação "aninhada")
Para alternar em que modo você está, use
SET IMPLICIT_TRANSACTIONS ON
ou
SET IMPLICIT_TRANSACTIONS OFF
select @@OPTIONS & 2
se acima retornar 2, você estará no modo de transação implícita. Se retornar 0, você estará na confirmação automática.
quanto custa o custo de criar uma transação quando não é realmente necessário?
As transações são necessárias para levar o banco de dados de um estado consistente para outro estado consistente. As transações não têm custo, pois não há alternativa às transações. Consulte: Usando níveis de isolamento baseados em controle de versão de linha
Mesmo se você estiver usando um nível de isolamento, read_uncomitted. É uma má prática? porque não deve ter problemas com o bloqueio.
O nível de isolamento READ_UNCOMMITED permitirá leituras sujas por definição, ou seja, uma transação poderá ver alterações não confirmadas feitas por outra transação. O que esse nível de isolamento faz é relaxar a sobrecarga do bloqueio - método de aquisição de bloqueios para proteger a simultaneidade do banco de dados.
Você pode usar isso no nível de conexão / consulta, para que não afete outras consultas.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Encontrei um artigo interessante de Jeff Atwood descrevendo Deadlocks devido ao Dining Philosophers Puzzle e descrevendo o nível de isolamento de snapshots comprometidos por leitura .
EDITAR:
Por curiosidade, fiz alguns testes para medir o impacto no T-log com contadores Perfmon como Log Bytes Flushed / Sec, Log Flush Waits / Sec (número de confirmações por segundo que estão aguardando a liberação do LOG) conforme o gráfico abaixo:
Código de amostra :
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
Transações de confirmação automática : (Editado como destacado por @TravisGan)
- A inserção levou 19 segundos.
- Cada confirmação automática liberará o buffer T-log no disco devido à confirmação automática (depois que o @TravisGan estiver destacado, e eu perdi isso para mencionar).
- O processo CHECKPOINT será concluído rapidamente, pois a quantidade de buffer de log sujo necessária para ser liberada será menor, pois ele fica silencioso com frequência.
Transação implícita e explícita:
- A inserção levou 2 segundos.
- Para transações EXPLICIT, os buffers de log serão liberados apenas quando estiverem cheios.
- Ao contrário da transação de confirmação automática, na transação EXPLICIT, o processo CHECKPOINT levará mais tempo, pois terá mais buffers de log para liberar (lembre-se de que os buffers de log são liberados somente quando estão cheios).
Existe um DMV sys.dm_tran_database_transactions que retornará informações sobre transações no nível do banco de dados.
Obviamente, esse é mais um teste simplista para mostrar o impacto. Outros fatores, como o subsistema de disco, as configurações de crescimento automático do banco de dados, o tamanho inicial do banco de dados, outros processos em execução no mesmo servidor \ banco de dados, etc. também terão influência.
Dos testes acima, não há quase nenhuma diferença entre transações implícitas e explícitas.
Agradecemos a @TravisGan por ajudar a adicionar mais à resposta.
BEGIN TRAN SELECT ... COMMIT
vs apenasSELECT
parece haver uma diferença de desempenho extremamente pequena .