Мне нужна помощь, чтобы понять, почему происходит сбой операции 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.