Welcome to MSDN Blogs Sign in | Join | Help

Configure Database Mirroring using SQL 2008 Power Shell

###########################################################################################
# Scenario: Configure Database mirroring
#
#  How to use this powershell script:
#    - Launch SQL Server PowerShell ( Start -> Run -> sqlps.exe)
#    - Copy the following powershell script and save to file (Ex c:\DBMirrroringSetup.ps1)
#    - in powershell window, type in script file path ( Ex: c:\DBMirrroringSetup.ps1) to run the script
###########################################################################################

# Backup Database
function BackupDatabase
{
        Param([string]$servername, [string]$dbName, [string]$backupfiledir, [Microsoft.SqlServer.Management.Smo.BackupActionType]$actionType
)

       $server = GetServer($servername
)

       
# construct a unique backup file name
        $backupfilepath = $backupfiledir + "\" + $dbName +  "-" + $actionType.ToString() + "-" +[DateTime]::Now.ToString('s').Replace(":","-") +
".bak"
       
        $backup = new-object ('Microsoft.SqlServer.Management.Smo.Backup'
)
        $backup.Action = $actionType
        $backup.Database =
$dbName
        $backup.Devices.AddDevice($backupfilepath, [Microsoft.SqlServer.Management.Smo.DeviceType]::File
)

        $backup.SqlBackup($server
)

        write-host
"Backup completed successfully"
        write-host "Server:",$server.Name
        write-host
"Database:$dbName"
        write-host
"Backup File:$backupfilepath"
       
        $backupfilepath
;
}

# Restore Database
function RestoreDatabase
{
        Param([string]$servername, [string]$dbName, [string]$backupDataFile
)

        $server = GetServer($servername
)
        $targetDBFilePath = $server.MasterDBPath + "\" + $dbName +  "-Data-" + [DateTime]::Now.ToString('s').Replace(":","-") +
".mdf"
        $targetLogFilePath = $server.MasterDBLogPath + "\" + $dbName +  "-Log-" + [DateTime]::Now.ToString('s').Replace(":","-") +
".ldf"

        $restore = new-object ('Microsoft.SqlServer.Management.Smo.Restore'
)
        $restore.Database =
$dbName
        $restore.Devices.AddDevice($backupDataFile, [Microsoft.SqlServer.Management.Smo.DeviceType]::File
)

        $relocateDataFile = new-object ('Microsoft.SqlServer.Management.Smo.RelocateFile')($dbName, $targetDBFilePath
)

        $logFileName = $dbName +
"_Log"
        $relocateLogFile  = new-object ('Microsoft.SqlServer.Management.Smo.RelocateFile')($logFileName, $targetLogFilePath
)

        $restore.RelocateFiles.Add($relocateDataFile
)
        $restore.RelocateFiles.Add($relocateLogFile
)

        $restore.ReplaceDatabase =
$True
        $restore.NoRecovery =
$True
        $restore.SqlRestore($server
)
       
        write-host
"Restore completed successfully"
        write-host "Server:", $server.Name
        write-host
"Database:$dbName"
}

# Create Endpoints for Database mirroring and grant permissions
function CreateDBMirroringEndPoint
{
        Param([string]$servername, [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]$mirroringRole
)
        $server = GetServer($servername
)
        $tcpPort = GetNextAvailableTCPPort
$servername

        $endPointName = "Database_Mirroring_" + [DateTime]::Now.ToString('s').Replace(":","-"
)
        $endpoint  = new-object ('Microsoft.SqlServer.Management.Smo.EndPoint')($server, $endPointName
)
        $endpoint.ProtocolType = [Microsoft.SqlServer.Management.Smo.ProtocolType]::Tcp
        $endpoint.EndpointType = [Microsoft.SqlServer.Management.Smo.EndpointType]::DatabaseMirroring
        $endpoint.Protocol.Tcp.ListenerPort = $tcpPort 
        $endpoint.Payload.DatabaseMirroring.ServerMirroringRole =
$mirroringRole
        $endpoint.Create
()
        $endpoint.Start
()
       
       
# TCP:Server:port
        $fullyQualifiedName = "TCP://" + $server.NetName + ":" + $tcpPort      
        $fullyQualifiedName
;
}

