=====Version 2=====
The below script should be executed with cscript on the source server. \\
It takes care of setting up database mirroring for one or all databases on a sourceserver. \\
Modify the directory and server variables before executing. \\
The account running this script has to have the correct perissions on both servers. \\
To mirror all databases:
cscript SQLMirroring.vbs
To mirror just a single database (can be used multiple times to mirror only some databases):
cscript SQLMirroring.vbs databasename
'SQLMirroring.vbs
'For configuring mirroring of databases between strSourceServer and strTargetServer.
'This script needs to be run on strSourceServer.
'20091121, v1.
'20111105, v2.
' Modified to be able to pass a databasename as an argument to the script
' to only mirror that database.
' Change compressing backups to only use zip (not 7z).
'TODO:
'Add check for psexec.exe accept-license-on-first-run.
'Add check for SQL and share connectivity between both systems.
Const bOverWrite = True
Const intForReading = 1
Const HideWindow = 0
Const WaitOnReturn = True
Const str7zipExe = "D:\Tools\7-zip\7za.exe"
'*****
'DON'T FORGET TO RUN PSEXEC ONCE MANUALLY TO ACCEPT THE LICENSE!
'*****
Const strPsExecExe = "D:\Tools\psexec.exe"
strBackupDir = "D:\MirBackup\"
strTargetBackupDir = "D:\Backup\"
strTargetDataDir = "E:\Data\"
strTargetLogDir = "E:\Logs\"
strSourceServer = "sourceserver.domain.com"
strSourceBackupDirUNC = "\\" & strSourceServer & "\D$\Backup"
strTargetServer = "targetserver.domain.com"
strTargetBackupDirUNC = "\\" & strTargetServer & "\D$\Backup"
strEndpointName = "Endpoint_Mirroring"
strMirrorPort = "5022"
Set objParam = Wscript.Arguments
If objParam.Count = 0 Then
strDatabaseName = ""
Else
strDatabaseName = objParam(0)
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
strConnSrc = "Provider=SQLOLEDB; Data Source=" & strSourceServer & "; Initial Catalog=master; Trusted_Connection=yes; Network Library=dbmssocn;"
strConnTarget = "Provider=SQLOLEDB; Data Source=" & strTargetServer & "; Initial Catalog=master; Trusted_Connection=yes; Network Library=dbmssocn;"
Set objRS = CreateObject("ADODB.RecordSet")
Set objRS2 = CreateObject("ADODB.RecordSet")
Set objMirRS = CreateObject("ADODB.RecordSet")
Set objConn = WScript.CreateObject("ADODB.Connection")
objConn.CommandTimeout=3600
objConn.Open strConnSrc
'If no databasename was passed as an argument to this script, select all databases except master, model, msdb and tempdb.
If strDatabaseName = "" Then
strSQL = "SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')"
'If a databasename was passed as a scriptargument, select info about this database only.
Else
strSQL = "SELECT name FROM sys.databases WHERE name = '" & strDatabaseName & "'"
End If
objRS.Open strSQL, strConnSrc
Do Until objRS.EOF
'SELECT name,physical_name FROM dbname.sys.database_files
strSQL = "SELECT name,physical_name FROM [" & objRS("name").Value & "].sys.database_files"
objRS2.Open strSQL, strConnSrc
Set tsDBFileGrpLog = objFso.CreateTextFile(strBackupDir & objRS("name").Value & ".txt", bOverwrite)
Do Until objRS2.EOF
tsDBFileGrpLog.WriteLine(objRS2("name").Value & chr(9) & objRS2("physical_name").Value)
objRS2.MoveNext
Loop
objRS2.Close
tsDBFileGrpLog.Close
strSQL = "SELECT recovery_model_desc FROM sys.databases WHERE name = '" & objRS("name").Value & "'"
objRS2.Open strSQL, strConnSrc
bIsNotFull = False
Do Until objRS2.EOF
If Not LCase(objRS2("recovery_model_desc").Value) = "full" Then
bIsNotFull = True
End If
objRS2.MoveNext
Loop
objRS2.Close
If bIsNotFull = False Then
'BACKUP DATABASE dbname TO DISK = N'X:\Dir\dbname.bak' WITH INIT, NAME = N'dbname-Full Database Backup'
strSQL = "BACKUP DATABASE [" & objRS("name").Value & "] TO DISK = N'" & strBackupDir & objRS("name").Value & ".bak' WITH INIT, NAME = N'" & objRS("name").Value & "-Full Database Backup'"
WScript.Echo Now() & " - Backup database " & objRS("name").Value
objConn.Execute(strSQL)
'BACKUP LOG dbname TO DISK = N'X:\Dir\dbname.bak' WITH NOINIT, NAME = N'dbname-Transaction Log Backup'
strSQL = "BACKUP LOG [" & objRS("name").Value & "] TO DISK = N'" & strBackupDir & objRS("name").Value & ".bak' WITH NOINIT, NAME = N'" & objRS("name").Value & "-Transaction Log Backup'"
WScript.Echo Now() & " - Backup log of " & objRS("name").Value
objConn.Execute(strSQL)
'ALTER DATABASE dbname SET OFFLINE
strSQL = "ALTER DATABASE [" & objRS("name").Value & "] SET OFFLINE"
WScript.Echo Now() & " - Set database " & objRS("name").Value & " offline."
objConn.Execute(strSQL)
Else
WScript.Echo Now() & " - Skipping database " & objRS("name").Value & " because it is not in Full Recovery mode."
End If
objRS.MoveNext
Loop
objRS.Close
objConn.Close
Set ToZipFolder = objFso.GetFolder(strBackupDir)
For Each file In ToZipFolder.Files
'Continue if strDatabaseName is not defined, or if it is defined and the current .bak-file matches strDatabaseName.
If (strDatabaseName = "" And objFso.GetExtensionName(file) = "bak") Or (strDatabaseName <> "" And strDatabaseName & ".bak" = file.Name) Then
WScript.Echo Now() & " - Compressing: " & file.Name
'Compress to .zip with fastest compression.
objShell.Run chr(34) & str7zipEXE & chr(34) & " a -tzip " & chr(34) & strBackupDir & Left(file.Name, Len(file.Name) - 4) & ".zip" & chr(34) & " " & chr(34) & strBackupDir & file.Name & chr(34) & " -mx=1", HideWindow, WaitOnReturn
End If
Next
Set ToZipFoler = Nothing
'Create the mirroring Encpoint on the sourceserver.
CreateEndpoint strSourceServer, strEndpointName, strConnSrc
'Create the mirroring Endpoint on the targetserver.
CreateEndpoint strTargetServer, strEndpointName, strConnTarget
Set BackupFolder = objFso.GetFolder(strBackupDir)
For Each file In BackupFolder.Files
'Continue if strDatabaseName is not defined, or if it is defined and the current .zip-file matches strDatabaseName.
If (strDatabaseName = "" And objFso.GetExtensionName(file) = "zip") Or (strDatabaseName <> "" And strDatabaseName & ".zip" = file.Name) Then
WScript.Echo Now() & " - Copying: " & file.Name
objFso.CopyFile strBackupDir & file.Name, strTargetBackupDirUNC & "\", bOverWrite
'If the file is equal in size on both sides, unpack it on the targetserver.
If objFso.FileExists(strTargetBackupDirUNC & "\" & file.Name) And objFso.FileExists(strBackupDir & "\" & file.Name) Then
Set objLocalFile = objFso.GetFile(strBackupDir & "\" & file.Name)
Set objTargetFile = objFso.GetFile(strTargetBackupDirUNC & "\" & file.Name)
If objLocalFile.Size = objTargetFile.Size Then
WScript.Echo Now() & " - Unpacking: " & file.Name & " on " & strTargetServer
objShell.Run chr(34) & strPsExecExe & chr(34) & " \\" & strTargetServer & " " & chr(34) & str7ZipExe & chr(34) & " e " & chr(34) & strTargetBackupDir & file.Name & chr(34) & " -o" & chr(34) & strTargetBackupDir & chr(34) & " -y", HideWindow, WaitOnReturn
Else
WScript.Echo Now() & " - " & "File mismatch for " & file.Name & "! Please check the file."
End If
Set objTargetFile = Nothing
Set objLocalFile = Nothing
End If
End If
Next
For Each file in BackupFolder.Files
'Continue if strDatabaseName is not defined, or if it is defined and the current .txt-file matches strDatabaseName.
If strDatabaseName = "" Or (strDatabaseName <> "" And strDatabaseName & ".txt" = file.Name) Then
'Continue if there is a textfile in the backupdir and an extracted .bak-file in the backupdir of the targetserver.
If objFso.GetExtensionName(file) = "txt" AND objFso.FileExists(strBackupDir & file.Name) And objFso.FileExists(strTargetBackupDirUNC & "\" & Left(file.Name, Len(file.Name) - 4) & ".bak") Then
Set tsReadDBFileGrpLog = objFso.OpenTextFile(strBackupDir & "\" & Left(file.Name, Len(file.Name) - 4) & ".txt", intForReading)
arrName = Array("empty")
arrPhysName = Array("empty")
c = 0
d = 0
Do Until tsReadDBFileGrpLog.AtEndOfStream
strLine = tsReadDBFileGrpLog.ReadLine
arrLine = Split(strLine, chr(9))
ReDim Preserve arrName(c)
arrName(c) = arrLine(0)
c = c + 1
ReDim Preserve arrPhysName(d)
arrPhysName(d) = Right(arrLine(1), Len(arrLine(1)) - InstrRev(arrLine(1), "\"))
d = d + 1
Loop
strMove = ""
For i = 0 To UBound(arrName)
If InStr(LCase(arrName(i)), "log") > 0 Or InStr(LCase(arrPhysName(i)), ".ldf") Then
strMove = strMove & ", Move N'" & arrName(i) & "' TO N'" & strTargetLogDir & arrPhysName(i) & "'"
Else
strMove = strMove & ", MOVE N'" & arrName(i) & "' TO N'" & strTargetDataDir & arrPhysName(i) & "'"
End If
Next
strDBName = Left(file.Name, Len(file.Name) - 4)
objConn.Open strConnTarget
strSQL = "RESTORE DATABASE [" & strDBName & "] FROM DISK = N'" & strTargetBackupDir & strDBName & ".bak' WITH FILE = 1" & strMove & ", NORECOVERY"
WScript.Echo Now() & " - Restore database " & strDBName
objConn.Execute(strSQL)
strSQL = "RESTORE LOG [" & strDBName & "] FROM DISK = N'" & strTargetBackupDir & strDBName & ".bak' WITH FILE = 2, NORECOVERY"
WScript.Echo Now() & " - Restore log for " & strDBName
objConn.Execute(strSQL)
strSQL = "ALTER DATABASE [" & strDBName & "] SET PARTNER = 'TCP://" & strSourceServer & ":" & strMirrorPort & "'"
WScript.Echo Now() & " - Set partner on mirror for " & strDBName
objConn.Execute(strSQL)
objConn.Close
objConn.Open strConnSrc
strSQL = "ALTER DATABASE [" & strDBName & "] SET ONLINE"
WScript.Echo Now() & " - Set database " & strDBName & " online on principal"
objConn.Execute(strSQL)
strSQL = "ALTER DATABASE [" & strDBName & "] SET PARTNER = 'TCP://" & strTargetServer & ":" & strMirrorPort & "'"
WScript.Echo Now() & " - Set partner on primary for " & strDBName
objConn.Execute(strSQL)
objConn.Close
End If
End If
Next
Function CreateEndpoint(strServer,strEndpointName, strConn)
strSQL = "SELECT name FROM sys.database_mirroring_endpoints"
objMirRS.Open strSQL, strConn
bEndpointExists = False
Do Until objMirRS.EOF
If objMirRS("name").Value = strEndpointName Then
WScript.Echo Now() & " - Found endpoint name: " & objMirRS("name").Value & " on " & strServer
bEndpointExists = True
Exit Do
End If
Loop
If bEndpointExists = False Then
objConn.Open strConn
strSQL = "CREATE ENDPOINT " & strEndpointName & " STATE=STARTED AS TCP (LISTENER_PORT=" & strMirrorPort & ") FOR DATABASE_MIRRORING (ROLE=ALL)"
WScript.Echo Now() & " - Create endpoint " & strEndpointName & " on " & strServer
objConn.Execute(strSQL)
objConn.Close
End If
objMirRS.Close
End Function
'Cleanup
Set objConn = Nothing
Set objMirRS = Nothing
Set objRS2 = Nothing
Set objRS = Nothing
Set objShell = Nothing
Set objFso = Nothing