É uma má prática sempre criar uma transação?

88

É uma má prática sempre criar uma transação?

Por exemplo, é uma boa prática criar uma transação apenas para uma simples SELECT?

Qual é o custo de criar uma transação quando ela não é realmente necessária?

Mesmo se você estiver usando um nível de isolamento como READ UNCOMMITTED, é uma prática ruim?

elranu
fonte
1
Olhando para o impacto de BEGIN TRAN SELECT ... COMMITvs apenas SELECTparece haver uma diferença de desempenho extremamente pequena .
Martin Smith

Respostas:

100

É 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é OFFe você explicitamente especificar begin trane 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é ONuma 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 TRANnesse modo aumentaria @@TRANCOUNTe 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:

insira a descrição da imagem aqui

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.

Kin Shah
fonte
35

Uma instrução SQL sempre é executada em uma transação. Se você não iniciar uma explicitamente, cada instrução SQL será executada em uma transação por si mesma.

A única opção é se você agrupa várias instruções em uma transação. As transações que abrangem várias instruções deixam bloqueios que prejudicam a simultaneidade. Portanto, "sempre" a criação de transações não é uma boa ideia. Você deve equilibrar o custo com o benefício.

Andomar
fonte
1

A questão é se um grupo de operações deve ser tratado como uma única ação. Em outras palavras, todas as operações devem ser concluídas e confirmadas com sucesso ou nenhuma das operações pode ser confirmada. Se você tiver um cenário que exige que você leia dados preliminares e execute atualizações com base nesses dados, a leitura inicial provavelmente deve fazer parte da transação. Nota: Estou evitando Selecionar / Inserir / Atualizar de propósito. O escopo da transação pode realmente estar no nível do aplicativo e envolver várias operações de banco de dados. Pense em padrões clássicos, como Reserva de assento de avião ou Consulta / retirada de saldo bancário. É preciso ter uma visão mais ampla do problema para garantir que todo o aplicativo produz dados confiáveis ​​e consistentes.

Raio
fonte