¿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_TRANSACTIONS
es OFF
y se especifica de forma explícita begin tran
y commit/rollback
entonces 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_TRANSACTIONS
es ON
una 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 TRAN
en este modo aumentaría @@TRANCOUNT
e 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:
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.
BEGIN TRAN SELECT ... COMMIT
vs soloSELECT
allí parece ser una diferencia de rendimiento extremadamente menor .