powershelldba.de

Database Restore: Traditional T-SQL vs. Automated PowerShell

Restoring a database sounds simple: run RESTORE DATABASE. But in AlwaysOn environments with users, files, and AG membership, it's complex. Automation handles it differently.

The Traditional Approach: Manual T-SQL Steps

To restore a database in an AlwaysOn environment the "traditional" way:

-- Step 1: Disconnect all users
ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

-- Step 2: Remove from AlwaysOn (if member)
-- (Must connect to primary replica)
ALTER AVAILABILITY GROUP MyAG REMOVE DATABASE MyDatabase;

-- Step 3: Delete from secondary replicas
-- (Connect to each secondary, run:)
DROP DATABASE MyDatabase;

-- Step 4: Restore the database
RESTORE DATABASE MyDatabase
FROM DISK = 'D:\Backups\MyDatabase_Full.bak'
WITH REPLACE;

-- Step 5: Restore transaction logs (if needed)
RESTORE LOG MyDatabase
FROM DISK = 'D:\Backups\MyDatabase_Log.trn'
WITH RECOVERY;  -- NORECOVERY if more logs follow

-- Step 6: Restore users and logins
-- Execute user/login creation scripts (if preserved)

-- Step 7: Fix orphaned users
EXEC sp_change_users_login 'Report';

-- Step 8: Re-add to AlwaysOn
ALTER AVAILABILITY GROUP MyAG ADD DATABASE MyDatabase;

-- Step 9: Set to multi-user
ALTER DATABASE MyDatabase SET MULTI_USER;
GO

The Problem with Manual Restore

The Automated Approach: PowerShell (Invoke-sqmRestoreDatabase)

The sqmSQLTool module provides Invoke-sqmRestoreDatabase, a PowerShell function that handles all steps automatically. A single command replaces the manual 9-step procedure:

# Restore from Full + Diff + Logs, with AlwaysOn handling
$backupSequence = @(
    "D:\Backups\MyDatabase_Full.bak",
    "D:\Backups\MyDatabase_Diff.bak",
    "D:\Backups\MyDatabase_Log.trn"
)

Invoke-sqmRestoreDatabase `
    -SqlInstance "SQL01" `
    -BackupFiles $backupSequence `
    -DatabaseName "MyDatabase" `
    -RejoinAvailabilityGroup

What happens automatically:

Feature-by-Feature Comparison

Feature Manual T-SQL Invoke-sqmRestoreDatabase
AlwaysOn Detection Manual check required Automatic
Remove from AG Manual (easy to forget) Automatic
Delete from Secondaries Manual (connect to each) Automatic
User Export Manual scripts needed Automatic (Export-DbaUser)
Single-User Mode Manual (ALTER DATABASE) Automatic
Full + Diff + Logs Multiple RESTORE statements Single -BackupFiles parameter
File Mapping Manual or script (complex) Automatic (RESTORE FILELISTONLY)
Orphan User Repair Manual (sp_change_users_login) Automatic (Repair-DbaDbOrphanUser)
Rejoin to AG Manual (Add-DbaAgDatabase) Automatic (-RejoinAvailabilityGroup)
Logging None (manual tracking) Detailed audit trail
Error Handling Script must manage Built-in (with rollback)
WhatIf/Confirm Not applicable Supported

Advanced Features of Invoke-sqmRestoreDatabase

1. Automatic File Mapping

Handles physical file renaming and relocation without manual scripting:

Invoke-sqmRestoreDatabase `
    -SqlInstance "SQL01" `
    -BackupFile "D:\Backups\OldDB.bak" `
    -DatabaseName "OldDB" `
    -NewDatabaseName "NewDB" `
    -NewDatabaseFilePath "E:\SQLData" `
    -NewLogFilePath "F:\SQLLogs"

The function automatically maps each file from the backup to new locations.

2. Pre-Restore Backup

Automatically backs up the existing database before restore (for recovery if needed):

Invoke-sqmRestoreDatabase `
    -SqlInstance "SQL01" `
    -BackupFile "D:\Backups\MyDatabase.bak" `
    -DatabaseName "MyDatabase" `
    -BackupBeforeRestore

3. Policy Management

Temporarily disables Policy-Based Management policies during restore to avoid conflicts:

# Policies are automatically disabled, restore runs, then re-enabled
Invoke-sqmRestoreDatabase `
    -SqlInstance "SQL01" `
    -BackupFile "D:\Backups\MyDatabase.bak" `
    -DatabaseName "MyDatabase"

4. WhatIf and Confirm

Preview what would happen without making changes:

Invoke-sqmRestoreDatabase `
    -SqlInstance "SQL01" `
    -BackupFile "D:\Backups\MyDatabase.bak" `
    -DatabaseName "MyDatabase" `
    -WhatIf

When to Use Each Approach

Scenario Manual T-SQL Automated PowerShell
Simple restore (no AG, no users) ✓ Fine ✓ Overkill but safe
AlwaysOn database restore ✗ Error-prone ✓ Designed for this
Restore with user recovery ✗ Manual scripts needed ✓ Automatic
Full + Diff + Logs restore ✗ Multiple statements ✓ Single command
Emergency restore (speed matters) ✗ Slow, error-prone ✓ Fast, reliable
One-time restore ✓ Manual is fine ~ Helps avoid mistakes
Repeating restore (daily/weekly) ✗ Manual each time ✓ Script it once

Risk Comparison

Manual T-SQL Risks

Automated PowerShell Safeguards

Real-World Example: Production Restore

Scenario: Restore Production Database to Test After Data Corruption

Manual Approach (error-prone, time-consuming):

  1. Connect to primary AG member
  2. Remove database from AG (1-2 minutes)
  3. Wait for secondary replicas to drop database (2-3 minutes)
  4. Export users (manual script)
  5. Connect to target SQL instance
  6. Set to single-user mode
  7. Run RESTORE DATABASE
  8. Run RESTORE LOG (multiple times)
  9. Run user import script
  10. Manually fix orphans
  11. Re-add to AG
  12. Verify replication

Total time: 30-45 minutes. Risk of errors at each step.

Automated Approach:

Invoke-sqmRestoreDatabase `
    -SqlInstance "TestSQL01" `
    -BackupFiles $backupSequence `
    -DatabaseName "Production" `
    -NewDatabaseName "Production_Restored" `
    -RejoinAvailabilityGroup

Total time: 10-15 minutes. Automatic handling of all steps with logging.

The Verdict

For AlwaysOn environments: Always use automation. Manual restore is too complex and error-prone. For single-server: Both work, but automation is safer and faster once the script is ready.

Automated restore (Invoke-sqmRestoreDatabase) provides: