Tengo un problema similar al The current transaction cannot be committed and cannot support operations that write to the log file, pero tengo una pregunta de seguimiento.Error de transacción SQL: la transacción actual no se puede confirmar y no puede admitir operaciones que escriben en el archivo de registro
La respuesta no hace referencia a Using TRY...CATCH in Transact-SQL, que voy a volver en un segundo ...
Mi código (heredado, por supuesto) tiene la forma simplificada:
SET NOCOUNT ON
SET XACT_ABORT ON
CREATE TABLE #tmp
SET @transaction = 'insert_backtest_results'
BEGIN TRANSACTION @transaction
BEGIN TRY
--do some bulk insert stuff into #tmp
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'bulk insert error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
'; check backtestfiles$ directory for error files ' +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -666
END CATCH
BEGIN TRY
EXEC usp_other_stuff_1 @whatever
EXEC usp_other_stuff_2 @whatever
-- a LOT of "normal" logic here... inserts, updates, etc...
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -777
END CATCH
RETURN 0
creo que tengo suficiente información para jugar con ella y resolverla yo mismo ... desafortunadamente reproducir el error está resultando casi imposible. Así que espero que preguntar aquí ayude a aclarar mi comprensión del problema y la solución.
Este procedimiento almacenado es, de forma intermitente, arrojando errores como éste:
error importing results for backtest 9649 error_number: 3930 error_message: The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. error_severity: 16 error_state 1 error_line: 217
Así que, obviamente, el error viene del segundo bloque catch
Sobre la base de lo que he leído en Using TRY...CATCH in Transact-SQL, me piense que lo que sucede es que cuando se lanza la excepción, el uso de XACT_ABORT
está causando que la transacción "finalice y se retrotraiga" ... y entonces la primera línea del BEGIN CATCH
intenta ciegamente volver atrás.
No sé por qué el desarrollador original habilitado XACT_ABORT
, así que estoy pensando que la mejor solución (de eliminarlo) sería utilizar XACT_STATE()
sólo para hacer retroceder si hay una transacción (<>0
). ¿Eso suena razonable? ¿Me estoy perdiendo de algo?
Además, la mención de iniciar sesión en el mensaje de error me hace preguntarme: ¿Hay otro problema, potencialmente con la configuración? ¿Nuestro uso de RAISEERROR()
en este escenario contribuye al problema? ¿Eso se registra, en algún tipo de caso donde el registro no es posible, como se alude al mensaje de error?
Su plantilla supone transacciones dentro del bloque try; tenemos múltiples bloques de prueba dentro de 1 transacción. –
@ Adam: Se trata de cómo manejas el 'XACT_STATE' y las transacciones en el bloque CATCH. Puedes tener múltiples bloques de prueba en una transacción usando esta misma plantilla. La idea es comprender cómo interactúan las transacciones y los bloques catch, y como bonificación también se manejan las transacciones anidadas y los puntos de rescate, lo cual es muy útil en el procesamiento por lotes, ya que permite reanudar el resto del lote incluso si la entrada había fallado –
He seguido adelante y envolví la declaración de reversión en un 'si XACT_STATE() <> 0', pero solo el tiempo dirá si eso lo resuelve por nosotros. Supongo que seguiré adelante y acepto tu respuesta por el momento. –