# Get DB Mirroring Endpoint ( if configured already)
# Note: we can have only one DB mirroring end point per sql instance
function GetFullyQualifiedMirroringEndpoint
{
        Param([string]$serverInstance, [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]$mirroringRole
)
        $fullyQualifiedMirroringEndPointName =
""
       
        $EndPointList = GetEndPointList
$serverInstance

        $server = GetServer
$serverInstance
       
        if($EndPointList -eq $null
)
       
{
                $fullyQualifiedMirroringEndPointName = CreateDBMirroringEndPoint $serverInstance
$mirroringRole
       
}
        else
       
{
                foreach($endPoint in $EndPointList
)
                {
                        $fullyQualifiedMirroringEndPointName = "TCP://" + $server.NetName + ":" + $endPoint.Properties["ListenerPort"].Value
                       
break
               
}
       
}
       
        write-host
"Server Name:$serverInstance"
        write-host
"Mirroring Role:$mirroringRole"
        write-host
"EndPointName:$fullyQualifiedMirroringEndPointName"
        $fullyQualifiedMirroringEndPointName
;
}

# Get EndPoint List
function GetEndPointList
{
        Param([string]$servername
)
        $server = GetServer($servername
)

        $PSPath = $server.PSParentPath +
"\EndPoints"

        $EndPointList = @
()

       
        $AllEndPoints = dir
$PSPath
        foreach($endpoint in $AllEndPoints
)
       
{
                $EndPointList += $endpoint.Protocol.Tcp
       
}

        $EndPointList
;
}


# Get Next available port
function GetNextAvailableTCPPort
{
        Param([string]$serverInstance
)
       
        $measure = GetEndPointList $serverInstance | measure-object ListenerPort -max

        if($measure.Maximum -eq $null
)
       
{
                $maxPort =
5000
       
}
       
else
       
{
                $maxPort = $measure.Maximum
       
}

       
#choose a random port that is greater than the current max port
        $maxPort + (new-object random).Next(1,500
)
}


# Get Server object
function GetServer
{
        Param([string]$serverInstance
)

       $array = $serverInstance.Split("\"
)

       if([String]::IsNullOrEmpty($serverInstance
))
      
{
                write-error
"Server instance  name is not valid"
               
return
      
}

       if($array.Length -eq 1
)
      
{
                $machineName = $array[0
]
                $instanceName =
"DEFAULT"
      
}
      
else
      
{
                $machineName = $array[0
]
                $instanceName = $array[1
]
      
}

       $PSPath = "\SQL\" + $machineName + "\" +
$instanceName

       $server = get-item
$PSPath
      
       CheckForErrors
       $server
;
}

# Set Recovery Model for given database
function SetRecoveryModel
{
        Param($serverInstance, $dbName, [Microsoft.SqlServer.Management.Smo.RecoveryModel]$recoveryModel
)
       
        write-host "Setting", $recoveryModel, "Recovery model for database:",
$dbName
        $server = GetServer($serverInstance
)

        $PSPath = $server.PSParentPath + "\Databases\"  +
$dbName

        $db = get-item
$PSPath
        $db.RecoveryModel =
$recoveryModel
        $db.Alter
()
       
        CheckForErrors
}


# Set Partner, Witness
function SetMirroringPartner
{
        Param($serverInstance, $dbName, $fqName, [bool]$isPartner
)
        $server = GetServer($serverInstance
)

        $PSPath = $server.PSParentPath + "\Databases\"  +
$dbName
       
        $db = get-item
$PSPath
       
        if($isPartner -eq $True
)
       
{
                $db.MirroringPartner =
$fqName
       
}
       
else
       
{
                $db.MirroringWitness =
$fqName
       
}
       
        $db.Alter
()
}

# Reports Errors
function CheckForErrors
{
        $errorsReported =
$False
        if($Error.Count -ne 0
)
       
{
                write-host
"******************************"
                write-host "Errors:", $Error.Count
                write-host
"******************************"
                foreach($err in $Error
)
               
{
                        $errorsReported  =
$True
                        if( $err.Exception.InnerException -ne $null
)
                       
{
                                write-host $err.Exception.InnerException.ToString
()
                       
}
                       
else
                       
{
                                write-host $err.Exception.ToString
()
                       
}
                               
                        write-host
"----------------------------------------------"
               
}
               
                throw
       
}
       
}

