尽管总是说作业成功,但计划备份任务并不总是备份所有数据库


9

我在SQL 2008中有一项工作,该工作运行存储的proc来备份所有数据库。这每天通过sql server agent作业运行。

它每天都会成功退出,但是有些时候只有备份了一些数据库后才能成功退出。每次可以有不同数量的数据库。大多数情况下,它成功备份了所有数据库,但有时成功备份了2个,有时成功备份了5个,等等。

我在作业历史记录,事件查看器或SQL Server日志中看不到任何错误。

尽管该文件夹是可扩展存储卷上文件夹的“连接”,但备份仍在本地磁盘上进行。

操作系统是Windows 2003 64位,作为运行在Vmware ESXi 5主机上的虚拟机运行Sql Server 2008 Web版64位。

存储过程:

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

有什么建议吗?

Answers:


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的建议
Peter Schofield

2

在“备份”命令后检查错误,并发送您自己的电子邮件以检测到任何错误。

这将为您提供一个起点,让您了解正在发生的事情,并保证在出现问题之前提醒您所有问题。


2

在光标上下一个命令。当您允许SQL选择返回数据的顺序时,我已经看到sys.databases的游标有“问题”。按名称订购就足够了。


2

备份与磁带备份或其他复制或访问备份文件的进程同时运行吗?如果是这样,我敢打赌它正在使用中,因此无法覆盖文件。如果您有空间容纳多个备份副本,则可以更改proc以便在输出文件中添加日期戳,但是随后需要清理例程。


不是我知道的。备份是在本地完成的,然后在几个小时后进行异地同步。
安迪·戴维斯

0

随着SQL Server 2005的引入,遍历sysdatabases甚至sys.databases的光标循环似乎发生了变化,因此它并不可靠-行为的变化也可以通过sp_foreachdb看到。

我发现更改游标的类型有帮助(我认为这是快速前进的方法),但最终我切换到了诸如Ola Hallengren的备份和维护解决方案之类的解决方案。像大多数至关重要的事情(例如备份)一样,您仍然需要交叉检查所有数据库以确保即使使用这些潜在解决方案也可以备份它们-而且您显然做得很好!

游标类型:http : //msdn.microsoft.com/zh-cn/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 Server用简单的单词进行异步填充,则游标可以获取记录,而键集仍将填充,并且您将看到在服务器级别进行此更改之后,您将永远不会错过任何使用游标。

解决方案:声明“ Cursor Static”或将“ Cursor Threshold”的服务器级别设置从-1设置为0。

谢谢,Gaurav Mishra | 高级DBA

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.