使用PowerShell 命令集进行SQL Server 2012 备份和还原
最近心相不错,所以打算翻译一些英文文档做福利,原文在此,翻译有不足的地方还请各位兄弟指点.
讨论什么是DBA最重要的工作的时候,你最常听到就是一条就是DBA只要做好备份和恢复.事实如此,如果你不做备份,或者无法保证你的备份能够有效恢复,你和你的公司就会处于数据丢失危险下.
T-SQL 命令BACKUP DATABASE已经使用了相当长的一段时间(在这之前用的是DUMP DATABASE 命令,老人们都记得). 它仍然不失为备份数据库好方式.我们现在有一个新的方法来自动的做这些日常的备份处理任务.在本文中我会通过实例来介绍如何通过PowerShell脚本来备份.并告诉大家在SQL Server 2012 使用PowerShell Cmdlet的便利性.
在SQL Server 2012 中,微软增加了4个新的备份和还原的cmdlet
- Backup-SqlDatabase
- Restore-SqlDatabase
- Backup-ASDatabase
- Restore-ASDatabase
为什么要通过外部程序来做脚本备份?
当备份工作越来越复杂,越来越多文件系统要被牵涉进去的时候.这些工作可能需要建立并按放备份文件至某个目录,删掉不需要的旧备份,异地拷贝,检查备份完整性,写入日志等等. 你也可能想一步操作就把在不同服务器上的多个数据库进行备份或者拷贝数据库到几个服务器或者虚拟机上做测试.这个时候备份和还原就需要考虑使用脚本,而PowerShell擅长此道.
使用Powershell和SMO编写脚本
在2009年我发布了白皮书backup.ps1 ,使用SMO(Server Management Objects)库来备份你的数据库.SMO支持SQL Server versions 2000 ~ 2012, 微软在SQL Server 2012并没有给SMO增加多少新的特性.所以没多少新东西可学.
在白皮书中我讲述了SQL Server snapins , 还有SQL Server 2008 和 SQL Server 2008 R2 里面的迷你Shell (SQLPS.exe) ,PowerShell 团队为 SQL Server 2008 扩展的,现在技术已经改变 , 采用”模块”来扩展Powershell 因此, SQL Server 2012 安装的时候Powershell 最低版本是2.0 , 然后 SQLPS.exe 程序已经被替换掉了(叫SQLPS = =).
微软在SQLPS模块中提供了一些新的cmdlets, 多数专门用来管理可用性组和高可用性还有灾难恢复. 他们新增了备份和还原操作的 cmdlets , Backup-SqlDatabase, Restore-SqlDatabase, Backup-ASDatabase 还有 Restore-ASDatabase.
安装SQLPS模块
启动 PowerShell 并且想要使用SQLPS模块, 你需要导入相应的cmdlet. 开启PowerShell 2.0,当导入模块的时候微软会通过一个列表来进行动词的检查.Backup 和 Restore并不在这个列表里面,所以你执行模块导入的时候会报错. 你可以使用 -DisableNameChecking 参数来避免这个错误

(译者注:我执行的时候报错. 提示SQLPS不被信任,所以模块导入出错了, 此时要执行Set-ExecutionPolicy RemoteSigned 来开启)