# Perform initial validation checks to make sure that all input parameters are valid
function PerformValidation
{
        Param($primary , $mirror, $witness, $shareName, $dbName
)
       
#Clear any errors
        $Error.Clear
()
       
        write-host
"Performing Validation checks..."
       
        $primaryServer = GetServer $primary
       
        $PSPath = $primaryServer.PSParentPath + "\Databases\"  +
$dbName
       
        $primaryDatabase = get-item
$PSPath

        write-host
"Checking if Database:$dbName on Primary:$primary is not mirrored..."
        if($primaryDatabase.MirroringStatus -ne [Microsoft.SqlServer.Management.Smo.MirroringStatus]::None
)
       
{
                $errorMessage = "Cannot setup mirroring on database due to its current MirroringState:" + $primaryDatabase.MirroringStatus
                throw
$errorMessage
       
}
       
        if($primaryDatabase.Status -ne [Microsoft.SqlServer.Management.Smo.DatabaseStatus]::Normal
)
       
{
                $errorMessage = "Cannot setup mirroring on database due to its current Status:" + $primaryDatabase.Status
                throw
$errorMessage
       
}
       
        write-host
"Checking if Database:$dbName does not exist on  Mirror:$mirror..."
        $mirrorServer = GetServer $mirror
        $PSPath = $mirrorServer.PSParentPath +
"\Databases\"
       
        $mirrorDatabase= get-childitem $PSPath | where {$_.Name -eq $dbName} 
       
        if($mirrorDatabase -ne $null
)
       
{
                $dbMeasures = $mirrorDatabase | measure-object
                if($dbMeasures.Count -ne 0
)
               
{
                        $errorMessage = "Database:" + $dbName + " already exists on mirror server:" +
$mirror
                        throw
$errorMessage
               
}
       
}
       
        write-host
"Checking if Witness Server exists..."
        $witnessServer = GetServer $witness
       
        write-host
"Checking if File Share:$ShareName exists..."
        if([System.IO.Directory]::Exists($shareName) -ne $True
)
       
{
                $errorMessage = "Share:" + $shareName +
" does not exists"
                throw
$errorMessage
       
}
       
        CheckForErrors
}

# Configure Database mirroring; if input params are not passed into this function,
# those values are read from user entered text from console
function ConfigureDatabaseMirroring
{
        Param([string]$primary = $(Read-Host "Primary SQL Instance(like server\instance)") ,
                [string]$mirror = $(Read-Host "Mirror SQL Instance(like server\instance)") ,
                [string]$witness = $(Read-Host "Witness SQL Instance(like server\instance)") ,
                [string]$shareName = $(Read-Host "Share Path(unc path like \\server\share)") ,
                [string]$dbName = $(Read-Host "Database Name")
               
)
       
       
write-host
        write-host
"============================================================="
        write-host
" 1: Performing Initial checks; validating input parameters"
        write-host
"============================================================="
        PerformValidation $primary $mirror $witness  $shareName $dbName
       
       
write-host
        write-host
"============================================================="
        write-host
" 2: Set Recovery Model as FULL on primary database"
        write-host
"============================================================="
        $fullRecoveryModelType = [Microsoft.SqlServer.Management.Smo.RecoveryModel]::Full
        SetRecoveryModel $primary $dbName
$fullRecoveryModelType

       
write-host
        write-host
"============================================================="
        write-host
" 3: Perform Full Database backup from Primary instance"
        write-host
"============================================================="
        $backupActionType = [Microsoft.SqlServer.Management.Smo.BackupActionType]::Database
        $primaryBackupDataFile = BackupDatabase $primary $dbName $shareName
$backupActionType

       
write-host
        write-host
"============================================================="
        write-host
" 4: Restore Database backup on Mirror"
        write-host
"============================================================="
        RestoreDatabase $mirror $dbName $primaryBackupDataFile

       
write-host
        write-host
"============================================================="
        write-host
" 5: Create endpoints for database mirroring"
        write-host
"============================================================="

        $mirroringRole = [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]::Partner
        $primaryFQName = GetFullyQualifiedMirroringEndpoint $primary
$mirroringRole

        $mirrorFQName = GetFullyQualifiedMirroringEndpoint $mirror
$mirroringRole

        $mirroringRole = [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]::Witness
        $witnessFQName = GetFullyQualifiedMirroringEndpoint $witness
$mirroringRole

       
write-host
        write-host
"============================================================="
        write-host
"  6: Set Primary, Mirror, Witness states in database"
        write-host
"============================================================="
        write-host
"Connecting to Mirror and set Primary as partner ..."
        SetMirroringPartner $mirror $dbName $primaryFQName
$True

        write-host
"Connecting to Primary, set partner as mirror and set witness ..."
        SetMirroringPartner $primary $dbName $mirrorFQName  
$True
        SetMirroringPartner $primary $dbName $witnessFQName  
$False
       
       
write-host
        write-host
"============================================================="
        write-host
"  Database:$dbName mirrored successfully."
        write-host
"============================================================="
}

################################################
# Configure Database mirroring
################################################
ConfigureDatabaseMirroring



ConfigureDBMirroring

# This posting is provided "AS IS" with no warranties, and confers no rights.
# Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

Published Monday, July 07, 2008 3:50 PM by Sethu Srinivasan

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker