收缩在SQL 2008中记录所有用户数据库

时间:2010-10-05 23:58:27

标签: sql-server sql-server-2008

您好我在每周维护过程中使用此脚本,建议使用最佳方法/脚本来进行收缩日志。目前我正在使用以下脚本收到错误

declare @s nvarchar(4000)
set @s= '
        if ''?'' not in (''tempdb'',''master'',''model'',''msdb'') 
        begin
            use [?] 
            Alter database [?] SET Recovery simple
        end '

exec sp_msforeachdb @s
set @s= '
        if ''?'' not in (''tempdb'',''master'',''model'',''msdb'') 
        begin     
            use [?]  
            Declare @LogFileLogicalName sysname
            select @LogFileLogicalName=Name from sys.database_files where Type=1
            DBCC Shrinkfile(@LogFileLogicalName,1) 
        end'
exec sp_msforeachdb @s

错误说明:

  

ShrinkLog执行SQL任务描述:执行查询“declare @s nvarchar(4000)set @ s ='...”失败,出现以下错误:“无法在数据库'tempdb'中设置选项'RECOVERY'。不能收缩日志文件2(DBServices_Log)因为逻辑日志文件的总数不能少于2. DBCC执行完成。如果DBCC打印出错误消息,请联系您的系统管理员。

注意:我在脚本中避免使用tempdb(所有系统数据库),但错误消息显示tempdb?

2 个答案:

答案 0 :(得分:3)

这可能是我去年见过的最糟糕的维护脚本。每周打破日志链并使数据库无法恢复的维护脚本?我的天啊。更不用说缩小日志维护任务的简单前提是错误的。如果数据库日志已增长到某个大小,则需要该大小。更频繁地安排日志备份以防止这种情况,但不要安排日志缩减操作。

答案 1 :(得分:0)

通过使用exec语句来更改数据库恢复模型,可以避免5058错误。以下脚本将每个用户数据库设置为简单恢复模型。 (它使用Jimmy's answer来检测系统数据库。)

exec sp_msforeachdb 'if exists (select name from sys.databases d where case when d.name in (''master'',''model'',''msdb'',''tempdb'') then 1 else d.is_distributor end = 0
    and name = ''?'' and recovery_model_desc != ''SIMPLE'')
begin
    declare @previousRecoveryModel varchar(100) = (select recovery_model_desc from sys.databases where name = ''?'');
    print ''Changing recovery model for ? from '' + @previousRecoveryModel + '' to SIMPLE.'';
    use master;
    -- Using exec avoids a compile-time 5058 error about tempdb, which is a branch that will never be executed in this code.
    exec (''alter database [?] set recovery simple'');
end';

然后你不会得到关于tempdb的编译时错误,因为exec语句将使用已经替换的数据库名称变量编译它的语句。