Al emitir un comando de respaldo dentro de un procedimiento almacenado que utiliza un try catch y sql dinámico, los mensajes de error son muy generales en comparación con la ejecución directa del comando de respaldo.
Probar / Atrapar dentro de SP:
begin try
execute sp_executesql @sql; -- a backup command
end try
begin catch
print ERROR_MESSAGE(); -- save to log, etc.
end catch
Resultados en
50000: usp_Backup: 117: BACKUP DATABASE está terminando anormalmente.
cuando emitimos el comando sin procesar:
backup DATABASE someDb to disk...
Resultados en mejores detalles:
Error de búsqueda: error de la base de datos de SQL Server: se produjo un error de E / S no recuperable en el archivo "H: \ FolderName \ Filename.bak:" 112 (No hay suficiente espacio en el disco).
¿Hay alguna manera de capturar estos detalles en variables dentro del procedimiento almacenado (para iniciar sesión, pasar de nuevo a la persona que llama, para volver a intentar la lógica)? Parece que los detalles están llegando en el canal de mensajes, pero me gustaría que estén disponibles en el SP.
fuente
Respuestas:
Cuando
BACKUP DATABASE
genera un error, en realidad genera dos. LamentablementeTRY/CATCH
no es capaz de capturar el primer error; solo captura el segundo error.Sospecho que su mejor opción para capturar la verdadera razón detrás de una copia de seguridad fallida es automatizar sus copias de seguridad a través de SQLCMD (
-o
para enviar la salida a un archivo), SSIS, C #, PowerShell, etc. Todo lo cual le dará un control mucho mayor sobre la captura de todos de los erroresLa respuesta SO en el comentario sugiere usar
DBCC OUTPUTBUFFER
, aunque es posible, esto no parece un juego de niños en absoluto. Siéntase libre de divertirse con este procedimiento desde el sitio de Erland Sommarskog , pero aún así no parece funcionar bien en combinaciónTRY/CATCH
.La única forma en la que parecía capaz de capturar el mensaje de error
spGET_LastErrorMessage
es si se produce el error real. Si lo envuelve en unTRY/CATCH
error, el error se traga y el procedimiento almacenado no hace nada:En SQL Server <2012 no puede volver a generar el error usted mismo, pero puede hacerlo en SQL Server 2012 y versiones posteriores. Entonces estas dos variaciones funcionan:
O en 2012 y en adelante, esto funciona, pero en gran medida frustra el propósito de
TRY/CATCH
, ya que el error original aún se produce:En ambos casos, el error todavía se arroja al cliente, por supuesto. Entonces, si está utilizando
TRY/CATCH
para evitar eso, a menos que haya algún vacío legal en el que no esté pensando, me temo que tendrá que tomar una decisión ... ya sea dar el error al usuario y poder capturar detalles sobre o suprima tanto el error como la razón real.fuente
Bueno, sé que este es un hilo antiguo, y sé que lo que voy a proponer es un truco complicado, pero en caso de que pueda ayudar a alguien, aquí va: dado que estos errores de copia de seguridad se registran, puede usar xp_readerrorlog en la captura bloque para raspar el registro para el mensaje relacionado (error o información). Puede buscar en Google los parámetros xp_readerrorlog, pero en resumen puede especificar una cadena de búsqueda y un filtro de tiempo de inicio que son útiles en este caso. No estoy seguro de si esto ayudaría a su lógica de reintento, pero para capturar información o errores para iniciar sesión, se me ocurrió algo como esto ...
HTH
fuente
Puede registrar los detalles del error en una tabla. También puede crear un archivo de registro, pero eso puede requerir un CLR o xp_cmdshell para hacerlo. También puede enviar correo de la base de datos, pero eso puede causar problemas de spam y no es un registro adecuado.
La tabla es más simple.
Mire el ejemplo de Jeremy Kadlec provisto en el siguiente enlace:
http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/
fuente
CATCH
. Esto se debe a que solo se devuelve el último mensaje de error enERROR_MESSAGE()
...