2013-07-24 128 views
0

我有一个奇怪的问题。我有一个数据库,名为restorelogs从SQL Server恢复差异备份

自动备份脚本执行完整备份,之后每隔3小时进行一次差异备份。 第二天再做一次,然后再次比较,依此类推。

不,我想写一个脚本,什么是恢复这个文件int restorelogs数据库。

从PHP我通过SQLSRV使用这些SQL查询:

USE master; 
ALTER DATABASE restorelogs SET MULTI_USER WITH ROLLBACK IMMEDIATE; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307151435.bak' WITH REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307151745diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307152045diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307152345diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307160245diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307160545diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307160845diff.bak' WITH FILE= 1, REPLACE, NORECOVERY; 
RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307161145diff.bak' WITH FILE= 1, REPLACE, RECOVERY; 

现在会自带游戏的有趣的部分。

如果我将这些查询复制到SQL Server Management Studio中并运行它,它可以正常工作。有表格,没有错误信息,一切都很好。

但是。当我尝试从php中完成时,数据库以恢复模式离开。

当我通读很多页面时,我明白了,最后一个查询需要包含RECOVERY选项来恢复数据库(我也尝试在第一次查询时不使用REPLACE)。

它怎么会发生?

请帮帮我,我错了什么。

更新:基于亚当评论:我完全试图做到这一点。我收集备份文件,并使用第一个(全部),NORECOVERY,REPLACE和最后一个WITH RECOVERY。

这是我尝试: 功能pushToDatabase($文件){

$dbh = new Database(); 
$dbh->query("USE master"); 
pre($dbh->errorInfo(), 0); 
$cnt = count($files); 
$i = 0; 
foreach ($files as $file) { 
    $withFile = ''; 
    $option = ''; 
    $moves = ''; 
    if ($i == 0) { 
    //restoreFromDisk($file); 
    //truncateDatabase(); 
    $option = " NORECOVERY, REPLACE"; 
    } else { 
    $option = " RECOVERY"; 
    } 
    if ($i > 0) { 
    $withFile = " FILE=1, "; 
    } 
    if ($i == 0 || $i == count($files) - 1) { 
    $sql = "RESTORE DATABASE " . DB_NAME . " FROM DISK = '" . $file . "' WITH " . $withFile . $option . ";"; 
    echo $sql . "<br />"; 
    $dbh->exec($sql); 
    pre($dbh->errorInfo(), 0); 
    } 
    $i++; 
} 
$sql = "RESTORE DATABASE " . DB_NAME . " WITH RECOVERY;"; 
$dbh->exec($sql); 
pre($dbh->errorInfo(), 0); 
echo $sql . "<br />"; 
die("NOW WE ARE DONE!"); 
} 

第一个语句运行没有任何问题:

RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307151435.bak' WITH NORECOVERY, REPLACE; 

但在此之后,当我想挽回最后一个diff文件:

RESTORE DATABASE restorelogs FROM DISK = 'D:/Apache/htdocs/logreader/extracts/SRO_VT_LOG201307161145diff.bak' WITH FILE=1, RECOVERY; 

我找回了一条错误消息:

[Microsoft][SQL Server Native Client 10.0][SQL Server]A previous restore operation was interrupted and did not complete processing on file 'Log_DB_Data'. Either restore the backup set that was interrupted or restart the restore sequence.' 

并且数据库状态保持还原模式。

我也尝试玩RESTORE FILELISTONLY,并将文件移动到正确的位置。我可以这样做,但之后我无法恢复差异备份。

function restoreFromDisk($file) { 
    $sql = "RESTORE FILELISTONLY FROM DISK = '" . $file . "'"; 
    $res = dbQuery($sql); 
    $option = ' ,REPLACE, RECOVERY'; 
    while ($row = dbFetchAssoc($res)) { 
    if ($row["LogicalName"] == "Log_DB_Data") { 
     $move[] = " MOVE '" . $row["LogicalName"] . "' TO '" . MSSQL_DATA_PATH . "resetlogs.mdf'"; 
    } else { 
     $move[] = " MOVE '" . $row["LogicalName"] . "' TO '" . MSSQL_DATA_PATH . "resetlogs.ldf'"; 
    } 
    } 
    $moves = join(",", $move); 
    $sql = "RESTORE DATABASE " . DB_NAME . " FROM DISK = '" . $file . "' WITH " . $moves . $option . ";"; 
    dbQuery($sql); 
    echo $sql . "<br />"; 
    $sql = "RESTORE DATABASE " . DB_NAME . " WITH RECOVERY;"; 
    dbQuery($sql); 
    echo $sql . "<br />"; 
} 

回答

0

如果用户有可能连接(如果可以杀死他们的会话),您应该将数据库设置为单个用户。既然你正在恢复数据库,我会认为它没问题。您需要在完整备份恢复中指定替换选项。此外,您只需要还原最新的差异备份(与恢复一起使用),因为它将包含自上次完全备份以来的所有更改。还应该注意的是,此还原将不包括自上次差异备份以来发生的事务。

我会考虑每3小时使用一次日志备份。这将对您的系统产生较小的影响,并允许日志截断(如果您处于完全恢复状态)。在此恢复方案中,您将需要完整备份和所有日志备份,最后一个选项指定恢复。

+0

好的,我想出了导致问题的原因。 当我将它复制到mssql管理器中时,它按照我的预期运行。因为,查询正在彼此等待。 我做你伤心,我只是我们最后的差异文件。 但是从php,我无法调用mysql_query(“GO”); 因此,当我尝试启动第二次恢复时,差分文件,我得到了这个回: 以前的恢复操作中断,并没有完成处理文件'Log_DB_Data'。恢复被中断的备份集或重新启动恢复序列。 – vaso123

+0

我会将恢复命令添加到数组,并自行处理每个命令。例如,第一次迭代将恢复完整备份,然后下一次迭代将执行差异恢复。 –

+0

我最后的尝试是创建一个存储过程,然后传递2个文件,也许mssql可以做到这一点。 – vaso123

0

另一种方法是将SQL脚本写入临时文件,然后使用osql将其作为脚本执行。当然这假定你正在安装osql的机器上运行。

osql -E -S <server> -d master -i <sql file>