Запланированное задание резервного копирования не всегда выполняет резервное копирование всех баз данных, несмотря на то, что всегда говорится, что задание выполнено успешно


9

У меня есть работа в SQL 2008, которая запускает сохраненный процесс для резервного копирования всех баз данных. Это выполняется ежедневно через работу агента sql server.

Он завершается успешно каждый день, но в некоторые дни он завершается успешно только после резервного копирования нескольких баз данных. Это может быть разное количество баз данных каждый раз. В большинстве случаев он успешно создает резервные копии всех баз данных, но иногда успешно выполняется резервное копирование 2, иногда 5 и т. Д.

Я не вижу ошибок в истории заданий, просмотра событий или журнала сервера SQL.

Резервное копирование выполняется на локальный диск, хотя папка является «соединением» с папкой на расширяемом томе хранилища.

Операционная система - Windows 2003 64-разрядная, работающая под управлением 64-разрядной версии Sql Server 2008 Web, в качестве виртуальной машины, работающей на хосте 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.database, который заменяет sysdatabase и читал флаги:

-- 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.database
Питер Шофилд

2

Проверьте на наличие ошибок после команды «backup», отправьте свой собственный адрес электронной почты для любых обнаруженных ошибок.

Это даст вам отправную точку, чтобы увидеть, что происходит, и гарантированно предупредит вас о любых проблемах, пока у вас не будет решена проблема с работой.


2

Поместите заказ на курсор. Я видел, что у курсоров в sys.database есть «проблемы», когда вы разрешаете SQL выбирать порядок возврата данных. Заказ по имени должно быть достаточно.


2

Резервное копирование выполняется одновременно с резервным копированием на ленту или каким-либо другим процессом, копирующим или получающим доступ к файлам резервной копии? Если так, я бы поспорил, что он не может перезаписать файл, потому что он используется. Если у вас есть место для нескольких резервных копий, вы можете изменить процедуру, чтобы добавить отметку даты в выходной файл, но тогда вам понадобится процедура очистки.


Не то, чтобы я знал. Резервное копирование выполняется локально, а через несколько часов - rsync-ed.
Энди Дэвис

0

С введением SQL Server 2005 цикл курсора через sysdatabase и даже sys.databases изменился, поэтому он стал ненадежным - и это изменение в поведении можно увидеть и в sp_foreachdb.

Мне показалось, что изменение типа курсора помогло (я думаю, что это было быстро), но в конечном итоге я переключился на такие решения, как решение для резервного копирования и обслуживания Олы Хелленгрен. Как и большинство важных вещей, таких как резервное копирование, вам все равно нужно перепроверить все базы данных, чтобы убедиться, что они резервируются даже с этими потенциальными решениями - и вы, очевидно, сделали это, молодец!

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

Решение Олы по техническому обслуживанию: 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.

Спасибо, Гаурав Мишра | Старший администратор

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.