Ошибка восстановления базы данных: HRESULT m_hr = 0x80040e14 - PullRequest
0 голосов
/ 06 июня 2019

Мне нужна помощь, чтобы понять, почему происходит сбой операции RESTORE DATABASE с SQL Server 2008 Express с кодом HRESULT 0x80040e14.

Обзор рабочей среды

Мыиметь приложение Point of Sale, работающее на нескольких сотрудничающих терминалах, архитектура которых состоит в том, чтобы иметь главный терминал со всеми оперативными данными и ноль или более спутниковых терминалов, которые обновляют оперативные данные по мере обработки транзакций.

Существуетальтернативная архитектура, в которой резервный главный терминал является частью группы терминалов.Существует команда для синхронизации рабочих данных главного терминала и резервного главного терминала в рамках настройки группы или выполнения замены главного терминала резервного копирования.

Большая часть данных операционных итогов хранится в набореплоских файлов на диске, однако мы используем Microsoft SQL Server Express для хранения итогов PLU.

В рамках операции синхронизации мы также передаем резервную копию базы данных SQL Server.Операция RESTORE DATABASE завершается неудачно, и мне нужна помощь, чтобы выяснить проблему.

Приложение написано на C ++ и использует ADO для интерфейса SQL Server.

Тестовая установка используетMicrosoft SQL Server Express 2008 R2, который был установлен с использованием экземпляра по умолчанию, чтобы быть совместимым с первоначальной установкой SQL Server 2000 Express несколько лет назад.Приложение POS указывает Экземпляр по умолчанию в строке подключения.

Исходный код функциональности Используется

Функция восстановления выглядит следующим образом:

ULONG   CnPluTotalDb::RestoreDB(LPCTSTR szSQlCode){

    CString szSQL;
    USHORT usError = 0;
    USHORT usErrorCount = 0;

    CString activeConn;
    activeConn.Format(ConnectionStringTemp,L"master");
    _bstr_t strConnect = activeConn;

    //We set the database to be in single user mode while we do this database reset
    //so that no one else can access the database information while we reset the DB
    //SR 725 JHHJ
SINGLE_USER_DB:
    szSQL.Format(L"ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE", szSQlCode);
    m_hr = __pRecO->OpenRec(CnVariant(szSQL), strConnect, adOpenForwardOnly,adLockOptimistic,adCmdText);

    //Close the recordset object so we can open a new one 
    //for the next SQL command
    __pRecO->Close();

    if (FAILED(m_hr))
    {
        char  xBuff[128];
        sprintf(xBuff, "CnPluTotalDb::RestoreDB() SET SINGLE_USER FAILED: HRESULT m_hr = 0x%8.8x", m_hr);
        NHPOS_ASSERT_TEXT(0, xBuff);
        usError = 1;
        goto MULTI_USER_DB;
    }

    //We will drop the database because the information in it is out of date
    //so that we can restore it in the next call.
    szSQL.Format(L"DROP DATABASE %s", szSQlCode);
    m_hr = __pRecO->OpenRec(CnVariant(szSQL), strConnect, adOpenForwardOnly,adLockOptimistic,adCmdText);
    __pRecO->Close();

    if (FAILED(m_hr))
    {
        char  xBuff[128];
        sprintf(xBuff, "CnPluTotalDb::RestoreDB() DROP DATABASE FAILED: HRESULT m_hr = 0x%8.8x", m_hr);
        NHPOS_ASSERT_TEXT(0, xBuff);
    }


    //Restore the database from the file that the master/backupmaster has just sent over.
    szSQL.Format(PLUTOTAL_DB_BACKUP_RESTORE, szSQlCode, szSQlCode);
    m_hr = __pRecO->OpenRec(CnVariant(szSQL), strConnect, adOpenForwardOnly,adLockOptimistic,adCmdText);
    __pRecO->Close();

    if (FAILED(m_hr))
    {
        char  xBuff[128];
        sprintf(xBuff, "CnPluTotalDb::RestoreDB() RESTORE DATABASE FAILED: HRESULT m_hr = 0x%8.8x", m_hr);
        NHPOS_ASSERT_TEXT(0, xBuff);
    }

MULTI_USER_DB:
    //Return the database back to multi-user mode. 
    szSQL.Format(L"ALTER DATABASE %s SET MULTI_USER", szSQlCode);
    m_hr = __pRecO->OpenRec(CnVariant(szSQL), strConnect, adOpenForwardOnly,adLockOptimistic,adCmdText);

    __pRecO->Close();   // one shot!!!

    if (FAILED(m_hr))
    {
        char  xBuff[128];
        sprintf(xBuff, "CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x%8.8x", m_hr);
        NHPOS_ASSERT_TEXT(0, xBuff);
        usErrorCount++;
        if (usErrorCount < 5) goto MULTI_USER_DB;
        return PLUTOTAL_E_FAILURE;
    } else if (usError)
    {
        usError = 0;
        goto SINGLE_USER_DB;
    }

    return PLUTOTAL_SUCCESS;
}

Используемый шаблон строки подключения:

ConnectionStringTemp = L"Provider=MSDASQL;DRIVER={SQL Server};SERVER=lpc:(local);DATABASE=%s;UID=; Password=;";

Определения, используемые для параметров:

#define PLUTOTAL_DB_BACKUP_PATH     L"C:\\TempDisk\\NCR\\Saratoga\\Database\\"    // was _T("C:\\Program Files\\Microsoft SQL Server\\MSSQL\\Data\\")
#define PLUTOTAL_DB_BACKUP_RESTORE  L"RESTORE DATABASE %s FROM DISK = 'C:\\TempDisk\\NCR\\Saratoga\\Database\\%s_BAK.dat' WITH REPLACE"
#define PLUTOTAL_DB_BACKUP_BACKUP   L"BACKUP DATABASE %s TO DISK = 'C:\\TempDisk\\NCR\\Saratoga\\Database\\%s_BAK.dat' WITH INIT"

Наблюдаемое поведение и сгенерированные журналы

Я вижу, что операция BACKUP DATABASE на главном терминале создает файл резервной копии, и этот файл передается на главный терминал резервного копирования.

Также похоже, что мастер резервного копирования переходит в однопользовательский режим иDROP DATABASE работает.

Сгенерированы журналы, показывающие ошибки:

PluTtlDb.cpp,   440, CnPluTotalDb::RestoreDB() RESTORE DATABASE FAILED: HRESULT m_hr = 0x80040e14                                            
 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 TtlPluBk.c,   190, **WARNING:  TTL_BKUPPLUDBFAIL  PluTotalRestoreDB() returned ulSts 9999 0x270f                                           

Редактировать A: После добавления дополнительных журналов в методе OpenRec() Чтобы получить более подробную информацию об ошибке, которая оказывается довольно общей целью HRESULT, у меня есть следующая новая информация.Эти журналы содержат несколько повторяющихся текстов, поскольку описание ошибки превышает ограничение в журнале ошибок, составляющее 110 символов, поэтому большинство описаний ошибок регистрируются с помощью двух вызовов API журнала для регистрации первой половины, а затем второй половины описания ошибки.

 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]The media family on device 'C:\TempDisk\NCR\Saratoga\Database\PluTtlDC_BA
 , rce\nhpos\plutotal\CnAdoXP.h,   349, sk\NCR\Saratoga\Database\PluTtlDC_BAK.dat' is incorrectly formed. SQL Server cannot process this media family.          
 ,                 PluTtlDb.cpp,   440, CnPluTotalDb::RestoreDB() RESTORE DATABASE FAILED: HRESULT m_hr = 0x80040e14                                            
 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]User does not have permission to alter database 'PluTtlDC', the database 
 , rce\nhpos\plutotal\CnAdoXP.h,   349, database 'PluTtlDC', the database does not exist, or the database is not in a state that allows access checks.          
 ,                 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]User does not have permission to alter database 'PluTtlDC', the database 
 , rce\nhpos\plutotal\CnAdoXP.h,   349, database 'PluTtlDC', the database does not exist, or the database is not in a state that allows access checks.          
 ,                 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]User does not have permission to alter database 'PluTtlDC', the database 
 , rce\nhpos\plutotal\CnAdoXP.h,   349, database 'PluTtlDC', the database does not exist, or the database is not in a state that allows access checks.          
 ,                 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]User does not have permission to alter database 'PluTtlDC', the database 
 , rce\nhpos\plutotal\CnAdoXP.h,   349, database 'PluTtlDC', the database does not exist, or the database is not in a state that allows access checks.          
 ,                 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 , rce\nhpos\plutotal\CnAdoXP.h,   342, IDispatch error #3092                                                                                                   
 , rce\nhpos\plutotal\CnAdoXP.h,   345, [Microsoft][ODBC SQL Server Driver][SQL Server]User does not have permission to alter database 'PluTtlDC', the database 
 , rce\nhpos\plutotal\CnAdoXP.h,   349, database 'PluTtlDC', the database does not exist, or the database is not in a state that allows access checks.          
 ,                 PluTtlDb.cpp,   454, CnPluTotalDb::RestoreDB() SET MULTI_USER FAILED: HRESULT m_hr = 0x80040e14                                              
 ,                   TtlPluBk.c,   190, **WARNING:  TTL_BKUPPLUDBFAIL  PluTotalRestoreDB() returned ulSts 9999 0x270f                                           

Дополнительный исходный код

Метод OpenRec() выглядит следующим образом:

virtual HRESULT OpenRec(CnVariant Source,_bstr_t ActiveConnection,
        CursorTypeEnum CursorType = adOpenKeyset,
        LockTypeEnum LockType = adLockOptimistic,
        long Options = adCmdUnknown)
{
    CString  errorMessage;
    try {
        if (m_pConnection->State != adStateOpen)
        {
            m_pConnection->ConnectionString = ActiveConnection;
            m_pConnection->Open("", "", "", -1);
        }
        m_hr = m_pRecordSet->Open((VARIANT)Source, _variant_t((IDispatch *)m_pConnection),CursorType,LockType,Options);
    }
    catch( _com_error &e) {
        _bstr_t bstrSource(e.Description());
        TCHAR *description;
        description = bstrSource;
        errorMessage.Format(_T("ERROR OpenRec %s  %s"), e.ErrorMessage(), description);
        m_hr = e.Error();
    }           
    if (!FAILED(m_hr)) {
        m_bOpened = TRUE;
    }
    else {
        TRACE3("%S(%d): %s\n", __FILE__, __LINE__, errorMessage);
    }
    return  m_hr;
}

, где m_pRecordSet имеет тип _RecordsetPtr, предоставленный ADO.

...