¿Es una mala práctica crear siempre una transacción?

88

¿Es una mala práctica crear siempre una transacción?

Por ejemplo, ¿es una buena práctica crear una transacción para nada más que una simple SELECT?

¿Cuál es el costo de crear una transacción cuando no es realmente necesario?

Incluso si está utilizando un nivel de aislamiento como READ UNCOMMITTED, ¿es una mala práctica?

elranu
fuente
1
Mirar el impacto de BEGIN TRAN SELECT ... COMMITvs solo SELECTallí parece ser una diferencia de rendimiento extremadamente menor .
Martin Smith

Respuestas:

100

¿Es una mala práctica crear una transacción siempre?

Depende de qué contexto estás hablando aquí. Si se trata de una actualización, recomiendo utilizar TRANSACTIONS explícitamente. Si es un SELECT, entonces NO (explícitamente).

Pero espere, hay más para entender primero: todo en el servidor SQL está contenido en una transacción.

Cuando la opción de sesión IMPLICIT_TRANSACTIONSes OFFy se especifica de forma explícita begin trany commit/rollbackentonces esto se conoce comúnmente como una transacción explícita . De lo contrario, obtendrá una transacción de confirmación automática.

Cuándo IMPLICIT_TRANSACTIONSes ONuna transacción implícita se inicia automáticamente al ejecutar uno de los tipos de instrucciones documentados en el artículo en línea de los libros (por ejemplo, SELECT/ UPDATE/ CREATE) y debe confirmarse o revertirse explícitamente. La ejecución de a BEGIN TRANen este modo aumentaría @@TRANCOUNTe iniciaría otra transacción "anidada")

Para cambiar en qué modo estás, usarías

SET IMPLICIT_TRANSACTIONS ON

o

SET IMPLICIT_TRANSACTIONS OFF

select @@OPTIONS & 2

si lo anterior devuelve 2, está en modo de transacción implícita. Si devuelve 0, está en confirmación automática.

¿Cuánto es el costo de crear una transacción cuando no es realmente necesario?

Se necesitan transacciones para llevar la base de datos de un estado consistente a otro estado consistente. Las transacciones no tienen costo ya que no hay alternativa a las transacciones. Consulte: Uso de niveles de aislamiento basados ​​en versiones de fila

Incluso si está utilizando un nivel de aislamiento read_uncomitted. ¿Es una mala práctica? porque no debería tener problemas con el bloqueo.

El nivel de aislamiento READ_UNCOMMITED permitirá lecturas sucias por definición, es decir, una transacción podrá ver los cambios no confirmados realizados por otra transacción. Lo que hace este nivel de aislamiento es que relaja la sobrecarga del bloqueo: método de adquirir bloqueos para proteger la concurrencia de la base de datos.

Puede usar esto en un nivel de conexión / consulta, para que no afecte otras consultas.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Encontré un artículo interesante de Jeff Atwood que describe Deadlocks debido al Rompecabezas de Dining Philosophers y describe el nivel de aislamiento de instantáneas de lectura comprometida .

EDITAR:

Por curiosidad, hice algunas pruebas para medir el impacto en T-log con contadores de Perfmon como Log Bytes Flushed / Sec, Log Flush Waits / Sec (Número de confirmaciones por segundo que esperan que ocurra LOG flush) como se muestra en el siguiente gráfico:

ingrese la descripción de la imagen aquí

Código de muestra :

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

Transacciones de confirmación automática : (Editado como resaltado por @TravisGan)

  • Insertar tomó 19 segundos.
  • Cada confirmación automática vaciará el búfer de T-log en el disco debido a la autocompilación (después de que @TravisGan se resalte, y me perdí eso por mencionar).
  • El proceso CHECKPOINT se completará rápidamente ya que la cantidad de búfer de registro sucio que se debe vaciar será menor, ya que se ejecuta con frecuencia en silencio.

IMPLÍCITA y transacción explícita:

  • Insertar tomó 2 segundos.
  • Para las transacciones EXPLICITAS, las memorias intermedias de registro se eliminarán solo cuando estén llenas.
  • Contrariamente a la transacción de confirmación automática, en la transacción EXPLICIT, el proceso CHECKPOINT tomará más tiempo ya que tendrá más buffers de registro para vaciar (recuerde que los buffers de registro se vacían solo cuando están llenos).

Hay un DMV sys.dm_tran_database_transactions que devolverá información sobre las transacciones a nivel de base de datos.

Obviamente, esta es una especie de prueba simplista para mostrar el impacto. También influirán otros factores como el subsistema de disco, la configuración de crecimiento automático de la base de datos, el tamaño inicial de la base de datos, otros procesos que se ejecutan en el mismo servidor \ base de datos, etc.

De las pruebas anteriores, no hay casi ninguna diferencia entre las transacciones implícitas y explícitas.

Gracias a @TravisGan por ayudar a agregar más a la respuesta.

Kin Shah
fuente
35

Una instrucción SQL siempre se ejecuta en una transacción. Si no inicia una explícitamente, cada instrucción SQL se ejecutará en una transacción de sí misma.

La única opción es si agrupa múltiples declaraciones en una transacción. Las transacciones que abarcan varias declaraciones dejan bloqueos que perjudican la concurrencia. Entonces, "siempre" crear una transacción no es una buena idea. Debe equilibrar el costo con el beneficio.

Andomar
fuente
1

El problema es si un grupo de operaciones debe tratarse como una sola acción. En otras palabras, todas las operaciones deben completarse y confirmarse con éxito o ninguna de las operaciones puede confirmarse. Si tiene un escenario que requiere que lea datos preliminares y luego realice actualizaciones basadas en esos datos, entonces la lectura inicial probablemente debería ser parte de la transacción. Nota: Estoy evitando Seleccionar / Insertar / Actualizar a propósito. El alcance de la transacción puede estar realmente en el nivel de la aplicación e involucrar múltiples operaciones de bases de datos. Piense en patrones clásicos como Reserva de asiento de avión o Consulta / retirada de saldo bancario. Se debe tener una visión más amplia del problema para garantizar que toda la aplicación produzca datos confiables y consistentes.

Rayo
fuente