我想使用 SQL 代理作业(这很可能涉及执行 SSIS 包)动态备份给定 SSAS 实例上的所有数据库。这是一个动态过程,这一点势在必行——如果用户添加数据库或多维数据集,我想一次性设置一项可以自动检测所有现有 SSAS 元数据的作业。
不幸的是,我没有看到任何东西告诉我如何以干净的方式自动和动态地备份 SSAS 实例上的所有数据库。“干净”,我的意思是:
DatabaseId
备份命令,不是的DatabaseName
。有时可以有之间的差异DatabaseName
和DatabaseId
,如果有是有差别,如果备份将无法DatabaseName
代替的使用DatabaseId
。仅查询目录架构不会给我DatabaseId
.这实际上是可以做到的。可能有几种方法可以做到这一点,这里是一个相当简单的例子。对于此解决方案,您将使用以下组合:
Execute Script Task
是使用分析管理对象(AMO) 。变量名称|范围|类型
备份目录 | 包级别或 Foreach 级别 | 细绳
数据库 ID | 包级别或 Foreach 级别 | 细绳
数据库名称 | 包级别或 Foreach 级别 | 细绳
InstanceForDatasource | 套餐级别 | 细绳
连接字符串 | 套餐级别 | 细绳
将 EvaluateAsExpression 属性设置为 true。
设置 Expression 属性如下: Data Source="+ @[User::InstanceForDatasource] +";Provider=MSOLAP.4;Integrated Security=SSPI;
请注意,如果需要,可以扩展此方法以使整个 ConnectionString 动态并由调用 SQL 代理作业步骤指示。
XMLAScript | 包或 Foreach 级别 | 细绳
在设计时使用真正的连接,以便元数据播放得很好。
现在不需要创建连接管理器,但它使以后更容易。对于流程中的每项任务,您都可以在下拉列表中使用适当的连接管理器,而无需即时创建任何连接管理器。
网
[User::ConnectionString]
有机发光二极管
[User::ConnectionString] + "Format=Tabular;"
分析服务
[User::ConnectionString] = "Impersonation Level=Impersonate;"
在这里,您将基于 Catalogs 架构行集创建一个 Foreach。这将为我们获取DatabaseName
实例中的每个数据库,DatabaseName
并将被放入其相应的变量中。
将脚本设置为使用 Visual Basic。
设置 ReadOnlyVariables 和 ReadWriteVariables 如下:
User::ConnectionString,User::DatabaseName,User::InstanceForDatasource
User::BackupDir,User::DatabaseId,User::XMLAScript
编辑脚本
添加对分析管理对象 (AMO) 程序集的引用。
右键单击项目名称(应该是单击“编辑脚本”时打开的 Visual Studio 窗口中“项目资源管理器”中最顶部的项目)并选择“添加引用”。
添加对 Analysis Services 对象组件的引用。AMO 的 dll 应位于 <SQL Server InstallationDrive>:\Program Files\Microsoft SQL Server\<SQL Server Version>\SDK\Assemblies
.
在脚本标头中,添加 Imports 语句以使用 AMO: Imports Microsoft.AnalysisServices
将 Public Sub Main() 的内容替换为以下脚本:
Public Sub Main()
'
Dim ASServer As New Microsoft.AnalysisServices.Server()
Dim AsDatabase As New Microsoft.AnalysisServices.Database
Dim ASConn As String = ""
Dim ASDatabaseName As String = ""
Dim ASDatabaseId As String = ""
'Create a variable that uses the dynamic ConnectionString variable
ASConn = Dts.Variables("ConnectionString").Value
'What database are we working with in this iteration of the Foreach?
ASDatabaseName = Dts.Variables("DatabaseName").Value
'Use the Analysis Services AMO to get the DatabaseId for this DatabaseName.
' It is necessary to get the DatabaseId because the XMLA backup command requires the DatabaseId,
' and if at any point the database is renamed, the DatabaseId will differ from the DatabaseName.
Try
'Establish the connection to SSAS.
ASServer.Connect(ASConn)
'Get the database.
AsDatabase = ASServer.Databases.FindByName(ASDatabaseName)
'***ONLY IF the EstimatedSize > 0***.
' --> If it is 0, it could be a corrupted database which causes the backup process to stop.
' --> In that case, we will leave the DatabaseId variable blank to be a visiblie indicator that the db is corrupt.
'***ONLY IF the number of cubes > 0***.
' --> The databse could be corrupt or backup could hang if there are no cubes.
If AsDatabase.EstimatedSize > 0 And AsDatabase.Cubes.Count > 0 Then
'Get the DatabaseId
'Retrieve the DatabaseId from the Databases collection.
ASDatabaseId = ASServer.Databases.FindByName(ASDatabaseName).ID
Else
Dts.Events.FireWarning(0, "Verifying database", "The estimated size and/or number of cubes in the database does not meet the requirements. Estimated Size= " & AsDatabase.EstimatedSize & "; " & "Number of cubes= " & AsDatabase.Cubes.Count, String.Empty, 0)
End If
Catch ex As Exception
'Couldn't connect. Do not error out because maybe the next iteration will succeed.
Dts.Events.FireWarning(0, "Establishing SSAS Connection", "Unable to connect to the SSAS Server with ConnectionString= '" & ASConn & "'. Error: " & ex.ToString, String.Empty, 0)
End Try
'Print info for output while testing/debugging.
Dts.Events.FireInformation(0, "Establishing SSAS Connection", "Connection established. ConnectionString= '" & ASConn & "'.", String.Empty, 0, True)
'Put the DatabaseId into the SSIS variable.
Dts.Variables("DatabaseId").Value = ASDatabaseId
'If we were able to retrieve the DatabaseId, then generate the backup directory and filename and the XMLA script.
If ASDatabaseId <> "" Then
'Print info for output while testing/debugging.
Dts.Events.FireInformation(0, "Retrieving DatabaseId", "DatabaseId retrieved for " & ASDatabaseName & ". DatabaseId= '" & ASDatabaseId & "'.", String.Empty, 0, True)
'Get timestamp for the backup file
Dim timeStamp As String = Now.Year & _
Right("0" & Now.Month, 2) & _
Right("0" & Now.Day, 2) & _
Right("0" & Now.Hour, 2) & _
Right("0" & Now.Minute, 2) & _
Right("0" & Now.Second, 2)
'Get the filename and location for the backupfile
Dim filePath As String = "\\<servershare>\" & Dts.Variables("ServerForDatasource").Value & "\" & ASDatabaseName
Dim fileName As String = ASDatabaseName & "_" & timeStamp & ".abf"
'Put the filepath into the SSIS variable
Dts.Variables("BackupDir").Value = filePath
'Print info for output while testing/debugging
Dts.Events.FireInformation(0, "Retrieving full backup path", "BackupPath= '" & filePath & "\" & fileName & "'.", String.Empty, 0, True)
'Build XMLA script
Dim xmlaScript As String = ""
xmlaScript = "<Backup xmlns=""http://schemas.microsoft.com/analysisservices/2003/engine"">" & _
"<Object><DatabaseID>" & ASDatabaseId & "</DatabaseID></Object>" & _
"<File>" & filePath & "\" & fileName & "</File>" & _
"</Backup>"
'Put the XMLA script into the SSIS variable
Dts.Variables("XMLAScript").Value = xmlaScript
'Print info for output while testing/debugging.
Dts.Events.FireInformation(0, "Generate XMLAScript", "XMLAScript= '" & xmlaScript & "'.", String.Empty, 0, True)
Else
'Print info for output while testing/debugging.
'If DatabaseId is empty, we will not perform the rest of the tasks in the Foreach container.
Dts.Events.FireWarning(0, "Retrieving DatabaseId", "Unable to retrieve the DatabaseId for Database= '" & ASDatabaseName & "'.", String.Empty, 0)
End If
' Return success
Dts.TaskResult = ScriptResults.Success
End Sub
Run Code Online (Sandbox Code Playgroud)如果备份目录已经存在,设置UseDirectoryIfExists
为true
以避免错误很重要。
此优先约束将处理丢失的 DatabaseId。如果无法在 vbscript 中建立到 SSAS 服务器的连接,或者数据库已损坏,则 DatabaseId 将丢失。您不想备份损坏的数据库。它将使备份停止。
表达式示例:`@[User::DatabaseId] !=""
InstanceForDatasource
为步骤的实例名称。
Property Path
:\Package.Variables[User::InstanceForDatasource].Properties[Value]
笔记:
要使整个备份目录动态化,您只需为此添加另一个变量并在 vbscript 中对其进行说明。
同样,如有必要,整个连接字符串变量可以由 SQL 代理作业设置,而不仅仅是实例名称。