DMO(Restore)

  • Hello,

    I created a tool using sqlDMO for hot standby .

    Functions of the tool : Backup & Restore.

    Every day tool will take a full backup and after user defined interval it will take Differential Backup. After every Backup it will restore it in standby server in standby mode .

    Problem :

    1) stand by mode needs a file called undo.dat some time it is not created after Restore operation .

    2) I changed restore operation in with noRecovary mode . it gives error while restoring Differential backup like chain is not complete or not in same chain.

    3) With Recovery also not supporting Differential Backup.

  • []

    Can you post the code?

    ''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    '' Author PADMAKUMAR

    '' Restore DATABASE To standby Server

    ''

    ''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Private WithEvents oRestore As SQLDMO.Restore

    Dim mvarPhysicalLocation As String

    Dim mvarAbort As Boolean

    Dim mvarFile As String

    Dim mvarGroupID As Integer

    Private mvarconnection As ADODB.Connection

    Private mvarDeviceName As String

    Private mvarDeviceType As Byte

    Private mvarDBName As String

    Private mvarsqlserver As New SQLDMO.SqlServer

    Private mvarAutoBackUp As Boolean

    Private mvarAction As Byte

    Private mvarfullBackup As Boolean

    Private mvarTotalAvilableFreeSpace As Long

    Private mvarFileNumber As Long

    Private mvarRestoreAs As String

    Private mvarResotoreDataAs As String

    Private mvarResotoreLogAs As String

    Private mvarLastFullBackUpID As Double

    Private mvarPosition As Integer

    Private mvarFilename As String

    Private mvarUndoFile As String

    Private Const BACKUPTYPE_DEVICE = 0 ''// BackUp through Device

    Private Const BackupType_File = 1 ''// BackUp through File

    Private Const BACKUPTYPE_Tape = 2 ''//BackUp To Tape

    ''// Const For FileList

    Private Const FileList_LogicalName = 1

    Private Const FileList_PhysicalName = 2

    Private Const FileList_Type = 3

    ''// Const For BackupHeader

    Private Const BackupHeader_BackupName = 1

    Private Const BackupHeader_BackupDescription = 2

    Private Const BackupHeader_BackupType = 3

    Private Const BackupHeader_ExpirationDate = 4

    Private Const BackupHeader_Compressed = 5

    Private Const BackupHeader_Position = 6

    Private Const BackupHeader_DeviceType = 7

    Private Const BackupHeader_UserName = 8

    Private Const BackupHeader_ServerName = 9

    Private Const BackupHeader_DatabaseName = 10

    Private Const BackupHeader_DatabaseVersion = 11

    Private Const BackupHeader_DatabaseCreationDatesmalldatetime = 12

    Private Const BackupHeader_BackupSize = 13

    Private Const BackupHeader_FirstLsn = 14

    Private Const BackupHeader_LastLsn = 15

    Private Const BackupHeader_CheckpointLsn = 16

    Private Const BackupHeader_DatabaseBackupLsn = 17

    Private Const BackupHeader_BackupStartDate = 18

    Private Const BackupHeader_BackupFinishDate = 19

    Private Const BackupHeader_SortOrder = 20

    Private Const BackupHeader_CodePage = 21

    Private Const BackupHeader_CompatibilityLevel = 22

    Private Const BackupHeader_SoftwareVendorId = 23

    Private Const BackupHeader_SoftwareVersionMajorinteger = 24

    Private Const BackupHeader_SoftwareVersionMinorinteger = 25

    Private Const BackupHeader_SoftwareVersionBuildinteger = 26

    Private Const BackupHeader_MachineName = 27

    ''// Const for Backup Type

    Private Const BackupSetType_Database = 1

    Private Const BackupSetType_TransactionLog = 2

    Private Const BackupSetType_File = 4

    Private Const BackupSetType_Differential_Database = 5

    Private Const FreeSpace = 1024

    Public Event RestoreEvent(Msg As String, Number As Long)

    Public Event RestoreError(Msg As String, Number As Long)

    Private Sub Class_Initialize()

    Set oRestore = New SQLDMO.Restore

    End Sub

    Public Property Get PhysicalLocation() As String

    PhysicalLocation = mvarPhysicalLocation

    End Property

    Public Property Let PhysicalLocation(ByVal vData As String)

    mvarPhysicalLocation = vData

    End Property

    Private Property Get Abort() As Boolean

    Abort = mvarAbort

    End Property

    Private Property Let Abort(ByVal vData As Boolean)

    mvarAbort = vData

    End Property

    Public Property Get cn() As ADODB.Connection

    cn = mvarconnection

    End Property

    Public Property Set cn(ByVal vData As ADODB.Connection)

    Set mvarconnection = vData

    End Property

    Public Property Get DeviceName() As String

    DeviceName = mvarDeviceName

    End Property

    Public Property Let DeviceName(ByVal vData As String)

    mvarDeviceName = vData

    End Property

    Public Property Get DeviceType() As Byte

    DeviceType = mvarDeviceType

    End Property

    Public Property Let DeviceType(ByVal vData As Byte)

    mvarDeviceType = vData

    End Property

    Public Function GetBackUpSet() As ADODB.Recordset

    Dim Adocm As New ADODB.Command

    On Error GoTo errhand

    ''// Select backupsets of a group

    strsql = "SELECT * FROM MSDB..backupsets WHERE GroupID=? "

    With Adocm

    Set .ActiveConnection = mvarconnection

    .CommandText = strsql

    .Parameters.Append .CreateParameter("GroupID", adInteger, adParamInput, , mvarGroupID)

    .CommandType = adCmdText

    Set GetBackUpSet = .Execute

    End With

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Property Get DbName() As String

    DbName = mvarDBName

    End Property

    Public Property Let DbName(ByVal vData As String)

    mvarDBName = vData

    End Property

    Public Function GetAutoBackUpSet() As ADODB.Recordset

    Dim strsql As String

    Dim Adocn As New ADODB.Command

    On Error GoTo errhand

    With Adocn

    Set .ActiveConnection = mvarconnection

    .CommandText = "SELECT * FROM MSDB..backupsets WHERE AutoBackUp=1"

    .CommandType = adCmdText

    Set GetAutoBackUpSet = .Execute

    End With

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Property Get Action() As Byte

    Action = mvarAction

    End Property

    Public Property Let Action(ByVal vData As Byte)

    mvarAction = vData

    End Property

    Public Property Get FileNumber() As Long

    FileNumber = mvarFileNumber

    End Property

    Public Property Let FileNumber(ByVal vData As Long)

    mvarFileNumber = vData

    End Property

    Public Sub DoRestore()

    Dim RsRestoreset As New ADODB.Recordset

    Dim str As String

    Dim HeaderQResults As QueryResults

    Dim FlistQResults As QueryResults

    Dim strDataFile As String

    Dim strLogFile As String

    Dim IFrom As Integer

    Dim blnIsdbExists As Boolean

    Dim mvarBackupdate As String

    Dim mvarLastFullBackUpID As String

    Dim LastFullBackPosition As Integer

    Dim I As Integer

    On Error GoTo errhand

    ''// Get All Auot Backup Set For restore

    Set RsRestoreset = GetAutoBackUpSet

    If RsRestoreset.RecordCount > 0 Then

    Do Until RsRestoreset.EOF

    With RsRestoreset

    mvarDeviceName = !DeviceName

    mvarDeviceType = !DeviceType

    mvarPhysicalLocation = !PhysicalLocation

    mvarRestoreAs = !RestoreAs

    mvarFilename = RsRestoreset!Filename

    mvarResotoreDataAs = "" & !ResotoreDataAs

    mvarResotoreLogAs = "" & !ResotoreLogAs

    mvarUndoFile = "" & !UndoFile

    End With

    With oRestore

    .Action = SQLDMORestore_Database

    ''// Type of Backup to Restore

    If mvarDeviceType = BACKUPTYPE_DEVICE Then

    .Devices = mvarDeviceName

    ElseIf mvarDeviceType = BackupType_File Then

    .Files = mvarPhysicalLocation & "\" & mvarFilename

    End If

    ''// Database Name to which OR AS you want to

    ''// Restore Backup

    .Database = mvarRestoreAs

    ''// Backup Info

    Set HeaderQResults = GetFileHeader(mvarPhysicalLocation & "\" & mvarFilename)

    Set FlistQResults = GetFileList(mvarPhysicalLocation & "\" & mvarFilename)

    ''// Get Restore Position

    If HeaderQResults.Rows > 0 Then

    LastFullBackPosition = GetRestorePosition(HeaderQResults, _

    mvarPosition)

    Else

    Exit Sub

    End If

    For IFrom = mvarPosition To HeaderQResults.Rows

    .FileNumber = IFrom

    strDataFile = ""

    strLogFile = ""

    GetFileandPath strDataFile, strLogFile

    mvarTotalAvilableFreeSpace = GetFreeDiskspaceInMB(Mid(strDataFile, 1, 2))

    If mvarTotalAvilableFreeSpace > CLng(GetBackupSizeInMB(HeaderQResults, _

    mvarPosition)) Then

    RaiseEvent RestoreEvent("There is not Enough Free Disk space", 0)

    Exit Sub

    End If

    If IsRestoreingOnsameDataBase(HeaderQResults, _

    mvarPosition, mvarRestoreAs) Then

    RaiseEvent RestoreEvent("Cannot Restore to Same Database from Which Backup is Done", 0)

    Exit Sub

    End If

    blnIsdbExists = IsExistsDataBase(mvarRestoreAs)

    If HeaderQResults.GetColumnString(IFrom, _

    BackupHeader_BackupType) = BackupSetType_Database Then

    mvarfullBackup = True

    End If

    If blnIsdbExists = False Or mvarfullBackup Then

    .RelocateFiles = GetRelocateFile(FlistQResults, _

    strDataFile, strLogFile)

    Else

    .RelocateFiles = ""

    End If

    If mvarfullBackup Or blnIsdbExists Then

    .ReplaceDatabase = True

    Else

    .ReplaceDatabase = False

    End If

    .StandbyFiles = mvarUndoFile & "\undo.dat"

    Debug.Print .GenerateSQL

    mvarBackupdate = HeaderQResults.GetColumnString(IFrom, _

    BackupHeader_BackupFinishDate)

    mvarLastFullBackUpID = HeaderQResults.GetColumnString(LastFullBackPosition, _

    BackupHeader_DatabaseBackupLsn)

    If VerifyBackup(oRestore) Then

    .SQLRestore mvarsqlserver

    I = I + 1

    Else

    GoTo GoTONext

    End If

    UpdateRestoreDetails RsRestoreset!BackUpSetID, _

    mvarBackupdate, mvarLastFullBackUpID, IFrom

    GoTONext:

    Next

    End With

    RsRestoreset.MoveNext

    Loop

    End If

    Exit Sub

    errhand:

    If Err.Number = -2147221499 Then

    UpdateRestoreDetails RsRestoreset!BackUpSetID, _

    mvarBackupdate, mvarLastFullBackUpID, mvarPosition

    Else

    MsgBox Err.Description, vbInformation + vbCritical, "Restore"

    End If

    End Sub

    Public Function GetFileList(Filename As String) As QueryResults

    On Error GoTo errhand

    With oRestore

    .Files = Filename

    .FileNumber = 1

    Set GetFileList = .ReadFileList(mvarsqlserver)

    End With

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Function GetFileHeader(Filename As String) As QueryResults

    On Error GoTo errhand

    With oRestore

    .Files = Filename

    .FileNumber = 1

    Set GetFileHeader = .ReadBackupHeader(mvarsqlserver)

    End With

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Private Function GetSqlDataRoot(SqlServer As SQLDMO.SqlServer) As String

    GetSqlDataRoot = SqlServer.Registry.SQLDataRoot

    End Function

    Public Property Get RestoreAs() As String

    RestoreAs = mvarRestoreAs

    End Property

    Public Property Let RestoreAs(ByVal vData As String)

    mvarRestoreAs = vData

    End Property

    Public Property Get ResotoreDataAs() As String

    ResotoreDataAs = mvarResotoreDataAs

    End Property

    Public Property Let ResotoreDataAs(ByVal vData As String)

    mvarResotoreDataAs = vData

    End Property

    Public Property Get ResotoreLogAs() As String

    ResotoreLogAs = mvarResotoreLogAs

    End Property

    Public Property Let ResotoreLogAs(ByVal vData As String)

    mvarResotoreLogAs = vData

    End Property

    Public Function GetFileandPath(DataFile As String, LogFile As String) As String

    On Error GoTo errhand

    If Not IsNull(mvarResotoreDataAs) And Not mvarResotoreDataAs = "" _

    And IsValidPathExists(mvarResotoreDataAs) Then

    DataFile = mvarResotoreDataAs & "\" & mvarRestoreAs & "_Data.MDF"

    Else

    DataFile = GetSqlDataRoot(mvarsqlserver) & "\" & mvarRestoreAs & "_Data.MDF"

    End If

    If Not IsNull(mvarResotoreLogAs) And Not mvarResotoreLogAs = "" _

    And IsValidPathExists(mvarResotoreLogAs) Then

    LogFile = mvarResotoreDataAs & "\" & mvarRestoreAs & "_Log.LDF"

    Else

    LogFile = GetSqlDataRoot(mvarsqlserver) & "\" & mvarRestoreAs & "_Log.LDF"

    End If

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Private Function GetLastrestoreInfo(DeviceName As String) As ADODB.Recordset

    Dim Adocn As New ADODB.Command

    On Error GoTo errhand

    With Adocn

    Set .ActiveConnection = mvarconnection

    .CommandText = "SELECT * FROM MSDB..RestoreDetails WHERE " _

    & " RecID=(Select Max(RecID) FROM MSDB..RestoreDetails RD , " _

    & " MSDB..backupsets BS WHERE RD.BackUpSetID=BS.BackUpSetID" _

    & " AND BS.DeviceName=?)"

    .Parameters.Append .CreateParameter("DeviceName", adVarChar, adParamInput, 40, mvarDeviceName)

    .CommandType = adCmdText

    Set GetLastrestoreInfo = .Execute

    End With

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Private Function IsExistsDataBase(RestoreDbName As String) As Boolean

    Dim Db As Database

    Dim p As Property

    On Error GoTo errhand

    IsExistsDataBase = False

    For Each Db In mvarsqlserver.Databases

    If Db.Name = RestoreDbName Then

    IsExistsDataBase = True

    End If

    Next

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Private Function GetRelocateFile(FileListQuery As QueryResults, DataFile As _

    String, LogFile As String) As String

    On Error GoTo errhand

    Dim strReFile As String

    Dim I As Integer

    Dim oDb As Database

    Dim strLogicalNameofLog As String

    Dim strLogicalNameofData As String

    strReFile = ""

    If IsExistsDataBase(mvarRestoreAs) Then

    strReFile = GetDataFileandLogFromAnExistingDB(mvarRestoreAs, _

    FileListQuery)

    Else

    For I = 1 To FileListQuery.Rows

    If strReFile <> "" Then

    strReFile = strReFile & ","

    End If

    strReFile = strReFile & "[" & FileListQuery.GetColumnString(I, 1) & "],"

    If FileListQuery.GetColumnString(I, 3) = "D" Then

    strReFile = strReFile & "[" & DataFile & "]"

    ElseIf FileListQuery.GetColumnString(I, 3) = "L" Then

    strReFile = strReFile & "[" & LogFile & "]"

    End If

    Next

    End If

    GetRelocateFile = strReFile

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Function GetRestorePosition(HeaderQ As QueryResults, _

    Position As Integer) As Integer

    On Error GoTo errhand

    Dim rs As New ADODB.Recordset

    Dim iRows As Integer

    Dim RPosition As Integer

    Dim RLastFullBackUpID As String

    Dim LastFullBackpos As Integer

    ''// Get Restore info from DataBase

    Set rs = GetLastrestoreInfo(mvarDeviceName)

    ''// Get Last Full Backup set From

    With HeaderQ

    If .Rows > 0 Then

    For iRows = .Rows To 1 Step -1

    If .GetColumnString(iRows, BackupHeader_BackupType) = BackupSetType_Database Then

    LastFullBackpos = iRows

    Exit For

    End If

    Next

    End If

    End With

    If rs.RecordCount > 0 Then

    RPosition = Val(0 & rs!Position)

    RLastFullBackUpID = rs!LastFullBackUpID

    End If

    With HeaderQ

    If CStr(RLastFullBackUpID) = CStr(.GetColumnString(LastFullBackpos, _

    BackupHeader_DatabaseBackupLsn)) Then

    If RPosition >= LastFullBackpos And LastFullBackpos < .Rows _

    And IsExistsDataBase(mvarRestoreAs) Then

    Position = RPosition + 1

    Else

    Position = LastFullBackpos

    End If

    Else

    Position = LastFullBackpos

    End If

    End With

    GetRestorePosition = LastFullBackpos

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Property Get LastFullBackUpID() As Double

    LastFullBackUpID = mvarLastFullBackUpID

    End Property

    Public Property Let LastFullBackUpID(ByVal vData As Double)

    mvarLastFullBackUpID = vData

    End Property

    Public Property Get Position() As Integer

    Position = mvarPosition

    End Property

    Public Property Let Position(ByVal vData As Integer)

    mvarPosition = vData

    End Property

    Private Function GetBackupSizeInMB(HeaderQ As QueryResults, _

    Position As Integer) As Currency

    Dim BackUpsize As Currency

    With HeaderQ

    BackUpsize = CCur(CDbl(.GetColumnString(Position, BackupHeader_BackupSize)))

    GetBackupSizeInMB = BackUpsize * 10000 / 1024 / 1024

    End With

    End Function

    Public Function IsRestoreingOnsameDataBase(HeaderQ As QueryResults, _

    Position As Integer, RestoreAs As String) As Boolean

    Dim strServerNameInBackupSet As String

    Dim strStandByServer As String

    Dim strDbNameInBackupSet As String

    On Error GoTo errhand

    strStandByServer = GetIni("STANDBY", "SERVER", App.Path & "\" & App.EXEName & ".INI")

    With HeaderQ

    strServerNameInBackupSet = .GetColumnString(Position, _

    BackupHeader_ServerName)

    strDbNameInBackupSet = .GetColumnString(Position, _

    BackupHeader_DatabaseName)

    End With

    If strServerNameInBackupSet = strStandByServer And _

    strDbNameInBackupSet = RestoreAs Then

    IsRestoreingOnsameDataBase = True

    End If

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Private Sub UpdateRestoreDetails(BakupSetID As Long, _

    BackUpDate As String, LastFullBackUpID As String, Position As Integer)

    Dim Adocn As New ADODB.Command

    On Error GoTo errhand

    With Adocn

    Set .ActiveConnection = mvarconnection

    .CommandText = "Insert Into MSDB..RestoreDetails (BackUpSetID," _

    & " BackUpDate,LastFullBackUpID,Position,RestoreTime)" _

    & " VALUES(?,?,?,?,GetDate()) "

    .CommandType = adCmdText

    .Parameters.Append .CreateParameter("BackUpSetID", adInteger, adParamInput, , BakupSetID)

    .Parameters.Append .CreateParameter("BackUpDate", adVarChar, adParamInput, 50, BackUpDate)

    .Parameters.Append .CreateParameter("LastFullBackUpID", adVarChar, adParamInput, 50, LastFullBackUpID)

    .Parameters.Append .CreateParameter("Position", adSmallInt, adParamInput, , Position)

    .Execute

    End With

    Exit Sub

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Sub

    Public Function GetDataFileandLogFromAnExistingDB(RestoreDbName As String, _

    FileListQuery As QueryResults) As String

    Dim Db As Database

    Dim p As Property

    Dim strLogicalNameofLog As String

    Dim strLogicalNameofData As String

    On Error GoTo errhand

    For I = 1 To FileListQuery.Rows

    If FileListQuery.GetColumnString(I, 3) = "D" Then

    strLogicalNameofData = FileListQuery.GetColumnString(I, 1)

    ElseIf FileListQuery.GetColumnString(I, 3) = "L" Then

    strLogicalNameofLog = FileListQuery.GetColumnString(I, 1)

    End If

    Next

    For Each Db In mvarsqlserver.Databases

    If Db.Name = RestoreDbName Then

    strReFile = "[" & strLogicalNameofData & "],"

    strReFile = strReFile & "[" & Trim(Db.FileGroups("PRIMARY").DBFiles(1).PhysicalName) & "]"

    For I = 1 To Db.TransactionLog.LogFiles.Count

    If strReFile <> "" Then

    strReFile = strReFile & ","

    End If

    strReFile = strReFile & "[" & strLogicalNameofLog & "],"

    strReFile = strReFile & Trim("[" & Db.TransactionLog.LogFiles(I).PhysicalName) & "]"

    Next

    End If

    Next

    GetDataFileandLogFromAnExistingDB = strReFile

    Exit Function

    errhand:

    RaiseEvent RestoreError(Err.Description, Err.Number)

    End Function

    Public Property Get Filename() As String

    Filename = mvarFilename

    End Property

    Public Property Let Filename(ByVal vData As String)

    mvarFilename = vData

    End Property

    Private Function VerifyBackup(ObjRestore As SQLDMO.Restore) As Boolean

    On Error GoTo errhand

    VerifyBackup = False

    With ObjRestore

    .SQLVerify mvarsqlserver

    End With

    VerifyBackup = True

    Exit Function

    errhand:

    Resume 0

    End Function

    Private Sub oRestore_Complete(ByVal Message As String)

    RaiseEvent RestoreEvent(Message, 0)

    End Sub

    Private Sub oRestore_NextMedia(ByVal Message As String)

    RaiseEvent RestoreEvent(Message, 0)

    End Sub

    Private Sub oRestore_PercentComplete(ByVal Message As String, ByVal Percent As Long)

    RaiseEvent RestoreEvent(Message, Percent)

    End Sub

    Public Sub FillReadOnlyDB(cmb As ComboBox)

    Dim Db As Database

    For Each Db In mvarsqlserver.Databases

    If Db.Properties("ReadOnly") = True Then

    End If

    Next

    End Sub

Viewing 3 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic. Login to reply