Як увімкнути дані про помилки під час використання команд try / catch для динамічних команд резервного копіювання SQL


10

При видачі команди резервного копіювання в межах збереженої процедури, яка використовує спробу вловлювання та динамічного sql, повідомлення про помилки є дуже загальними в порівнянні з безпосередньо виконанням команди резервного копіювання.

Спробуйте / ловіть в рамках SP:

    begin try
        execute sp_executesql @sql;  -- a backup command
    end try
    begin catch  
        print ERROR_MESSAGE();  -- save to log, etc.
    end catch

Призводить до

50000: usp_Backup: 117: БЕЗПЕКА БАТАБАЗИ закінчується аномально.

qare видає необроблену команду:

    backup DATABASE someDb to disk...

Результати в більш детальних деталях:

Помилка пошуку - помилка бази даних SQL Server: у файлі "H: \ FolderName \ Filename.bak:" 112 (на диску не вистачає місця) сталася помилка, яку не можна відновити

Чи є спосіб зафіксувати ці деталі у змінних у межах збереженої процедури (увійти в систему, перейти назад до абонента, для повторної логіки)? Здається, деталі надходять на каналі повідомлень, але я хотів би, щоб вони були доступні в рамках SP.


Ви можете побачити це: stackoverflow.com/questions/5966670/…
8 кб,

Відповіді:


13

Коли BACKUP DATABASEвиникає помилка, вона фактично генерує дві. На жаль TRY/CATCH, не здатний зафіксувати першу помилку; він фіксує лише другу помилку.

Я підозрюю, що найкраща ставка, щоб зафіксувати справжню причину невдалої резервної копії, - це автоматизувати резервні копії через SQLCMD-oнадсиланням виводу у файл), SSIS, C #, PowerShell тощо. Все це дасть вам набагато більший контроль над захопленням усіх помилок.

Відповідь ТА у коментарі пропонує використовувати DBCC OUTPUTBUFFER- хоча це можливо, це зовсім не здається дитячою грою. Не соромтеся розважитися цією процедурою з сайту Ерланда Соммарського , але це все ще не працює добре в поєднанні з TRY/CATCH.

Єдиний спосіб, з якого я, здається, зможу зафіксувати повідомлення про помилку spGET_LastErrorMessage- це, якщо дійсна помилка все-таки буде кинута. Якщо ви обернете його TRY/CATCHпомилкою, котрий помилка проковтується, а збережена процедура нічого не робить:

BEGIN TRY
  EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
  EXEC dbo.spGet_LastErrorMessage;
END CATCH

У SQL Server <2012 ви не можете самостійно підвищити помилку, але ви можете в SQL Server 2012 та новіших версіях. Отже, ці дві варіанти працюють:

CREATE PROCEDURE dbo.dothebackup
AS
BEGIN
  SET NOCOUNT ON;
  EXEC sp_executesql N'backup that fails...';
END
GO

EXEC dbo.dothebackup;
EXEC dbo.spGET_LastErrorMessage;

Або в 2012 році і вище, це працює, але значною мірою перемагає мету TRY/CATCH, оскільки первісна помилка все-таки викидається:

CREATE PROCEDURE dbo.dothebackup2
AS
BEGIN
  SET NOCOUNT ON;
  BEGIN TRY
    EXEC sp_executesql N'backup that fails...';
  END TRY
  BEGIN CATCH
    THROW;
  END CATCH
END
GO

EXEC dbo.dothebackup2;
EXEC dbo.spGET_LastErrorMessage;

В обох цих випадках помилка все-таки кидається на клієнта. Тож якщо ви використовуєте це, TRY/CATCHщоб уникнути цього, якщо не існує лазівки, про яку я не замислююся, боюся, вам доведеться зробити вибір ... або надати користувачеві помилку і мати змогу фіксувати деталі про це або придушити як помилку, так і фактичну причину.


Як би смішно це не виглядало, підхід Соммарського не викликає сумнівів, якщо я просто хотів надати певний контекст для абонента в інтерфейсі. Краще, ніж починати окремий процес. Ви хочете сказати, що він не працюватиме в СЛУЧАЙ / СЛУЧАЙ?
crokusek

@crokusek Я спробував одну варіацію, і результат вийшов порожнім. Я дам сьогодні ще один знімок.
Аарон Бертран

У разі відсутності помилок, чи отримує LastErrorMessage () результати будь-якої попередньої помилки від сеансу? Тоді, якщо останні два виконавці виконуються як скрипт, можливо, перший виконавець може бути зафіксований у межах try / catch та всередині catch, встановити змінну, а потім повторно кинути. Тоді LastError викликається, лише якщо встановлена ​​змінна. Припускає, що повторний кидок не пропускає 2-й дзвінок, який, на мою думку, зазвичай відповідає дійсності в сценарії. Зрештою, я не можу використати такий підхід, врешті-решт, тому що він не може бути поміщений в ІП, якщо я правильно розумію. Дякую, хоча!
crokusek

2

Ну я знаю, що це стара тема, і я знаю, що я збираюся запропонувати, це перекручений хак, але на всякий випадок, коли це може допомогти комусь, ось що йде: Оскільки ці помилки резервного копіювання заносяться, ви можете використовувати xp_readerrorlog в улові блок, щоб скребти журнал на пов’язане повідомлення (помилка чи інформація). Ви можете переглядати параметри xp_readerrorlog, але коротко кажучи, ви можете вказати рядок пошуку та фільтр часу початку, які корисні в цьому випадку. Не впевнений, чи це допоможе вашій логіці спроби, але для отримання інформації або помилок для ведення журналу я придумав щось подібне ...

IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results (LogDate datetime,ProcessInfo nvarchar(100),LogText nvarchar(4000))
BEGIN TRY
SELECT @begintime = GETDATE()
EXEC sp_executesql @SQL --your backup statement string
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'backed up',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'Backup' order by logdate desc
END TRY
BEGIN CATCH
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'Backup',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'spid'+cast(@@SPID as varchar(6)) order by logdate desc
END CATCH
PRINT @result

HTH


Це чудово підходить для деяких поширених помилок, але є деякі помилки, які, мабуть, потрапляють безпосередньо безпосередньо клієнту. Журнал sp_readerrorlog буде містити повідомлення, що говорять про "журнал додатків", де я припускаю, що під "застосуванням" вони мають на увазі зовнішній процес, який видає команди. SO Link
crokusek

0

Ви можете записати дані про помилку до таблиці. Ви також можете створити файл журналу, але для цього може знадобитися CLR або xp_cmdshell. Ви також можете надсилати пошту до бази даних, але це може спричинити проблеми зі спамом та не є належним журналом.

Таблиця найпростіша.

  1. Створіть таблицю для зберігання помилок
  2. Створіть збережену процедуру, яка вставляється в таблицю помилок
  3. Викличте збережену процедуру в блоці лову

Подивіться приклад Джеремі Кадлека, поданий за посиланням нижче:

http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/


3
Проблема не в тому, що робити з помилками, а в тому, що відповідне повідомлення про помилку недоступне для деяких команд всередині CATCH. Це тому, що повертається лише останнє повідомлення про помилку ERROR_MESSAGE()...
Аарон Бертран
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.