суббота, 12 июля 2014 г.

Windows: Поднимаем из бэкапов базы MSSQL на другой машине

Рассмотрим такую гипотетическую ситуацию (которая не далее как сегодня утром реализовалась на практике, но это неважно).

Есть у нас компьютер WinServA, на котором живёт-поживает и добра наживает Microsoft SQL Server 2005, хранящий все свои базы в каталоге E:\MSSQL\Data. И вот в один не очень прекрасный день этот сервер умирает. Скажем, отказали диски. Ага, сразу все. Возникает задача - поднять базу на другом, девственно чистом сервере WinServB, который до этого спокойно управлялся ОС Windows 2008, ни сном, ни духом не ведал о каких-то SQL Server-ах две тысячи пятого затёртого года и вообще, имеет свободное место только на диске D:.

Для этого нам понадобится: 1) бэкапы дорогих нашему сердцу баз, 2) бэкапы системных баз почившего сервера 3) немного валидола.

Шаг первый - поднимаем Microsoft SQL Server 2005 на Windows 2008.

Тут возможны всяческие чудеса. Например, однажды MSSQL отказывался ставиться до тех пор, пока система не притворилась, что у неё один процессор. Сегодня же нас порадовали другой ошибкой - в процессе установки MSSQL Native Client вываливается сообщение Error 1603, а файлы логов в папке C:\Program Files\Microsoft SQL Server\90\Setup Bootstrap\LOG содержат примерно такое разъяснение:
An error occurred during the installation of assembly 'Microsoft.VC80.CRT,type="win32",version="8.0.50727.42",publicKeyToken="1fc8b3b9a1e18e3b",processorArchitecture="x86"'. Please refer to Help and Support for more information. HRESULT: 0x80070BC9. assembly interface: IAssemblyCacheItem, function: Commit, component: {98CB24AD-52FB-DB5F-A01F-C8B3B9A1E18E}
Решением оказалось в реестре прописать параметр:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control 
Key: RegistrySizeLimit 
Type: REG_DWORD 
Value: 0xffffff (4294967295)
перезагрузиться и прогнать инсталляцию ещё раз.

Дальше интереснее. Для второго шага требуется, чтобы версии старого и нового SQL Server-ов совпадали. Умерший сервер был версии 9.0.5057. Новый, после установки SP4 - 9.0.5000. Очевидно, на старый сервер накатывались какие-то обновления Центром обновлений. Но какие? Тут приходит на помощь вот эта таблица. В частности, в нашем случае помогает установка kb2494120. И можно переходить к следующему шагу.

Шаг второй - восстанавливаем системные базы из бэкапов.

На самом деле хватает трёх бэкапов: master, msdb и model. Но ситуация осложняется тем, что отличаются пути, по которым жили базы на старом сервере и на новом. Помолясь, поступаем так:
a) Находим в списке сервисов сервис MSSQLSERVER и останавливаем его. В свойствах сервиса прописываем параметр командной строки -m и запускаем сервис снова. После этого СУБД стартует в однопользовательском режиме.
b) Заходим в Microsoft SQL Server Management Studio, оно предложит законнектиться к какой-нибудь базе, мы отказываемся. Нажимаем кнопку "New Query" и пишем следующее:
RESTORE DATABASE master FROM DISK='c:\temp\master.bak' WITH REPLACE
Нажимаем конпку "Execute", указываем наконец, к какой базе прицепиться, и ждём.
Сервер сообщит, что база данных восстановлена, и работа будет продолжена после перезапуска сервиса. Фигушки, с восстановленной базой сервис запускаться откажется, указав примерно такую причину в системном журнале Windows: Could not open file E:\MSSQL\Data\mssqlsystemresource.mdf
c) Тут самое время запустить SQL Server из командной строки примерно такой командой:
"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe" -f -T3608
Сервер снова станет доступным, и тогда через Microsoft SQL Server Management Studio удастся сменить пути для всех системных баз на их реальное местоположение в новом сервере:
ALTER DATABASE mssqlsystemresource modify file (name=data,filename='D:\MSSQL\Data\mssqlsystemresource.mdf')
ALTER DATABASE mssqlsystemresource modify file (name=log,filename='D:\MSSQL\Data\mssqlsystemresource.ldf')
ALTER DATABASE msdb modify file (name=MSDBData,filename='D:\MSSQL\Data\msdbdata.mdf')
ALTER DATABASE msdb modify file (name=MSDBLog, filename='D:\MSSQL\Data\msdblog.ldf')
ALTER DATABASE model modify file (name=modeldev,filename='D:\MSSQL\Data\model.mdf')
ALTER DATABASE model modify file (name=modellog, filename='D:\MSSQL\Data\modellog.ldf')
ALTER DATABASE tempdb modify file (name=tempdev,filename='D:\MSSQL\Data\tempdb.mdf')
ALTER DATABASE tempdb modify file (name=templog, filename='D:\MSSQL\Data\templog.ldf')
Кстати, есть способ посмотреть, какие пути каким базам назначены, выполнив команду:
SELECT name, physical_name
FROM sys.master_files
d) После этого можно попробовать вновь запустить штатно сервис MSSQLSERVER и восстановить оставшиеся системные базы:
RESTORE DATABASE msdb FROM DISK='C:\temp\msdb.bak' WITH REPLACE
RESTORE DATABASE model FROM DISK='C:\temp\model.bak' WITH REPLACE

