我有一个奇怪的问题。我有一个数据库,名为restorelogs
.
自动备份脚本执行完整备份,之后每 3 小时进行一次差异备份。第二天再做一次完整的,然后再做一次差异,依此类推。
不,我想编写一个脚本,将这些文件还原到 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。
这就是我尝试的方法: function pushToDatabase($files) {
$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;
但在此之后,当我想恢复最后一个差异文件时:
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 />";
}