删除具有活动租约的备份 Blob 文件
备份到 Azure 存储或从 Azure 存储还原时,SQL Server会获取无限租约,以锁定对 Blob 的独占访问。 当成功完成备份或还原过程时,释放租约。 如果备份或还原失败,备份过程将尝试清除所有无效 blob。 但是,如果备份由于长期或持续的网络连接故障而失败,则备份过程可能无法访问 Blob,并且 Blob 可能保持孤立状态。 这意味着在释放租约前,不能写入或删除 blob。 本主题说明如何释放租约和删除 blob。
有关租约类型的详细信息,请阅读此 文章。
如果备份操作失败,它可能生成无效的备份文件。 备份 blob 文件可能还有活动租约,以防止其被删除或覆盖。 为了删除或覆盖这类 blob,应首先中断租约。如果备份失败,我们建议您清除租约并删除 blob。 您还可以选择作为存储管理任务一部分的定期清除。
如果还原失败,将不阻止后续还原,因此活动租约不会导致问题。 仅当必须覆盖或删除 blob 时,才有必要中断租约。
管理孤立的 Blob
以下步骤说明在备份或还原活动失败后如何进行清除。 可以使用 PowerShell 脚本来执行所有这些步骤。 在接下来的章节中提供了代码示例:
标识具有租约的 blob: 如果您有运行备份过程的脚本或进程,可能可以捕获脚本或进程内的失败并使用它清除 blob。 您还可以使用 LeaseStats 和 LeastState 属性来标识具有租约的 blob。 一旦您标识了 blob,我们建议您查看列表,在删除 blob 前验证备份文件的有效性。
中断租约: 获得授权的请求可以中断租约而不提供租约 ID。 有关详细信息,请参阅 此处 。
提示
SQL Server 发出租约 ID 以在还原操作期间建立独占访问。 还原租约 ID 是 BAC2BAC2BAC2BAC2BAC2BAC2BAC2BAC2。
删除 Blob: 要删除具有活动租约的 blob,必须首先中断租约。
PowerShell 脚本示例
**重要** 如果运行的是 PowerShell 2.0,则可能在加载 Microsoft WindowsAzure.Storage.dll 程序集时遇到问题。 我们建议您升级到 Powershell 3.0 以解决该问题。 您也可以为 PowerShell 2.0 使用以下解决方法:
使用以下语句创建或修改 powershell.exe.config 文件以在运行时加载 .NET 2.0 和 .NET 4.0 程序集:
<?xml version="1.0"?> <configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0.30319"/> <supportedRuntime version="v2.0.50727"/> </startup> </configuration>
下面的示例说明了如何标识具有活动租约的 blob,然后中断租约。 该示例还演示如何为释放租约 ID 进行筛选。
有关运行此脚本的提示
警告
如果备份到 Azure Blob 存储服务与此脚本同时运行,则备份可能会失败,因为此脚本将中断备份尝试同时获取的租约。 我们建议在维护时间段或预计没有执行备份时运行此脚本。
运行此脚本时,系统会提示你提供存储帐户、存储密钥、容器以及 Azure 存储程序集路径和名称参数的值。 存储程序集的路径为 SQL Server实例的安装目录。 存储程序集的文件名为 Microsoft.WindowsAzure.Storage.dll。 以下是提示和输入的值的示例:
cmdlet at command pipeline position 1 Supply values for the following parameters: storageAccount: mycloudstorageaccount storageKey: 0BopKY7eEha3gBnistYk+904nf blobContainer: mycontainer storageAssemblyPath: C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Binn\Microsoft.WindowsAzure.Storage.dll
如果没有已锁定租约的 blob,您应该看到以下消息:
没有具有已锁定租约状态的 blob
如果有具有已锁定租约的 blob,您应该看到以下消息:
正在中断租约
Blob> URL 上的<租约是还原租约:仅当具有还原租约仍处于活动状态的 Blob 时,才会看到此消息。
Blob> URL 上的<租约不是对 Bob> 的 URL 中断<租约的还原租约。
param(
[Parameter(Mandatory=$true)]
[string]$storageAccount,
[Parameter(Mandatory=$true)]
[string]$storageKey,
[Parameter(Mandatory=$true)]
[string]$blobContainer,
[Parameter(Mandatory=$true)]
[string]$storageAssemblyPath
)
# Well known Restore Lease ID
$restoreLeaseId = "BAC2BAC2BAC2BAC2BAC2BAC2BAC2BAC2"
# Load the storage assembly without locking the file for the duration of the PowerShell session
$bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath)
[System.Reflection.Assembly]::Load($bytes)
$cred = New-Object 'Microsoft.WindowsAzure.Storage.Auth.StorageCredentials' $storageAccount, $storageKey
$client = New-Object 'Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient' "https://$storageAccount.blob.core.windows.net", $cred
$container = $client.GetContainerReference($blobContainer)
#list all the blobs
$allBlobs = $container.ListBlobs()
$lockedBlobs = @()
# filter blobs that are have Lease Status as "locked"
foreach($blob in $allBlobs)
{
$blobProperties = $blob.Properties
if($blobProperties.LeaseStatus -eq "Locked")
{
$lockedBlobs += $blob
}
}
if ($lockedBlobs.Count -eq 0)
{
Write-Host " There are no blobs with locked lease status"
}
if($lockedBlobs.Count -gt 0)
{
Write-Host "Breaking leases"
foreach($blob in $lockedBlobs )
{
try
{
$blob.AcquireLease($null, $restoreLeaseId, $null, $null, $null)
Write-Host "The lease on $($blob.Uri) is a restore lease"
}
catch [Microsoft.WindowsAzure.Storage.StorageException]
{
if($_.Exception.RequestInformation.HttpStatusCode -eq 409)
{
Write-Host "The lease on $($blob.Uri) is not a restore lease"
}
}
Write-Host "Breaking lease on $($blob.Uri)"
$blob.BreakLease($(New-TimeSpan), $null, $null, $null) | Out-Null
}
}