使用Backup-SqlDatabase CmdLet来备份数据库
简单的 Backup-SQLDatabase 语句
当你导入模块以后,可以先简单的建立个备份数据库的脚本,如下:
{$dt = Get-Date -Format yyyyMMddHHmmss
$dbname = 'AdventureWorks'
Backup-SqlDatabase -ServerInstance TESTSQL -Database $dbname -BackupFile "E:\Backup\$($dbname)_db_$($dt).bak"
有很多的方法来调用这个指令,比如说你可以使用Get-ChildItem来获取你定位到的数据库实例的目录数据库名,然后通过管道发送给Backup-SqlDatabase命令,进行迭代的进行数据库备份 . 因为你已经连到你的实例这里所以就不需要在加 -ServerInstance 参数了.
简单打下面两句就了…
Set-Location SQLSERVER:\SQL\
TESTSQL
\DEFAULT\Databases
get-childitem|Backup-SqlDatabase
备份会放在默认的备份目录里面, 备份文件名也是默认的数据库名字. 如果你想指定备份文件的名字,或者其他一些阐述,可以用下面的代码
Set-Location SQLSERVER:\SQL\TESTSQL\DEFAULT\Databases
foreach ($db in (Get-ChildItem))
{
$dbname = $db.Name
$dt = Get-Date -Format yyyyMMddHHmmss
Backup-SqlDatabase -Database $dbname -BackupFile "$($dbname)_db_$($dt).bak"
}
下面段会备份所有用户数据库被分到默认备份目录,并且以数据库的名字和当前日期时间作为备份文件的名字. (如果你使用 Get-ChildItem 加上-Force 参数,那就会包含系统数据库,当然 tempdb被Where过滤掉了.)
get-childitem -force|where name -ne 'TempDB'| Backup-SqlDatabase
你也可以建立一个包含 SMO Server 对象的脚本 , 用 -InputObject 代替-ServerInstance . 虽然我们示例是备份一个数据库,但是这个在处理多服务器上的数据库的时候会很有用.
$dt = Get-Date -Format yyyyMMddHHmmss
$dbname = 'AdventureWorks'
$svr = new-object ('Microsoft.SqlServer.Management.Smo.Server') 'TESTSQL'
Backup-SqlDatabase -InputObject $svr -Database $dbname -BackupFile "E:\Backup\$($dbname)_db_$($dt).bak"
另外你也可以使用一个包含SMO数据库的变量,然后使用 -DatabaseObject 参数.
$dt = Get-Date -Format yyyyMMddHHmmss
Set-Location SQLSERVER:\SQL\TESTSQL\DEFAULT\Databases\AdventureWorks
$db = Get-Item .
$dbname = $db.Name
Backup-SqlDatabase -DatabaseObject $db -BackupFile "E:\Backup\$($dbname)_db_$($dt).bak"
以上示例为了便于理解,均使用了最少的参数,实际操作的话,你应该看一下其他参数,使得备份方案符合你的需求.
SQL备份: 关键参数
我通常会加参数 -BackupAction. 选项可以是Database,Files和Log,默认是Database, 如果你想做差异备份,那么指定 BackupAction 为Database ,然后加上-Incremental参数.如果你想备份单个文件或者文件组,你可以使用 Files 选项.而 Log 选项允许你做事务日志备份.为了节省篇幅,因此去掉了这些参数. 所以例子直接备份了整个数据库.
举个例子,我总是会使用-CompressionOption 参数. 当然还有-ConnectionTimeout ,并且设置为0 ,因为你不想备份的时候因为超时而被中断.
我们用get-help 获得 Backup-SqlDatabase 的参数列表 :
Backup-SqlDatabase
[-Database] <string>
[-BackupFile] <string[]>]
[-ServerInstance <string[]> ]
[-BackupAction <BackupActionType>]
[-BackupDevice <BackupDeviceItem[]>]
[-BackupSetDescription <string>]
[-BackupSetName <string>]
[-BlockSize <int>]
[-BufferCount <int>]
[-Checksum]
[-CompressionOption <BackupCompressionOptions>]
[-ConnectionTimeout <int>]
[-ContinueAfterError]
[-CopyOnly]
[-Credential <PSCredential>]
[-DatabaseFile <string[]>]
[-DatabaseFileGroup <string[]>]
[-ExpirationDate <DateTime>]
[-FormatMedia]
[-Incremental]
[-Initialize]
[-LogTruncationType <BackupTruncateLogType>]
[-MaxTransferSize <int>]
[-MediaDescription <string>]
[-MediaName <string>]
[-MirrorDevices <BackupDeviceList[]>]
[-NoRecovery]
[-NoRewind]
[-Passthru]
[-Restart]
[-RetainDays <int>]
[-Script]
[-SkipTapeHeader]
[-UndoFileName <string>]
[-UnloadTapeAfter]
[-Confirm]
[-WhatIf]
[<CommonParameters>]
比SMO显著的优势
最明显的就是在命令集中增加了一些SMO没有的功能.比如通过Transact-SQL可以设置备份的块大小和缓冲区数而SMO没有.下图是等价功能的SMO的备份对象的属性和方法:

(上图是通过Visual Studio 的 Object Browser 载入SMOExtended DLL的截图)
使用Restore-SQLDatabase CmdLet 还原数据库
总归有各种各样的原因需要还原数据库, 所以…还原的选项比备份的还要多.
下面是恢复full backup一个简单示例, 选项设置直接覆盖现有数据库.
Restore-SqlDatabase -ServerInstance TESTSQL -Database AdventureWorks `
-BackupFile "E:\Backup\AdventureWorks_db_20130420153024.bak" -ReplaceDatabase
我还原数据库最频繁的理由之一就是用户不小心删掉了数据,随后又被事务更新,导致数据丢失.碰到这种情况我就要用另外一个名字还原该数据库,然后把需要的数据复制过去.
通过 SMO 还原数据库
下面是我们使用SMO还原的代码
# Connect to the specified instance
$srv = new-object ('Microsoft.SqlServer.Management.Smo.Server') 'TESTSQL' # Get the default file and log locations
# (If DefaultFile and DefaultLog are empty, use the MasterDBPath and MasterDBLogPath values)
$fileloc = $srv.Settings.DefaultFile
$logloc = $srv.Settings.DefaultLog
if ($fileloc.Length -eq 0) {
$fileloc = $srv.Information.MasterDBPath
}
if ($logloc.Length -eq 0) {
$logloc = $srv.Information.MasterDBLogPath
} # Identify the backup file to use, and the name of the database copy to create
$bckfile = 'E:\Backup\AdventureWorks_db_20101016135438.bak'
$dbname = 'AdventureWorks_20101016' # Build the physical file names for the database copy
$dbfile = $fileloc + '\'+ $dbname + '_Data.mdf'
$logfile = $logloc + '\'+ $dbname + '_Log.ldf' # Use the backup file name to create the backup device
$bdi = new-object ('Microsoft.SqlServer.Management.Smo.BackupDeviceItem') ($bckfile, 'File') # Create the new restore object, set the database name and add the backup device
$rs = new-object('Microsoft.SqlServer.Management.Smo.Restore')
$rs.Database = $dbname
$rs.Devices.Add($bdi) # Get the file list info from the backup file
$fl = $rs.ReadFileList($srv)
foreach ($fil in $fl) {
$rsfile = new-object('Microsoft.SqlServer.Management.Smo.RelocateFile')
$rsfile.LogicalFileName = $fil.LogicalName
if ($fil.Type -eq 'D'){
$rsfile.PhysicalFileName = $dbfile
}
else {
$rsfile.PhysicalFileName = $logfile
}
$rs.RelocateFiles.Add($rsfile)
} # Restore the database
$rs.SqlRestore($srv)
还原一个已存在的数据库的问题就是物理名称冲突,要解决这个问题SMO 可以使用RelocateFile 对象. 这和Transact-SQL 使用 WITH MOVE 条件一样. 有趣的是Restore-SqlDatabase 命令也使用SMO 对象处理这个事情.
使用纯SMO 和 Restore-SqlDatabase 命令的唯一区就是何存储和传递RelocateFile 对象. 建立一个空的集合,然后读取备份文件列表,并且把每个RelocateFile 的每个对象都添加到集合中. 随后调用 Restore-SqlDatabase命令. 下图中最后最后一部分用的是新的cmdlet,其他上面的例子都一样.
# Get the file list info from the backup file
$fl = $rs.ReadFileList($srv)
$rfl = @()
foreach ($fil in $fl) {
$rsfile = new-object('Microsoft.SqlServer.Management.Smo.RelocateFile')
$rsfile.LogicalFileName = $fil.LogicalName
if ($fil.Type -eq 'D') {
$rsfile.PhysicalFileName = $dbfile
}
else {
$rsfile.PhysicalFileName = $logfile
}
$rfl += $rsfile
} # Restore the database
Restore-SqlDatabase -ServerInstance TESTSQL -Database $dbname `
-BackupFile "E:\Backup\AdventureWorks_db_20101016135438.bak" `
-RelocateFile $rfl
在本例中我贴出了纯SMO的例子,应该已经很清楚了.
指定一个时间点来还原数据库
最后一个例子是通过一个时间点来还原数据库. 有时候你知道问题发生的时间,你可以恢复到那个时间点.
在这个情境中我们所有的被封文件都放在本地服务器的 E:\Backup 目录. 我们有很多完全备份,差异备份,还有一些事务日志备份文件用来做某一个时间点的还原.文件名格式为 DatabaseName_type_datetime.ext, 其中type是db, diff 和 tran ,ext是 bak 或 trn.
$dbname = 'AdventureWorks'
$restorept = '2013-04-20 15:30:00'
Set-Location 'E:\Backup'
$fullfile = Get-ChildItem -Filter "$($dbname)_db_*" | Where-Object {$_.LastWriteTime -lt $restorept} | Sort-Object LastWriteTime Desc | Select-Object -First 1
$difffile = Get-ChildItem -Filter "$($dbname)_diff_*" | Where-Object {$_.LastWriteTime -lt $restorept} | Sort-Object LastWriteTime Desc | Select-Object -First 1
$tranfile = Get-ChildItem -Filter "$($dbname)_tran_*" | Where-Object {$_.LastWriteTime -gt $difffile.LastWriteTime} | Sort-Object LastWriteTime Asc
$fullfile 变量包含指定时间点前的完整备份文件信息,$difffile变量包含指定时间点前的差异备份文件信息 , $tranfile 包含差异备份后至指定时间点前的所有的事务日志文件信息
首先我们需要还原完整备份, 并且指定 no recovery选项.
Restore-SqlDatabase -ServerInstance TESTSQL -Database $dbname `
-BackupFile $fullfile.FullName -ReplaceDatabase `
-NoRecovery
然后我们还原最后一个差异备份,同样的,指定no recovery选项.
Restore-SqlDatabase -ServerInstance TESTSQL -Database $dbname `
-BackupFile $difffile.FullName -ReplaceDatabase `
-NoRecovery
最后我们通过循环来读取$tranfile变量中的文件来还原事务日志, 如果LastWriteTime 属性比 $restorept 变量小,那么恢复的时候指定no recovery,然后处理下一个,否则,则根据-ToPointInTime 参数指定的时间点来还原. 不加-NoRecovery 参数,至此整个还原过程结束.
$recovery = 0
foreach ($trnfile in $tranfile) {
if ($trnfile.LastWriteTime -lt $restorept) {
Restore-SqlDatabase -ServerInstance TESTSQL -Database $dbname `
-BackupFile $trnfile.FullName -ReplaceDatabase `
-NoRecovery
}
else {
if ($recovery -eq 0) {
Restore-SqlDatabase -ServerInstance TESTSQL -Database $dbname `
-BackupFile $trnfile.FullName -ReplaceDatabase `
-ToPointInTime $restorept
$recovery = 1
}
}
}
还有很多特性,结合通过操作系统的一些功能来做备份和还原操作,比用Transact-SQL要方便许多
下图是SMO Restore 对象的属性和方法:

相应的下面是Restore-SqlDatabase的参数
Restore-SqlDatabase
[-Database] <string>
[[-BackupFile] <string[]>]
-ServerInstance <string[]>
[-BackupDevice <BackupDeviceItem[]>]
[-BlockSize <int>]
[-BufferCount <int>]
[-Checksum]
[-ClearSuspectPageTable]
[-ConnectionTimeout <int>]
[-ContinueAfterError]
[-Credential <PSCredential>]
[-DatabaseFile <string[]>]
[-DatabaseFileGroup <string[]>]
[-FileNumber <int>]
[-KeepReplication]
[-MaxTransferSize <int>]
[-MediaName <string>]
[-NoRecovery]
[-NoRewind]
[-Offset <Int64[]>]
[-Partial]
[-Passthru]
[-RelocateFile <RelocateFile[]>]
[-ReplaceDatabase]
[-Restart]
[-RestoreAction <RestoreActionType>]
[-RestrictedUser]
[-Script]
[-StandbyFile <string>]
[-StopAtMarkAfterDate <string>]
[-StopAtMarkName <string>]
[-StopBeforeMarkAfterDate <string>]
[-StopBeforeMarkName <string>]
[-ToPointInTime <string>]
[-UnloadTapeAfter]
[-Confirm]
[-WhatIf]
[<CommonParameters>]
使用Backup-ASDatabase备份 Analysis Services
Analysis Services 的数据库也是需要备份的,虽然没多少选项可用. 首先你需要载入Analysis Services 命令集的模块 .
Import-Module SQLASCMDLETS
我们先看下 Backup-ASDatabase的所有参数.
Backup-ASDatabase
[-BackupFile] <string>
[-Name] <string>
[-AllowOverwrite <SwitchParameter>]
[-BackupRemotePartitions <SwitchParameter>]
[-ApplyCompression <SwitchParameter>]
[-FilePassword <SecureString>]
[-Locations <Microsoft.AnalysisServices.BackupLocation[]>]
[-Server <string>]
[-Credentials <PSCredential>]
[<CommonParameters>]
注意:这里没有差异备份或者日志备份的选项.下面是备份AWDB database一个简单例子.
Backup-ASDatabase "E:\Backup\AWDB.abf" AWDB
如果需要覆盖已存在的数据库备份,可以加上 -AllowOverwrite 参数,需要压缩备份则加上-ApplyCompression参数, 要加密的话可以使用 -FilePassword 参数.
使用Restore-ASDatabase还原 Analysis Services数据库
同样的还原Analysis Services 数据库也没多少可用选项.
Restore-ASDatabase
[-RestoreFile] <string>
[-Name] <System.String>
[-AllowOverwrite <SwitchParameter>]
[-Locations <Microsoft.AnalysisServices.RestoreLocation[]>]
[-Security <Microsoft.AnalysisServices.RestoreSecurity>]
[-Password <System.SecureString>]
[-StorageLocation <System.String>]
[-Server <string>]
[-Credentials <PSCredential>] [<CommonParameters>]
下面是一个还原例子
Restore-ASDatabase "E:\Backup\AWDB.abf" AWDB -Security:CopyAll
还原的时候同事恢复roles和members
总结
组织数据的备份还原是至关重要的.使用Powershell和SMO编写脚本来管理SQL SERVER的备份还原是最好的,尤其是DBA需要完成更复杂,的重复性的任务的时候. 比如数据库需要高可用性, 我们可以创建脚本来重建他们,进行高可用性测试排练.总之 在 SQL Server 2012中使用他们最理想的,而且很方便.
使用PowerShell 命令集进行SQL Server 2012 备份和还原的更多相关文章
- SQL Server 数据库备份和还原
一.SQL命令 备份BACKUP DATABASE TestDb TO DISK='d:\TestDb.bak'还原RESTORE DATABASE TestDb FROM DISK='d:\Test ...
- (图解版)SQL Server数据库备份与还原
本文介绍了SQL Server数据库备份的两种方式.一种是直接拷贝数据库中的文件mdf 和日志文件ldf,另一种是生成脚本语言. 第一种方式: 选中需要备份的数据库,将数据库从运行的数 ...
- SQL Server 2012 AlwaysOn集群配置指南
1. AlwaysOn介绍 AlwaysOn是SQL Server 2012提供的全新综合.灵活.高效经济的高可用性和灾难恢复解决方案.它整合了镜像和群集的功能,基于OS 故障转移群集(Windows ...
- 在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群
需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服 ...
- 在SQL Server 2012中如何使用分组集
作者:Itzik Ben-Gan 翻译:张洪举 此文摘自作者的<Microsoft SQL Server 2012 T-SQL基础>. 分组集就是你据以分组的一个属性集.传统上,SQL中 ...
- Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 1 -使用FOR XML返回XML结果集
XML 介绍 <CustomersOrders> <Customer custid="1" companyname="Customer NRZBB&qu ...
- 图文详解在Windows server 2008 R2上安装SQL Server 2012集群
1.准备: 4台服务器(1台AD.2台SQL服务器.1台iSCSI存储服务器) 9个IP(1个AD的IP.2个SQL服务器的IP.2个心跳IP.1个iSCSI存储服务器的IP.1个集群IP.1个DTC ...
- 在Windows Server 2012中搭建SQL Server 2012故障转移集群
OK~ WSFC 2012 R2 年度盛宴开始~ 在本文中,老王将用一系列的场景,把动态仲裁,动态见证,票数调整,LowerQuorumPriorityNodeID,阻止仲裁等群集仲裁技术串起来,完成 ...
- 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)
本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...
随机推荐
- 在ProgressBar上加文字----显示百分比的进度条
http://www.cnblogs.com/3dant/archive/2011/04/25/2026776.html
- javascript块级作用域
在c/java中,拥有块级作用域的概念,大括号内就是一个块级作用域,在块级作用域内声明的变量,块以外不可见. C语音的块级作用域示例如下: ,two = ; if(one < two){ ; t ...
- 14-C语言宏
目录: 一.宏定义 二.#x,##x使用和预定义宏 三.宏的高级使用(条件编译) 回到顶部 一.宏定义 1 宏是常用的预处理功能之一,是在编译之前进行宏替换,即将宏名替换成所定义的宏体. 2 优点:可 ...
- 59 pages的Delphi源码
http://www.codesc.net/source/list_10_59.shtml
- BZOJ 2252: [2010Beijing wc]矩阵距离
题目 2252: [2010Beijing wc]矩阵距离 Time Limit: 10 Sec Memory Limit: 256 MB Description 假设我们有矩阵,其元素值非零即1 ...
- 第八届河南省赛F.Distribution(水题)
10411: F.Distribution Time Limit: 1 Sec Memory Limit: 128 MB Submit: 11 Solved: 8 [Submit][Status] ...
- [置顶] 【GBT28181开发:SIP协议实践】之设备远程启动
下面学习的是设备远程控制的流程,和设备信息.设备目录.设备状态的流程差不多,主要是描述的协议字段不同,模拟SPVMN系统向源设备发送远程启动控制指令,记录下交互的消息,详细研究了下: 转载请注明出处: ...
- C++中搜索、截取字符串
演示样例中有具体凝视,直接上代码: #include <iostream> #include <string> using std::cout; using std::endl ...
- poj 3624 Charm Bracelet 01背包问题
题目链接:poj 3624 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 用子问题定义状态:即F [i, v]表示前i件物品恰放入一个容量为v 的背包可以 ...
- FPGA STA(静态时序分析)
1 FPGA设计过程中所遇到的路径有输入到触发器,触发器到触发器,触发器到输出,例如以下图所看到的: 这些路径与输入延时输出延时,建立和保持时序有关. 2. 应用背景 静态时序分析简称STA,它是一种 ...