Заплановане завдання резервного копіювання не завжди створює резервну копію всіх баз даних, незважаючи на те, що робота завжди є успішною


9

У мене є робота в SQL 2008, яка виконує збережену процедуру для резервного копіювання всіх баз даних. Це працює щодня через роботу агента sql сервера.

Він закривається з успіхом щодня, але через кілька днів він закінчується з успіхом лише після створення резервної копії декількох баз даних. Кожен раз може бути різна кількість баз даних. Більшість днів він успішно створює резервні копії всіх баз даних, але іноді успішно створює 2 резервні копії, іноді 5 тощо.

Я не бачу жодних помилок в історії роботи, переглядачі подій або журналі sql сервера.

Резервне копіювання відбувається на локальному диску, хоча папка є "з'єднанням" з папкою на розширюваному обсязі зберігання.

Операційна система Windows 2003 64-бітна з 64-бітною версією Sql Server 2008, веб-видання 64, як віртуальна машина, що працює на хості Vmware ESXi 5.

Збережена процедура:

ALTER PROCEDURE [dbo].[backup_all_databases] 
@path VARCHAR(255)='c:\backups\'

AS

DECLARE @name VARCHAR(50) -- database name  
DECLARE @fileName VARCHAR(256) -- filename for backup  
DECLARE @fileDate VARCHAR(20) -- used for file name 
DECLARE @dbIsReadOnly sql_variant -- is database read_only?
DECLARE @dbIsOffline sql_variant -- is database offline?

DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('tempdb')
AND version > 0 AND version IS NOT NULL

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @name   

WHILE @@FETCH_STATUS = 0   
BEGIN   
SET @fileName = @path + @name + '.bak'

SET @dbIsReadOnly = (SELECT DATABASEPROPERTY(@name, 'IsReadOnly')) -- 1 = Read Only
SET @dbIsOffline = (SELECT DATABASEPROPERTY(@name, 'IsOffline')) -- 1 = Offline

IF (@dbIsReadOnly = 0 OR @dbIsReadOnly IS NULL) AND @dbIsOffline =0
BEGIN
    BACKUP DATABASE @name TO DISK = @fileName  WITH INIT
    WAITFOR DELAY '00:00:20'
END

FETCH NEXT FROM db_cursor INTO @name 
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

Будь-які пропозиції, будь ласка?

Відповіді:


9

Я б додав блоки TRY / CATCH для обробки помилок та їх реєстрації. БД може бути в одному користувачі, відновлюється чи будь-що інше.

Без цього помилки можуть бути скасовані таким чином, що жодних помилок не реєструється (заява, пакет, область, з'єднання тощо)

З TRY / CATCH тоді реєструється все, крім помилок компіляції чи з'єднання, що припиняють роботу? але я сумніваюся, що це так.

Я також би використовував sys.databases, який замінює sysdatabases та читає більше прапорів:

-- declares etc

BEGIN TRY

    DECLARE db_cursor CURSOR FOR  
    SELECT name, state, user_access
    FROM sys.databases 
    WHERE name NOT IN ('tempdb')

    OPEN db_cursor   
    FETCH NEXT FROM db_cursor INTO @name, @state, @user_access

    WHILE @@FETCH_STATUS = 0   
    BEGIN   

        SET @fileName = @path + @name + '.bak'
        IF @state = 0 AND user_access = 0
        BEGIN
            BEGIN TRY
                BACKUP DATABASE @name TO DISK = @fileName  WITH INIT
            END TRY
            BEGIN CATCH
                -- log but do not rethrow so loop continues
            END CATCH
            WAITFOR DELAY '00:00:20'
        END
        ELSE
           --log user and/or state issues

        FETCH NEXT FROM db_cursor INTO @name 
    END   

    CLOSE db_cursor   
    DEALLOCATE db_cursor

END TRY
BEGIN CATCH
  -- some useful stuff here
END CATCH

+1 за пораду щодо використання sys.databases
Пітер Шофілд

2

Перевірте наявність помилок після команди «резервного копіювання», надішліть власну електронну пошту на наявність виявлених помилок.

Це дасть вам вихідну точку для того, щоб побачити, що відбувається, і гарантує вам сповістити про будь-які проблеми, поки у вас не буде вирішено питання роботи.


2

Наведіть замовлення на курсор. Я бачив, що курсори для sys.databases мають "проблеми", коли ви дозволяєте SQL вибирати порядок повернення даних. Замовлення по імені повинно вистачити.


2

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


Не те, що мені відомо. Резервне копіювання робиться локально, а потім через декілька годин після rsync-ed.
Енді Девіс

0

З впровадженням SQL Server 2005 цикл курсора через системні бази та навіть sys.databases змінився, тому він не був надійним - і цю зміну поведінки можна було побачити і з sp_foreachdb.

Я виявив, що зміна типу курсора допомогла (я думаю, це було швидко вперед), але врешті-решт я перейшов до таких рішень, як рішення резервного копіювання та обслуговування Ola Hallengren. Як і більшість найважливіших речей, таких як резервне копіювання, вам все одно потрібно перехресно перевірити всі бази даних, щоб переконатися, що вони є резервними копіями навіть із цими потенційними рішеннями - і ви, очевидно, це зробили, так добре!

Типи курсорів: http://msdn.microsoft.com/en-us/library/ms378405(v=SQL.90).aspx

Рішення з технічного обслуговування Ola: http://ola.hallengren.com/


0

У мене була така ж проблема, особливо під час резервного копіювання великих БД.

@@fetch_statusє змінною GLOBAL, тому вона може бути змінена (встановлена ​​на 0) іншим курсором, ніж ваш. Я вирішив це, зробивши наступне (у псевдокоді):

create a temp table with dbNames
select top 1 in a variable (use order by)
while variable is null
do your thing

set variable = null
delete top 1(use order by)
select top 1 in a variable (use order by)
loop

-1

Я намагався розібратися в цій проблемі, і, здається, багато разів користувачі опублікували рішення, що якщо ви зробите декларацію курсору нечутливою, вона почне працювати. Тому я перевірив це, і так, це просто переконайтеся, що курсор оголошує статичним, і він почне працювати.

Справа в тому, що це не вдається - Перевірте встановлення порогу порогового значення курсору на рівні сервера - якщо він налаштований як -1, це означає, що всі курсори заповнюються синхронно іншими словами, намагаючись прочитати дані набору клавіш курсора синхронізовані, і все намагається читати одночасно. Якщо ми змінимо це значення на 0, що вказує SQL-серверу робити асинхронну сукупність простими словами, курсор може отримати записи, тоді як набір ключів все ще буде заповнюватися, і ви побачите, що виконавши цю зміну на рівні сервера, ви ніколи не пропустите жодну базу даних, використовуючи курсори.

Рішення: або оголосіть курсор статичним або змініть налаштування рівня сервера «Поріг курсору» на 0 з -1.

Спасибі, Гаурав Мішра | Старший DBA

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.