Podczas wydawania polecenia tworzenia kopii zapasowej w ramach procedury składowanej, która korzysta z try catch i dynamicznego SQL, komunikaty o błędach są bardzo ogólne w porównaniu z bezpośrednim uruchomieniem polecenia tworzenia kopii zapasowej.
Spróbuj / Złap w SP:
begin try
execute sp_executesql @sql; -- a backup command
end try
begin catch
print ERROR_MESSAGE(); -- save to log, etc.
end catch
Prowadzi do
50000: usp_Backup: 117: BACKUP DATABASE kończy się nieprawidłowo.
obszary wydające surowe polecenie:
backup DATABASE someDb to disk...
Wyniki w lepszych szczegółach:
Błąd wyszukiwania - błąd bazy danych SQL Server: Wystąpił nieodwracalny błąd we / wy w pliku „H: \ FolderName \ Filename.bak:” 112 (na dysku jest za mało miejsca).
Czy istnieje sposób na przechwycenie tych szczegółów w zmiennych w ramach procedury składowanej (w celu zalogowania, przekazania z powrotem do osoby dzwoniącej, w celu ponownej logiki)? Wygląda na to, że szczegóły przechodzą na kanale wiadomości, ale chciałbym, żeby były dostępne w SP.
źródło
Odpowiedzi:
Gdy
BACKUP DATABASE
generuje błąd, w rzeczywistości generuje dwa. NiestetyTRY/CATCH
nie jest w stanie uchwycić pierwszego błędu; wychwytuje tylko drugi błąd.Podejrzewam, że najlepszym rozwiązaniem, aby uchwycić prawdziwy powód nieudanej kopii zapasowej, jest zautomatyzowanie kopii zapasowych za pomocą SQLCMD (z
-o
wysyłaniem danych wyjściowych do pliku), SSIS, C #, PowerShell itp. Wszystko to daje znacznie większą kontrolę nad przechwytywaniem wszystkich błędów.Odpowiedź SO w komentarzu sugeruje użycie
DBCC OUTPUTBUFFER
- chociaż jest to możliwe, wcale nie wydaje się to dziecinną zabawą. Zapraszam do zabawy z tą procedurą ze strony Erlanda Sommarskoga , ale nadal nie działa to dobrze w połączeniu zTRY/CATCH
.Wydaje mi się, że jedynym sposobem na uchwycenie komunikatu o błędzie jest zgłoszenie
spGET_LastErrorMessage
błędu. Jeśli otoczysz go,TRY/CATCH
błąd zostanie połknięty, a procedura składowana nie spowoduje:W SQL Server <2012 nie można samodzielnie zgłosić błędu, ale można to zrobić w SQL Server 2012 i nowszych. Te dwie odmiany działają:
Lub w 2012 roku i powyżej, to działa, ale w dużym stopniu nie spełnia celu
TRY/CATCH
, ponieważ pierwotny błąd wciąż jest generowany:W obu przypadkach błąd jest nadal zgłaszany klientowi. Więc jeśli używasz
TRY/CATCH
tego, aby tego uniknąć, chyba że jest jakaś luka, o której nie myślę, obawiam się, że będziesz musiał dokonać wyboru ... albo dać użytkownikowi błąd i być w stanie uchwycić szczegółowe informacje na temat lub pomiń zarówno błąd, jak i rzeczywistą przyczynę.źródło
Wiem, że to stary wątek i wiem, że zamierzam zaproponować zawiły hack, ale na wszelki wypadek może pomóc każdemu, oto: Ponieważ te błędy tworzenia kopii zapasowych są rejestrowane, możesz użyć xp_readerrorlog blok, aby zeskrobać dziennik dla powiązanego komunikatu (błąd lub informacje). Możesz wyszukiwać w sieci parametry xp_readerrorlog, ale w skrócie możesz podać ciąg wyszukiwania i filtr czasu rozpoczęcia, które są przydatne w tym przypadku. Nie jestem pewien, czy pomogłoby to w ponownej logice, ale aby uchwycić informacje lub błędy w logowaniu, wpadłem na coś takiego ...
HTH
źródło
Możesz zapisać szczegóły błędu w tabeli. Możesz także utworzyć plik dziennika, ale może to wymagać wykonania CLR lub xp_cmdshell. Możesz również wysyłać pocztę z bazy danych, ale może to powodować problemy ze spamem i nie jest prawidłowym dziennikiem.
Stół jest najprostszy.
Spójrz na przykład Jeremy Kadlec podany w poniższym linku:
http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/
źródło
CATCH
. Dzieje się tak, ponieważ zwracany jest tylko ostatni komunikat o błędzie wERROR_MESSAGE()
...