练习 - 还原到某个时间点
在此练习中,你将了解如何使用时间点还原 (PITR) 从常见错误中恢复。 可以在门户中或以编程方式轻松执行此过程。 在此练习中,你将了解如何使用 Azure CLI 执行此操作。
设置:使用脚本部署 Azure SQL 数据库
在右侧终端中,你将看到 Azure Cloud Shell,可通过它使用浏览器与 Azure 进行交互。 开始练习之前,你需要在此处运行脚本以创建环境:即具有 AdventureWorks 数据库的 Azure SQL 数据库。 在脚本中,系统会提示输入密码和本地 IP 地址。
完成这些脚本需要 3-5 分钟。 请确保记下密码、唯一 ID 和区域,因为它们将不会再次显示。
若要获得所需的 IP 地址,必须断开与任何 VPN 服务的连接,并在本地 PowerShell 窗口(非此浏览器)中运行
(Invoke-WebRequest -Uri "https://ipinfo.io/ip").Content
。 请注意生成的 IP 地址。在此页右侧的 Azure Cloud Shell 中运行以下脚本。 出现提示时,输入复杂的密码和公共 IP 地址。
$adminSqlLogin = "cloudadmin" $password = Read-Host "Your username is 'cloudadmin'. Please enter a password for your Azure SQL Database server that meets the password requirements" # Prompt for local IP address $ipAddress = Read-Host "Disconnect your VPN, open PowerShell on your machine and run '(Invoke-WebRequest -Uri "https://ipinfo.io/ip").Content'. Please enter the value (include periods) next to 'Address': " # Get resource group and location and random string $resourceGroup = Get-AzResourceGroup | Where ResourceGroupName -like "<rgn>[sandbox resource group name]</rgn>" $resourceGroupName = "<rgn>[sandbox resource group name]</rgn>" $uniqueID = Get-Random -Minimum 100000 -Maximum 1000000 $storageAccountName = "mslearnsa"+$uniqueID $location = $resourceGroup.Location # The logical server name has to be unique in the system $serverName = "aw-server$($uniqueID)"
通过在 Azure Cloud Shell 中运行以下脚本,(在文本文件或类似位置)输出并存储本模块所需的信息。 粘贴到代码中后,可能需要选择 Enter,因为默认不运行最后一行。
Write-Host "Please note your unique ID for future exercises in this module:" Write-Host $uniqueID Write-Host "Your resource group name is:" Write-Host $resourceGroupName Write-Host "Your resources were deployed in the following region:" Write-Host $location Write-Host "Your server name is:" Write-Host $serverName
重要
切记记下密码、唯一 ID 和区域。 在本模块中,你需要使用这些信息。
运行以下脚本,部署具有 AdventureWorks 示例的 Azure SQL 数据库和逻辑服务器。 此脚本还将添加你的 IP 地址作为防火墙规则、启用 Microsoft Defender for Cloud,并创建存储帐户以供后续单元使用。
# The logical server name has to be unique in the system $serverName = "aw-server$($uniqueID)" # The sample database name $databaseName = "AdventureWorks" # The storage account name has to be unique in the system $storageAccountName = $("sql$($uniqueID)") # Create a new server with a system-wide unique server name $server = New-AzSqlServer -ResourceGroupName $resourceGroupName ` -ServerName $serverName ` -Location $location ` -SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $adminSqlLogin, $(ConvertTo-SecureString -String $password -AsPlainText -Force)) # Create a server firewall rule that allows access from the specified IP range and all Azure services $serverFirewallRule = New-AzSqlServerFirewallRule ` -ResourceGroupName $resourceGroupName ` -ServerName $serverName ` -FirewallRuleName "AllowedIPs" ` -StartIpAddress $ipAddress -EndIpAddress $ipAddress $allowAzureIpsRule = New-AzSqlServerFirewallRule ` -ResourceGroupName $resourceGroupName ` -ServerName $serverName ` -AllowAllAzureIPs # Create a database $database = New-AzSqlDatabase -ResourceGroupName $resourceGroupName ` -ServerName $serverName ` -DatabaseName $databaseName ` -SampleName "AdventureWorksLT" ` -Edition "GeneralPurpose" -Vcore 2 -ComputeGeneration "Gen5" # Enable Azure Defender $azureDefender = Enable-AzSqlServerAdvancedDataSecurity ` -ResourceGroupName $resourceGroupName ` -ServerName $serverName # Create a storage account $storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName ` -AccountName $storageAccountName ` -Location $location ` -Type "Standard_LRS"
在本地计算机上,打开 SSMS 并新建与逻辑服务器的连接。 对于服务器名称,请输入 Azure SQL 数据库逻辑服务器的名称。 如果之前未保存该名称,可能需要参阅 Azure 门户获取该名称。 例如:
aw-server\<unique ID>.database.windows.net
。进入 Azure 门户后,可以在搜索框中输入 AdventureWorks,查找数据库及其关联的逻辑服务器。
在“身份验证”框中,输入“SQL Server 身份验证”。 输入相应的服务器管理员登录名和密码(在上一练习的部署过程中所提供的登录名和密码)。
选中“记住密码”框,然后选择“连接”。
注意
根据本地配置(例如 VPN),客户端 IP 地址可能不同于部署期间 Azure 门户所用的 IP 地址。 如果确实不同,你将看到一条消息,显示“客户端 IP 地址无权访问服务器。 请登录到 Azure 帐户并新建防火墙规则以支持访问。”如果收到此消息,请使用要用于沙盒的帐户登录,并为客户端 IP 地址添加防火墙规则。 可以在 SSMS 中使用弹出式向导完成这些步骤。
完成 PITR
继续操作前,务必了解为实现 PITR 所推荐的流程:
- 意外删除表或数据库。
- 确定需要返回的时间;它应该在错误发生之前。
- 通过 PowerShell 或 Azure 门户完成 PITR,以返回到该时间。 该过程会部署新数据库并还原数据库的副本。 例如:AdventureWorks-copy。
- 确认新数据库(例如 AdventureWorks-copy)处于正确状态(和意外发生之前一样)。
- 重命名原始数据库。 例如,将 AdventureWorks 重命名为 AdventureWorks-old。
- 将新数据库重命名为原始数据库名称。 例如,将 AdventureWorks-copy 重命名为 AdventureWorks。
- 删除原始数据库。 例如:AdventureWorks 旧。
在此练习中,你将完成这些步骤。
模拟删除数据
首先,确保要意外删除的表存在且包含数据。 接下来看一下 SalesLT.OrderDetail 中的一些值。
转到 SSMS 并检查/更新连接。 选择“文件”>“连接对象资源管理器”,然后选择“选项”按钮。
请确保所用连接连接的是逻辑服务器,而不是特定的数据库。 (例如使用 <默认>,如以下屏幕截图所示。)此外,确认“其他连接参数”选项卡不包含任何文本。
展开“数据库”文件夹,然后右键单击 AdventureWorks 数据库并选择“新建查询”。 输入以下查询并通过选择“执行”来运行它,然后查看结果:
SELECT TOP 10 * from SalesLT.SalesOrderDetail
通过删除数据库中的表,模拟数据丢失。
在同一查询窗口中,运行此查询,然后在“结果”窗口中选择“消息”选项卡,并记下完成时间:
DROP TABLE SalesLT.SalesOrderDetail
重要
保存完成时间。 稍后需要用到此信息。 下面是一个示例:
Completion time: 2020-06-22T09:20:27.1859237-07:00
。最后,请在此页右侧的 Azure Cloud Shell 中运行以下代码来配置环境,然后再开始执行还原数据库的步骤:
$resourceGroup = Get-AzResourceGroup | Where ResourceGroupName -like <rgn>[sandbox resource group name]</rgn> $server = Get-AzureRmSqlServer -ResourceGroupName $resourceGroup.ResourceGroupName $logical_server = $server.ServerName $resource_group = $resourceGroup.ResourceGroupName # Specify your default resource group and Azure SQL Database logical server az configure --defaults group=$resource_group sql-server=$logical_server # Confirm the defaults are set az configure --list-defaults
返回的
group
和sql-server
参数应与 Microsoft Learn 资源组和 Azure SQL 数据库逻辑服务器的名称匹配。
确定数据库将还原到的时间
第一步是确定数据库将还原到的时间。 你需要知道“错误”事务发生前的最近一次“正确”事务的发生时间。 你将还原到该“错误”事务之前以及该“正确”事务之后。
确定删除时间的其中一种方法是,查看在上一步中记下的 DROP 语句的完成时间。
另一种方法是在 Azure 门户中使用审核日志。 在此练习中,你没有为 Log Analytics 配置审核,但让我们探索一下已配置审核的情况下你可以执行的操作。 在 Azure 门户中,转到 Azure SQL 数据库。 在左侧窗格的“安全性”下,可以选择“审核”,然后可选择“查看审核日志”。 选择“Log Analytics”后,系统会将你转到查询编辑器,以支持你使用 Kusto 查询语言 (KQL) 查询日志。 SQL 专业人员可使用此查询语言轻松查询日志。
然后,可运行以下 KQL 查询:
search database_name_s == "AdventureWorks" | where Category == 'SQLSecurityAuditEvents' and statement_s like 'DROP' | project format_datetime(event_time_t, 'yyyy-MM-dd hh:mm:ss.fff'), ResourceGroup, server_instance_name_s, database_name_s, statement_s, succeeded_s,client_ip_s, server_principal_name_s, application_name_s | sort by event_time_t desc
结果应与以下结果类似,但具有不同的日期和时间。
注意
日志可能需要 5 到 10 分钟才能显示在此处,因此出于本练习的目的,我们已将其忽略。你将改用上一步中记录的完成时间。 (需要将其转换为 GMT。)在实际情况中,不太可能访问含完成时间的窗口,因此使用审核会很有帮助。
在本示例中,Log Analytics 中的日期/时间为
2020-07-24 08:06:24.386
,而 SSMS 中为2020-07-24T13:06:24.386-07:00
。 规定的格式略有不同。 使用以下示例来确定正确的格式。 你可能还需要减去 0.001 秒,确保还原到错误发生前的时间:- Log Analytics 格式:
2020-07-24 08:06:24.386
- SSMS 格式:
2020-07-24T13:06:24.386-07:00
- 规定的格式:
2020-07-24T20:06:24.385
- Log Analytics 格式:
将
$before_error_time
设置为生成的值,从而将你的时间替换为本示例中的时间:$before_error_time ="2020-07-24T20:06:24.385"
还原数据库并确认丢失的数据
在本节中,你将使用 az cli db restore
将数据库还原到删除表之前的时间。
在此窗口右侧的终端中运行以下脚本:
# Restore the database to a time before the database was deleted az sql db restore --dest-name "AdventureWorks-copy" --name "AdventureWorks" --time $before_error_time --verbose
还原大约需要 5 到 10 分钟。 运行还原时,Azure 会在 Azure SQL 数据库逻辑服务器中部署新的 Azure SQL 数据库。 该数据库的所有配置选项与原始数据库相同。 部署 Azure SQL 数据库后,Azure 会将数据库还原到新的 Azure SQL 数据库中。
可以通过刷新 SSMS 中的数据库视图以查看状态。 右键单击“数据库”文件夹并选择“刷新”。 部署数据库后,你现在将看到正在进行还原:
看到还原进行后,此还原还应需要 2 到 3 分钟才会完成。 完成后你会知道,因为命令将结束。 另外,刷新后,副本数据库旁将不再显示“(正在还原...)”。
如果你发现还原花费的时间比前面所述的时间更长,那可能是 Microsoft Learn 环境所致。 单个订阅可以同时处理/提交的还原请求数有限。 如果在等待时希望详细了解 PITR 的限制和相关详细信息。请参阅从 Azure SQL 数据库中的备份还原数据库。
接下来请确认新数据库处于正确状态(和意外发生之前的状态一样)。 请右键单击 SSMS 中的逻辑服务器,再选择“刷新”以刷新与 Azure SQL 数据库逻辑服务器的连接。
右键单击新数据库(例如 AdventureWorks-copy)并选择“新建查询”。
使用此查询确认表是否存在:
SELECT TOP 10 * from SalesLT.SalesOrderDetail
应显示类似于下面屏幕截图中所示的结果。 此结果确认数据库将还原到你想要的位置。
交换数据库并清理
接下来,将原始数据库重命名为 AdventureWorks-old,以便稍后可以将新数据库重命名为原始数据库名称。 只要应用程序使用重试逻辑,就可实现这一变化,而无需更改任何连接字符串。
如果数据库在任何时候都显示为不可用(例如,刷新连接后无法连接到 SSMS 中的数据库),则可能是因为 DNS 表进行了更新。 因此,尽管数据库实际上并非不可用,但却不可解析。 等待一分钟左右应能够恢复正常活动。
使用此命令来更改数据库名称:
az sql db rename --name "AdventureWorks" --new-name "AdventureWorks-old"
由于不再使用原始数据库名称,因此可以再次使用 Azure Cloud Shell 将副本数据库重命名为原始数据库的名称:
az sql db rename --name "AdventureWorks-copy" --new-name "AdventureWorks"
不需要旧数据库,因此可以使用
az sql db delete
将其删除:az sql db delete --name "AdventureWorks-old" --yes Write-Host "Database deleted"
可以使用以下命令确认旧数据库是否不再存在:
az sql db list -o table
现在,你了解了如何在 Azure SQL 数据库中使用 PITR。 PITR 还可用于 Azure SQL 托管实例中的数据库,而不是整个实例。 你可以使用几乎相同的命令,只是需要使用 az sql midb
而不是 az sql db
。