По завершении этой процедуры у нас в руках оказывается живой сервер с восстановленными системными базами.

Шаг третий - восстанавливаем из бэкапов интересующие нас базы.

Это уже делается тривиально, со штатным использованием соответствующих пунктов контекстного меню Microsoft SQL Server Management Studio. Единственное - каждую базу придётся перед восстановлением из бэкапа пересоздать.

Шаг четвертый - пытаемся запустить SQL Server Agent.

Если тот не хочет стартовать с ошибкой Error creating a new session, значит, что-то не слава богу с правами. Нам помогло следующее:
a) на сервере выполнили команды:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Agent XPs', 1;
GO
RECONFIGURE
GO
b) В группу пользователей SQLServer2005SQLAgentUser$ServerName добавили учетную запись, под которой сервис этого самого агента у нас запускается. Не знаем точно, что из этого помогло, но больше SQL Server Agent нам не жаловался.

Шаг пятый - выставляем правильное имя сервера в планах обслуживания.

Если были настроены какие-то планы обслуживания, то в них нужно поменять свойства локальных подключений (Local connection). Сделать это можно либо через редактирование планов в Microsoft SQL Server Management Studio (кнопка Manage connections), либо выполнив вот такой скрипт:
use msdb

-- указываем имя старого сервера
DECLARE @oldservername as varchar(max)
SET @oldservername='WinServA'

-- указываем имя нового сервера
declare @newservername as varchar(max)
set @newservername='WinServB'

declare
    @planid      uniqueidentifier,
    @xml         varchar(max),
    @planname    varchar(max)

-- вытаскиваем все планы, в строке подключения которых значится старый сервер
DECLARE PlansToFix LOCAL STATIC CURSOR FOR
SELECT
    id
FROM sysdtspackages90
WHERE (CAST(CAST(packagedata AS varbinary(MAX)) AS varchar(MAX)) LIKE '%server=''' + @oldservername + '%')

OPEN PlansToFix
FETCH NEXT FROM PlansToFix INTO @planid

WHILE (@@fetch_status != -1)
    BEGIN

    if (@@fetch_status != -2)
        begin

        -- получаем имя плана и его содержимое в виде xml-строки
        select
            @xml = cast(cast(packagedata as varbinary(max)) as varchar(max)),
            @planname = name
        from sysdtspackages90
        where id = @planid

        -- печатаем пользователю, какой план патчим
        print 'Changing ' + @planname + ' server from ' + @oldservername + ' to ' + @newservername

        -- меняем упоминания старого сервера на новый
        set @xml = replace(@xml,'server=''' + @oldservername + '''','server=''' + @newservername +'''')

        -- обновляем план
        UPDATE sysdtspackages90
        SET packagedata = cast(@xml as varbinary(max))
        WHERE id = @planid

        end

    FETCH NEXT FROM PlansToFix INTO @planid  

    END

CLOSE PlansToFix
DEALLOCATE PlansToFix

Вот, собственно, и всё.

Комментариев нет:

Отправить комментарий