最近心相不错,所以打算翻译一些英文文档做福利,原文在此,翻译有不足的地方还请各位兄弟指点.

讨论什么是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 备份和还原的更多相关文章

  1. SQL Server 数据库备份和还原

    一.SQL命令 备份BACKUP DATABASE TestDb TO DISK='d:\TestDb.bak'还原RESTORE DATABASE TestDb FROM DISK='d:\Test ...

  2. (图解版)SQL Server数据库备份与还原

        本文介绍了SQL Server数据库备份的两种方式.一种是直接拷贝数据库中的文件mdf 和日志文件ldf,另一种是生成脚本语言. 第一种方式:     选中需要备份的数据库,将数据库从运行的数 ...

  3. SQL Server 2012 AlwaysOn集群配置指南

    1. AlwaysOn介绍 AlwaysOn是SQL Server 2012提供的全新综合.灵活.高效经济的高可用性和灾难恢复解决方案.它整合了镜像和群集的功能,基于OS 故障转移群集(Windows ...

  4. 在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群

    需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服 ...

  5. 在SQL Server 2012中如何使用分组集

    作者:Itzik Ben-Gan  翻译:张洪举 此文摘自作者的<Microsoft SQL Server 2012 T-SQL基础>. 分组集就是你据以分组的一个属性集.传统上,SQL中 ...

  6. Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 1 -使用FOR XML返回XML结果集

    XML 介绍 <CustomersOrders> <Customer custid="1" companyname="Customer NRZBB&qu ...

  7. 图文详解在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 ...

  8. 在Windows Server 2012中搭建SQL Server 2012故障转移集群

    OK~ WSFC 2012 R2 年度盛宴开始~ 在本文中,老王将用一系列的场景,把动态仲裁,动态见证,票数调整,LowerQuorumPriorityNodeID,阻止仲裁等群集仲裁技术串起来,完成 ...

  9. 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)

    本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...

随机推荐

  1. Codeigniter使用phpexcel

    1. 去 http://phpexcel.codeplex.com/ 下载phpexcel源码,解压缩后把phpexcel/Classes里的PHPExcel文件夹和PHPExcel.php复制到CI ...

  2. codeforces 632D. Longest Subsequence 筛法

    题目链接 记录小于等于m的数出现的次数, 然后从后往前筛, 具体看代码. #include <iostream> #include <vector> #include < ...

  3. 在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be closed first”

    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be ...

  4. jasmine note

    jasmine 简介 jasmine 是一个测试驱动开发(TDD)测试框架, 一个js测试框架,它不依赖于浏览器.dom或其他js框架 jasmine有十分简洁的语法 使用 从 这里 下载 stant ...

  5. QPointer很大程度上避免了野指针(使用if语句判断即可,类似于dynamic_cast),而且使用非常方便 good

    QPointer 如何翻译呢?我不太清楚,保留英文吧. The QPointer class is a template class that provides guarded pointers    ...

  6. Mysql 忘密码 + Phpadmin 修改密码无法登陆

    mysql有时候忘记密码了怎么办?我给出案例和说明!一下就解决了! Windows下的实际操作如下 1.关闭正在运行的MySQL. 2.打开DOS窗口,转到mysql\bin目录. 3.输入mysql ...

  7. 具有 CSA CCM 证明的 SOC 2 可简化 Windows Azure 客户的安全性评估过程

    编辑人员注释:本文章由 Windows Azure 产品市场营销总监 Sarah Fender 撰写. 今天,我们宣布 Microsoft 的公共审计师 Deloitte 已经发布了有关 Window ...

  8. 预处理指令中#Pragma

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  9. Android应用开发基础篇(4)-----TabHost(选项卡)

    一.概述 TabHost是一种用来显示标签的组件,不清楚?看一下来电通这个应用就知道了.这个组件用起来与其他组件不太一样,它需要继承TabActivity这个类,还有它的布局文件与我们平时用的也有些不 ...

  10. OpenGL 4 : 一个漂亮的心 For you, My Love

    画一个心形有非常多公式能够使用,以下这个公式我觉得最完美了: float x = R * 16 * pow(sin(theta), 3); float y = R * (13 * cos(theta) ...