如果 SQL Server 資料庫檔案分散在多個磁碟上,您可以同時備份所有磁碟,維持應用程式和資料的一致性。您可以使用 Compute Engine 即時快照一致性群組,達成這個精確的時間點備份,備份一組磁碟中的資料。
本教學課程說明如何使用 Compute Engine 快照,以及 SQL Server 2022 以上版本提供的 Transact-SQL (T-SQL) 快照功能,備份 SQL Server 資料庫。這項解決方案支援 Windows 和 Linux 部署作業,並盡量減少對即時工作負載的效能影響。
運作方式
工作流程包含下列主要步驟,這些步驟由在運算執行個體上執行的指令碼管理:
- 凍結資料庫:指令碼會將 T-SQL 指令傳送至 SQL Server,暫停目標資料庫的所有寫入作業。確保資料庫檔案處於一致狀態,方便備份。
- 建立即時快照:在資料庫凍結期間,為資料庫資料和記錄檔所在的磁碟建立一組即時快照。這相當於使用硬體或服務層級的快照機制。 Google Cloud
- 記錄及解除凍結:指令碼會將另一個 T-SQL 指令傳送至 SQL Server,以記錄備份中繼資料。這個指令會建立小型備份檔案,指向即時快照的一致性群組,並記錄在
msdb備份記錄中。完成後,SQL Server 會自動解除凍結資料庫,並恢復正常運作。
整個過程通常會在不到一秒內完成,盡量縮短資料庫寫入凍結的時間。凍結期間,系統可以讀取資料,但無法寫入。您可以為資料庫設定 SUSPEND_FOR_SNAPSHOT_BACKUP=OFF,手動取消凍結狀態。
目標
在本教學課程中,您將瞭解如何完成下列工作:- 建立具備兩個資料磁碟的 SQL Server 執行個體。
- 使用不同磁碟上的資料和記錄檔建立新資料庫。
- 為執行 SQL Server 的 VM 的所有磁碟建立一致性群組。
- 建立磁碟群組的即時快照。
- 從即時快照建立新磁碟。
費用
在本文件中,您會使用下列 Google Cloud的計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。
事前準備
本教學課程需要 Google Cloud 專案。您可以建立新專案,或是選取現有專案:
-
在 Google Cloud 控制台的專案選擇器頁面中,選取或建立 Google Cloud 專案。
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
-
建立專案:如要建立專案,您需要「專案建立者」角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
在 Google Cloud 控制台中啟用 Cloud Shell。
-
確認已安裝並執行 Microsoft SQL Server 2022 以上版本。
所需權限
除了標準讀取權限外,請確保 SQL Server 管理員授予您目標資料庫的 ALTER DATABASE 權限。
如要取得建立執行個體和快照所需的權限,請要求管理員授予您專案的下列 IAM 角色:
-
管理執行個體:
compute.instanceAdmin.v1 -
建立快照:
compute.storageAdmin
如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。
建立 Compute Engine SQL 執行個體
建立 SQL Server 執行個體。
在 Google Cloud 控制台中,按一下「啟用 Cloud Shell」
按鈕,開啟 Cloud Shell。
建立 SQL Server 執行個體。貼上下列指令:
REGION=REGIONZONE=$REGION-a VM_NAME=VM_NAMEgcloud compute instances create $VM_NAME \ --boot-disk-auto-delete \ --boot-disk-size 100 \ --boot-disk-type hyperdisk-balanced \ --image-family sql-std-2022-win-2025 \ --image-project windows-sql-cloud \ --machine-type c4-highmem-4 \ --zone $ZONE \ --network-interface subnet=default \ --tags sql-server-instant-snapshot \ --scopes=cloud-platform,service-control,service-management,monitoring-write,logging-write,storage-rw \ --create-disk=device-name=$VM_NAME-data-disk1,mode=rw,name=$VM_NAME-data-disk1,size=100,type=hyperdisk-balanced \ --create-disk=device-name=$VM_NAME-data-disk2,mode=rw,name=$VM_NAME-data-disk2,size=100,type=hyperdisk-balanced
更改下列內容:
- 區域:新執行個體的部署區域。
- VM_NAME:新 SQL Server 執行個體的名稱。
建立磁碟一致性群組
建立一致性群組。
gcloud compute resource-policies create disk-consistency-group $VM_NAME-snap-grp \ --region=$REGION將 VM 的磁碟新增至一致性群組。
gcloud compute disks add-resource-policies $VM_NAME \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp gcloud compute disks add-resource-policies $VM_NAME-data-disk1 \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp gcloud compute disks add-resource-policies $VM_NAME-data-disk2 \ --zone=$ZONE \ --resource-policies=$VM_NAME-snap-grp
建立新的資料庫
- 建立 VM 執行個體的使用者名稱和密碼。
- 使用遠端桌面連線至 VM,並使用上一步建立的使用者名稱和密碼登入。
- 在「開始」按鈕上按一下滑鼠右鍵 (或按下 Win+X 鍵),然後按一下「終端機 (系統管理員)」。
- 按一下「是」,確認提升權限提示。
在開啟的終端機視窗中執行下列 PowerShell 指令碼。這個指令碼會初始化資料磁碟、以 64 KB 區塊大小格式化磁碟,並指派磁碟機代號。
$availableDisks = Get-PhysicalDisk -CanPool $True $diskLetters = [char[]] (68..72) | Where-Object { !(Get-PSDrive $_ -ErrorAction SilentlyContinue) } $diskCount = 0 foreach ($disk in $availableDisks) { $diskLetter = $diskLetters[$diskCount] $diskLabel = "$diskLetter-DataDisk" Initialize-Disk -Number $disk.DeviceId -PartitionStyle MBR -PassThru New-Partition -DiskNumber $disk.DeviceId -UseMaximumSize ` -DriveLetter $diskLetter | Format-Volume -FileSystem NTFS ` -NewFileSystemLabel $diskLabel -AllocationUnitSize 65536 -Confirm:$false New-Item -ItemType Directory -Path "$($diskLetter):\MSSQL" $diskCount = $diskCount +1 }開啟 SQL Server Management Studio (SSMS)。以管理員身分執行。
在「連線到伺服器」對話方塊中,確認伺服器名稱已設為
localhost,然後選取「連線」。在檔案選單中,依序選取「檔案」>「新增」>「查詢」,並使用目前的連線。
將下列程式碼複製到新開啟的查詢視窗。
USE Master; GO CREATE DATABASE SnapBackupDB ON PRIMARY ( NAME = 'SnapBackupDB_Data', FILENAME = 'D:\MSSQL\SnapBackupDB.mdf', SIZE = 500MB, MAXSIZE = UNLIMITED, FILEGROWTH = 64MB ) LOG ON ( NAME = 'SnapBackupDB_Log', FILENAME = 'E:\MSSQL\SnapBackupDB_log.ldf', SIZE = 250MB, MAXSIZE = 2GB, FILEGROWTH = 64MB );
部署快照指令碼
這項指令碼會自動執行完整程序,為連結至執行 SQL Server 的 VM 的磁碟建立應用程式一致性快照。
- 在同一個遠端桌面連線中開啟記事本。
- 複製下列指令碼的內容,然後貼到開啟的「記事本」視窗中。
將檔案儲存為
take-snapshot.ps1,並放在c:\scripts# Import Modules Import-Module -Name SQLPS # Set variables $formattedTimestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $backupLocation = 'D:\MSSQL\Backup' $dbName = 'SnapBackupDB' $bkmFile = Join-Path -Path $backupLocation -ChildPath ("${dbName}_${formattedTimestamp}.bkm") $sqlServer = 'localhost' # SQL Commands $suspendDbCmd = "ALTER DATABASE [$dbName] SET SUSPEND_FOR_SNAPSHOT_BACKUP=ON WITH NO_WAIT;" $backupMetadataCmd = "BACKUP DATABASE [$dbName] TO DISK='$bkmFile' WITH METADATA_ONLY, FORMAT;" $unsuspendDbCmd = "ALTER DATABASE [$dbName] SET SUSPEND_FOR_SNAPSHOT_BACKUP=OFF;" # --- Helper Function for SQL Execution --- function Invoke-MySqlCommand { param( [Parameter(Mandatory=$true)] [string]$CommandText, [Parameter(Mandatory=$true)] [System.Data.SqlClient.SqlConnection]$SqlConnection ) Write-Host "Executing SQL Command: $($CommandText)" try { $Command = New-Object System.Data.SqlClient.SqlCommand($CommandText, $SqlConnection) $Result = $Command.ExecuteNonQuery() return $true } catch { Write-Host "Error executing SQL Command: $($CommandText)`n$($_.Exception.Message)" -ForegroundColor Red return $false } } $sqlConn = New-Object System.Data.SqlClient.SqlConnection $sqlConn.ConnectionString = "server='$sqlServer';database='$dbName';Integrated Security=True;" $databaseSuspended = $false if (-not(Test-Path $backupLocation)) { New-Item -Path $backupLocation -ItemType directory -Force } try { $instanceName = (Invoke-RestMethod -Headers @{"Metadata-Flavor"="Google"} -Uri "http://metadata.google.internal/computeMetadata/v1/instance/name") $vmConfigString = (gcloud compute instances list --filter="name=('$instanceName')" --format=json --quiet) if ($LASTEXITCODE -ne 0) { Write-Host "Error querying gcloud for VM instances (exit code: $LASTEXITCODE). Exiting." -ForegroundColor Red exit 1 } $vmConfig = $vmConfigString | ConvertFrom-Json # Open SQL Server connection $sqlConn.Open() # Suspend Database Write-Host "Suspending database '$dbName' for snapshot..." if (-not (Invoke-MySqlCommand -CommandText $suspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to suspend database. Exiting." -ForegroundColor Red exit 1 } $databaseSuspended = $true # Take a disk snapshot try { $consistencyGroupListStr = (gcloud compute resource-policies list --filter='name:*-snap-grp' --format=json --quiet) if ($LASTEXITCODE -ne 0) { throw "gcloud resource-policies list failed (exit code: $LASTEXITCODE)." } $consistencyGroupList = $consistencyGroupListStr | ConvertFrom-Json if (@($consistencyGroupList).Count -eq 0) { throw "No consistency group found matching '*-snap-grp'." } if (@($consistencyGroupList).Count -gt 1) { Write-Warning "More than one consistency group found, using the first one." } $consistencyGroupSelfLink = $consistencyGroupList[0].selfLink $zoneName = Split-Path $vmConfig[0].zone -Leaf $snapshotName = "$($vmConfig.Name)-${formattedTimestamp}" $snapshotCmd = "gcloud compute instant-snapshot-groups create $snapshotName --source-consistency-group=$consistencyGroupSelfLink --zone=$zoneName --quiet" Invoke-Expression $snapshotCmd if ($LASTEXITCODE -ne 0) { throw "gcloud compute instant-snapshot-groups create failed (exit code: $LASTEXITCODE)." } Write-Host "Instant snapshot group created successfully." } catch { Write-Host "Error during snapshot creation: $($_.Exception.Message)" -ForegroundColor Red exit 1 # Exit after handling in finally } # Backup database metadata if (-not (Invoke-MySqlCommand -CommandText $backupMetadataCmd -SqlConnection $sqlConn)) { Write-Host "Failed to backup database metadata." -ForegroundColor Red exit 1 } # Unsuspend Database Write-Host "Unsuspending database '$dbName'..." if (-not (Invoke-MySqlCommand -CommandText $unsuspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to unsuspend database after successful snapshot and metadata backup. Manual intervention may be required." -ForegroundColor Red exit 1 } $databaseSuspended = $false # Successfully unsuspended } catch { Write-Host "An unhandled error occurred: $($_.Exception.Message)" -ForegroundColor Red exit 1 } finally { if ($databaseSuspended -and ($sqlConn.State -eq [System.Data.ConnectionState]::Open)) { if (-not (Invoke-MySqlCommand -CommandText $unsuspendDbCmd -SqlConnection $sqlConn)) { Write-Host "Failed to unsuspend database in finally block. Manual intervention may be required." -ForegroundColor Red } } # Ensure SQL connection is closed if ($sqlConn.State -eq [System.Data.ConnectionState]::Open) { $sqlConn.Close() } }在「開始」按鈕上按一下滑鼠右鍵 (或按下 Win+X 鍵),然後按一下「終端機 (系統管理員)」。
按一下「是」,確認提升權限提示。
執行下列指令來執行指令碼。
C:\scripts\take-snapshot.ps1
確認已建立即時快照
在 Cloud Shell 中執行下列指令:
確認指令碼已建立快照。
gcloud compute instant-snapshots list --filter="name:$VM_NAME*"列出即時快照群組。
gcloud compute instant-snapshot-groups list --zones $ZONE查看即時快照群組的詳細資料。
gcloud compute instant-snapshot-groups describe \INSTANT_SNAPSHOT_NAME--zone=$ZONE複製
selfLink值,以便在下一節中使用。
將即時快照還原到新磁碟
在 Google Cloud 控制台視窗中執行下列指令。
從即時快照一致性群組建立磁碟。
gcloud compute disks bulk create --source-instant-snapshot-group \INSTANT_SNAPSHOT_NAME_URL\ --source-instant-snapshot-group-region $REGION --zone=$ZONE列出可用區中的磁碟,確認快照已還原。
gcloud compute disks list --zones=$ZONE --filter="name:$VM_NAME-*"從新建立的磁碟建立新的 VM。
REGION=
REGIONZONE=$REGION-a VM_NAME=VM_NAMEgcloud compute instances create $VM_NAME \ --machine-type c4-highmem-4 \ --zone $ZONE \ --network-interface subnet=default \ --tags sql-server-instant-snapshot \ --disk=name=BOOT_DISK_NAME,boot=yes,auto-delete=no \ --disk=name=DATA_DISK_1_NAME,mode=rw,auto-delete=no \ --disk=name=DATA_DISK_2_NAME,mode=rw,auto-delete=no
更改下列內容:
- 區域:新執行個體的部署區域。
- VM_NAME:新 SQL 執行個體的名稱。
- BOOT_DISK_NAME:在上一個步驟中建立的開機磁碟名稱。
- DATA_DISK_1_NAME:在上一個步驟中建立的第一個資料磁碟名稱。
- DATA_DISK_2_NAME:在上一個步驟中建立的第二個資料磁碟名稱。
現在可以將磁碟連結至新的或現有的 VM。
清除所用資源
如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除專案。
刪除專案
- 前往 Google Cloud 控制台的「Manage resources」(管理資源) 頁面。
- 在專案清單中選取要刪除的專案,然後點選「Delete」(刪除)。
- 在對話方塊中輸入專案 ID,然後按一下 [Shut down] (關閉) 以刪除專案。
後續步驟
- 查看 Google Cloud 的參考架構、圖表和最佳做法。 歡迎瀏覽我們的 Cloud Architecture Center。