我在工作组中有两台服务器,我需要将 SQL Server 2008 备份从一台服务器的本地驱动器传输到另一台服务器的网络驱动器。理想情况下,我希望 SQL 在备份后调用 Powershell 脚本。有人有可以执行此操作的脚本吗?有更好的方法吗?
我尝试将 SQL 备份直接复制到网络驱动器,但如果它们不在同一个域中,似乎无法做到这一点。
答案1
Powershell 当然可以做到这一点,但我发现 ROBOCOPY 更容易,只需在 SQL 服务器上创建维护清理计划后使用 /MIR 选项自动清除旧备份,即可摆脱超过 X 天的备份,并且您将始终在网络驱动器上保留副本;
您可以将副本设置为 Windows 计划任务,或者通过操作系统命令设置为 SQL 代理任务。
答案2
我为自己编写了这个脚本。它使用我自己熟悉的文件名格式将备份直接创建到网络共享中。它从 Windows 调度程序执行。
function Backup-Database {
[CmdletBinding()]
param(
$Server,
[String[]]$Database,
[String]$Path,
[Switch]$CreateSubfolder,
[Switch]$Check,
[Switch]$CopyOnly,
[Switch]$BackupDatabase = $true,
[Switch]$BackupTransactionLog,
[Switch]$NoInnerVerbose,
[Switch]$Differential
)
begin {
$AllDatabases = @()
}
process {
#All database names into 1 list
$AllDatabases += $Database
}
end {
$DefaultProgressPreference = $ProgressPreference
if (-not $Path.EndsWith('\')) {
$Path = $Path + '\'
}
#$Differential = $false
$RetainDays = 0
if ($Differential) {
$RetainDays = 31
}
if ($NoInnerVerbose) {
$Verbose = $false
}
else {
$Verbose = ($VerbosePreference -eq 'Continue')
}
Import-Module SQLPS -Verbose:$false -WarningAction SilentlyContinue
$Activity = "Backing up databases"
# Some cmdlets cannot specify timeouts, this is workout
Write-Verbose "Connecting to $Server"
Write-Progress -Activity $Activity -CurrentOperation "Connecting to $Server"
$ServerInstance = New-Object Microsoft.SqlServer.Management.Smo.Server $Server
$ServerInstance.ConnectionContext.StatementTimeout = 0
for ($index = 0; $index -lt $AllDatabases.Count; $index++) {
$TotalProgress = $index / $AllDatabases.Count * 100
$DB = $AllDatabases[$index]
$DBTitle = [Char]::ToUpperInvariant($DB[0]) + $DB.Substring(1)
$Operation = "Backing up $DBTitle database"
#Write-Verbose $Operation
if ($Check) {
Write-Progress -Activity $Activity -CurrentOperation $Operation -Status 'Checking database integrity' -PercentComplete $TotalProgress
Write-Verbose "Checking $DB database integrity"
Invoke-Sqlcmd -ServerInstance $ServerInstance -Database $DB -Query 'DBCC CHECKDB($(dbname))' -Variable "dbname='$DB'" -Verbose:$Verbose -QueryTimeout 65535
}
if ($BackupTransactionLog) {
Write-Progress -Activity $Activity -CurrentOperation $Operation -Status 'Backing up transaction log' -PercentComplete $TotalProgress
$FileName = $Path
if ($CreateSubfolder) {
$FileName = Join-Path $FileName $DBTitle
if (-not (Test-Path $FileName)) {
Push-Location
New-Item $FileName -ItemType Container -Force | Out-Null
Pop-Location
}
}
$FileName = Join-Path $FileName "$($DBTitle)_$(Get-Date -format 'yyyy-MM-dd_HH-mm')_log.trn"
Write-Verbose "Backing up transaction log to $FileName"
$ProgressPreference = 'SilentlyContinue'
Backup-SqlDatabase -Database $DB -BackupFile $FileName -InputObject $ServerInstance -BackupAction Log -Checksum:$Check -CompressionOption On -CopyOnly:$CopyOnly -RetainDays $RetainDays -LogTruncationType Truncate -Verbose:$Verbose
$ProgressPreference = $DefaultProgressPreference
if ($Check) {
Write-Progress -Activity $Activity -CurrentOperation $Operation -Status 'Checking transaction log backup integrity' -PercentComplete $TotalProgress
$FileNumber = Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'select position from msdb..backupset where database_name=$(dbname) and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=$(dbname))' -Variable "dbname='$DB'" -Verbose:$Verbose | select -ExpandProperty position
$Position = Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'RESTORE HEADERONLY FROM DISK=$(filename)' -Variable "filename='$FileName'" -Verbose:$Verbose | select -Last 1 -ExpandProperty Position
if ($FileNumber -ne $null -and $FileNumber -eq $Position) {
Write-Verbose "Verifying backup file '$FileName', position $FileNumber"
Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'RESTORE VERIFYONLY FROM DISK=$(filename) WITH FILE=$(position)' -Variable "filename='$FileName'","position=$FileNumber" -QueryTimeout 65535 -Verbose:$Verbose
}
else {
Write-Error "Transaction log verify failed. Backup information for database $DB not found or incorrect (query position $FileNumber, file position $Position)" -Category InvalidResult
}
}
}
if ($BackupDatabase) {
Write-Progress -Activity $Activity -CurrentOperation $Operation -Status 'Backing up database' -PercentComplete $TotalProgress
$FileName = $Path
if ($CreateSubfolder) {
$FileName = Join-Path $FileName $DBTitle
if (-not (Test-Path $FileName)) {
Push-Location
New-Item $FileName -ItemType Container -Force | Out-Null
Pop-Location
}
}
if ($Differential) {
$part = 'diff'
}
else {
$part = 'full'
}
$FileName = Join-Path $FileName "$($DBTitle)_$(Get-Date -format 'yyyy-MM-dd_HH-mm')_$part.bak"
Write-Verbose "Backing up $DB database to $FileName"
$ProgressPreference = 'SilentlyContinue'
Backup-SqlDatabase -Database $DB -BackupFile $FileName -InputObject $ServerInstance -BackupAction Database -Checksum:$Check -CompressionOption On -Incremental:$Differential -CopyOnly:$CopyOnly -RetainDays $RetainDays -Verbose:$Verbose
$ProgressPreference = $DefaultProgressPreference
#Backing up (Database: 'accounting' ; Server: 'Serv1C' ; Action = 'Database') .
if ($Check) {
Write-Progress -Activity $Activity -CurrentOperation $Operation -Status 'Checking database backup integrity' -PercentComplete $TotalProgress
$FileNumber = Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'select position from msdb..backupset where database_name=$(dbname) and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=$(dbname))' -Variable "dbname='$DB'" -Verbose:$Verbose | select -ExpandProperty position
$Position = Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'RESTORE HEADERONLY FROM DISK=$(filename)' -Variable "filename='$FileName'" -Verbose:$Verbose | select -Last 1 -ExpandProperty Position
if ($FileNumber -ne $null -and $FileNumber -eq $Position) {
Write-Verbose "Verifying backup file '$FileName', position $FileNumber"
Invoke-Sqlcmd -ServerInstance $ServerInstance -Query 'RESTORE VERIFYONLY FROM DISK=$(filename) WITH FILE=$(position)' -Variable "filename='$FileName'","position=$FileNumber" -QueryTimeout 65535 -Verbose:$Verbose
}
else {
Write-Error "Database backup verify failed. Backup information for database $DB not found or incorrect (query position $FileNumber, file position $Position)" -Category InvalidResult
}
}
}
}
Write-Progress -Activity $Activity -Completed
}
}
$Server = 'Serv1C'
$Databases = 'accounting3','zup','accounting','pult','accounting_ip','accounting_u','accounting_u2'
$Differential = $true
$TransactionLog = $true
$Check = $false
$BackupPath = '\\MAIN\Backup\SQL'
Backup-Database -Server $Server -Database $Databases -Path $BackupPath -CreateSubfolder -Verbose -NoInnerVerbose -Differential:$Differential -BackupTransactionLog:$TransactionLog -Check:$Check
答案3
我使用 Powershell 调用富文本复制。如果您使用 RAR 实用程序将大文件拆分成多个块,RichCopy 可以真正节省空间。
另一种方法是使用 PowerShell v2 BITS 模块,尽管我还没有尝试过。从“import-module filetransfer”和“get-help add-filetransfer –example”开始
至于 SQL 调用脚本,尝试让它明确调用所有内容:
%windir%\system32\windowspowershell\v1.0\powershell.exe -nologo -command“&{C:\path\to\Script.ps1}”