Joh*_*ell 5 sql-server etl backup restore sql-server-2014
问题陈述: 我们的支持工程师需要从客户那里获取数据库备份。目前,我们的数据库包含在一个 Primary/.mdf 文件组/文件中。这些数据库多年来一直在收集历史数据,并且越来越大。我们的工程师需要几天时间才能将备份复制到我们的办公室。
似乎没有任何规定/想法来管理数据库的增长。
最“有价值”的数据是我们系统的“配置”。它包含在大约 50 个表中,我们正在考虑将这些表移至与历史数据(将放置在数据文件组中)分开的新配置文件组,以尝试为部分或文件备份设置阶段。
但我不确定我需要哪种备份/恢复策略来完成这个 - 部分备份或文件备份?
出于研发目的,我有一个名为FilegroupDemo
使用SIMPLE
恢复模型的数据库。FilegroupDemo
包含 3 个文件组:
配置文件组中的数据不会经常更改,并且可能会被标记为只读(如果有帮助),而数据文件组中的数据每分钟更改一次。
我希望能够灵活地仅备份/恢复主文件组和配置文件组/文件。
在SQL Server Partial Backups的 BOL 文章中,它指出:
部分备份类似于完整数据库备份,但部分备份不包含所有文件组。相反,对于读写数据库,部分备份包含主文件组、每个读写文件组以及一个或多个只读文件(可选)中的数据。
这种读取方式让我认为部分备份旨在省略只读文件组,最有可能用于不会更改并标记为只读的大量数据。这些不需要每次都备份。
1. 我说存在部分备份是为了备份所有文件组(除了标记为只读的文件组)是否正确?换句话说,如果我不使用只读文件组,那么使用部分备份就没有意义了——对吗?而且我认为我不能使用部分备份来备份只读文件组?
因此,我不认为部分备份是我所需要的。我相当天真地尝试了文件备份/恢复。我将数据库切换到FULL
恢复模式并运行:
BACKUP DATABASE FilegroupDemo FILEGROUP = N'PRIMARY'
TO DISK = N'C:\Backups\FilegroupDemo_FG_Primary.bak'
WITH INIT
GO
BACKUP DATABASE FilegroupDemo FILEGROUP = N'Configuration'
TO DISK = N'C:\Backups\FilegroupDemo_FG_Configuration.bak'
WITH INIT
GO
BACKUP DATABASE FilegroupDemo FILEGROUP = N'Data'
TO DISK = N'C:\Backups\FilegroupDemo_FG_Data.bak'
WITH INIT
GO
<delete the database>
RESTORE DATABASE FilegroupDemo FILEGROUP = 'PRIMARY'
FROM DISK = 'C:\Backups\FilegroupDemo_FG_Primary.bak'
WITH PARTIAL, NORECOVERY, REPLACE
GO
RESTORE DATABASE FilegroupDemo
FROM DISK = N'C:\Backups\FilegroupDemo_FG_Configuration.bak'
WITH NORECOVERY, REPLACE
GO
RESTORE LOG FilegroupDemo
FROM DISK = 'C:\Backups\FilegroupDemo_Log.trn'
WITH RECOVERY
GO
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,这实际上似乎有效。我可以查询配置文件组中的表,而当我查询数据文件组中的表时,我得到:
The query processor is unable to produce a plan for the table or view 'xxx' because the table resides in a filegroup that is not online.
Run Code Online (Sandbox Code Playgroud)
2. 我想我很惊讶这有效,因为我认为这是一个“在线恢复”,它是企业功能。换句话说,当辅助文件组保持脱机时,我的数据库可以正常运行 - 不是吗?
我绝对使用标准版:
Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) Jun 17 2016 19:14:09 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
Run Code Online (Sandbox Code Playgroud)
3. 文件恢复需要FULL
恢复模式吗?如果我不能使用 SIMPLE 恢复模式来执行这种类型的文件备份并且我必须切换到 FULL,我是否可以暂时做一些事情 - 只是为了获取备份副本 - 然后将其切换回SIMPLE
?这有什么害处吗?另外,知道为什么必须使用 FULL - 只是好奇吗?
鉴于以下信息:
我们的支持工程师需要从客户那里获取数据库备份。
和:
最“有价值”的数据是我们系统的“配置”。它包含在大约 50 个表中......
和:
我担心为此目的临时更改恢复模型 [允许“数据”文件组变为只读,以便可以从备份中省略它]
我建议采用稍微不同的方法:使用SqlPackage.exe(SQL Server Data Tools / SSDT 的一部分)将所需的表和数据“提取”或“导出”到单个存档文件中,然后可以检索并“发布” ”或“进口”。SSDT 是免费的,因此在客户端系统上放置SqlPackage.exe可执行文件(和任何依赖的 DLL 等)应该没有许可问题。
您只需要确保每个客户端系统上都有SqlPackage.exe(以及任何相关的 DLL 等)。您可以从SqlPackage.exe启动xp_cmdshell
。您甚至可以创建一个.CMD脚本,使用适当的命令行参数执行SqlPackage.exe(有几个——或者您可以将大多数选项放入基于 XML 的“发布配置文件”文件中,并在命令行上指定)。然后您将在本地传输存档文件(.dacpac或.bacpac),就像您现在传输备份文件一样。如果您从他们的 FTP 到您的本地服务器,您可以在.CMD脚本中包含 FTP 命令,然后如果您将EXEC xp_cmdshell 'ExportAndTransferData.cmd';
语句转换为存储过程,您只需要执行该存储过程:-)。
查看各种选项,并知道您想要表的子集,我认为您应该首先尝试“提取”(即/Action:Extract
。您不想要所有表,因此请指定:/p:ExtractAllTableData=false
。然后,对于每个表如果您确实需要,请指定:(/p:TableData=schema.table
如果您需要大约 50 个表,您将指定大约 50 个这些选项。最后,通过指定来验证提取可能是一个好主意: /p:VerifyExtraction=true
。
在本地检索.dacpac文件后,您将“发布”它(即/Action:Publish
。对于此操作,您只需要一个包含所有架构(表、PK、FK、索引、视图等)和存储过程/函数的模板数据库已经在那里了。这个操作只会将数据放入正确的表中。
示例 CMD 脚本 ( ExportAndTransfer.cmd
)
@ECHO OFF
SET SQLPATH="C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin"
%SQLPATH%\SqlPackage.exe ^
/Action:Extract ^
/OverwriteFiles:True ^
/SourceDatabaseName:ClientDatabaseName ^
/SourceServerName:(local) ^
/TargetFile:%TEMP%\ConfigurationTables.dacpac ^
/p:IgnoreExtendedProperties=True ^
/p:ExtractAllTableData=False ^
/p:TableData="dbo.Table1" ^
/p:TableData="dbo.Table2" ^
/p:VerifyExtraction=true
ftp -s:path\to\FtpScript.txt my_server_hostname
Run Code Online (Sandbox Code Playgroud)
调用 CMD 脚本的存储过程示例
CREATE PROCEDURE dbo.RunExtract
AS
SET NOCOUNT ON;
EXEC xp_cmdshell 'C:\path\to\ExportAndTransfer.cmd';
GO
Run Code Online (Sandbox Code Playgroud)
在这两个之后你需要的只是 ftp 脚本。
更新
虽然由于“导出”不喜欢各种类型的对象,“提取”操作通常比“导出”操作更宽容,但在这种特殊情况下,“导出”操作适用于 OP,因为它不需要抓取所有表通过外键关联的。“提取”操作要求,如果指定的表具有到其他表的任何 FK,或者如果有任何其他表 FK 到它,则必须包括以任何方式链接到所需表的所有表。我发现这个MSDN 论坛帖子讨论了这个要求的原因:
dacpac 可以发布到任何数据库——空的或非空的。并且在发布表数据时,如果目标表不为空,则删除并替换所有数据。但是如果目标表不为空并且它有传入的 FK 依赖项,那么可能存在损坏的 FK 引用。要求所有表都是封闭集解决了这个问题,因为任何传入的引用也将被删除。
为“导出”指定的选项较少,因此命令行看起来更像以下内容:
%SQLPATH%\SqlPackage.exe ^
/Action:Export ^
/OverwriteFiles:True ^
/SourceDatabaseName:ClientDatabaseName ^
/SourceServerName:(local) ^
/TargetFile:%TEMP%\ConfigurationTables.bacpac ^
/p:TableData="dbo.Table1" ^
/p:TableData="dbo.Table2"
Run Code Online (Sandbox Code Playgroud)