Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Добрый день.

От прошлого админа остался скрипт которым обновляли тестовые базы 1С. Я проверил, что он работает и в него особо не вглядывался. Но на базу erp понадобилось добавить второй файл лога и скрипт работать перестал. Я решил в нем поправить эту часть, чтобы опять заработало, но изучив скрипт не понял, почему он вообще работал...

Текст запроса:
+
DECLARE @sql nvarchar(4000)
DECLARE @db nvarchar(100)
DECLARE @full nvarchar(250)
DECLARE @diff nvarchar(250)
DECLARE @erphrm nvarchar(10)

SET @db = 'ERP_rasrab'
SET @full = 'erp_20122018.bak'
SET @diff = ''

SELECT @erphrm = SUBSTRING(@full,1,3)
USE [master]
SET @sql = 'USE [master]; ALTER DATABASE ' + @db + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'
EXEC sp_executesql @sql
---Полный
SET @sql = 'RESTORE DATABASE ' + @db + ' FROM DISK = N''E:\SQL1\' + @full + '.bak'' WITH FILE = 1, NOUNLOAD, NORECOVERY,  REPLACE,  STATS = 5'
EXEC sp_executesql @sql
--Дифф
IF @diff<>''
	BEGIN
		SET @sql = 'RESTORE DATABASE ' + @db + ' FROM DISK = N''E:\SQL1\' + @diff + '.bak'' WITH FILE = 1, NOUNLOAD, NORECOVERY, STATS = 5'
		EXEC sp_executesql @sql;
	END

SET @sql = 'RESTORE DATABASE ' + @db + ' WITH RECOVERY'
EXEC sp_executesql @sql

SET @sql = 'ALTER DATABASE ' + @db + ' SET MULTI_USER'
EXEC sp_executesql @sql


Указывать нужно БД куда восстанавливаем, фулл бекап и ели есть - дифф.
Пути на проде и тесте разные, имена файлов тоже. Но скрипт восстанавливал с перемещением и переименованием под БД.mdf и БД.ldf

Сейчас переписал с явным move в тексте под эту базу и работает нормально, но интересует за счет чего работал вариант прошлого админа.

Пока тестировал выяснил: не работает, если базы нет.
Работает не с любым названием, а в основном с erp_фамилия разраб, причем erp_случайная фамилия не сработало.
Триггеров на сервере нет, в базе мастер тоже ничего.
При восстановлении базы с дополнительным логов проблема возникла только с ним, на mdf и первый лог move похоже работал.
Вообще выглядит как будто есть объект в котором есть имя базы и пути файлов для перемещения и при ресторе через скрипт автоматом мувит.
у кого какие идеи насчёт возможной реализации, интересно как такое реализовано.
20 дек 18, 16:36    [21769821]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
а какие проблемы вы нашли в скрипте?
вот такое генерится:

USE [master]; ALTER DATABASE ERP_rasrab SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE ERP_rasrab FROM DISK = N'E:\SQL1\erp_20122018.bak.bak' WITH FILE = 1, NOUNLOAD, NORECOVERY,  REPLACE,  STATS = 5
RESTORE DATABASE ERP_rasrab WITH RECOVERY
ALTER DATABASE ERP_rasrab SET MULTI_USER


т.е. делается WITH REPLACE уже существующей базе,
все пути к вашей базе берутся из метаданных самой базы, а не бэкапа.

я на свой ноут (с единственным диском С) так таскаю базы,
хотя на сервере, откуда беру, файлы разнесены по дискам О и Р
20 дек 18, 17:09    [21769866]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
хотя да,
если например имеем 2 сервера на одном компе,
на обоих база существует,
пути к базам разные,
то попытка восстановить с одного на другой,
указав лишь with replace,
закончится плачевно, ибо попытается восстановить поверх файлов базы-исходника.

т.е. какая-то неконсистентность все же есть:
сперва он пытается восстановить по путям, взятым из бэкапа,
и только если таких нет, восстанавливает по путям текущей базы
20 дек 18, 17:16    [21769876]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Yasha123,

Через принт проверил, что да - скрипт восстановления похож на Ваш вариант.

Разве при восстановлении по умолчанию берутся данные существующей базы, а не те, что были у базы, чей бекап?
Я привык при восстановлении всегда точно указывать куда. Ну если только не эту же базы из бекапа поднимаю.
Может и туплю с этим вариантом.

Сейчас ещё раз попробовал, создал БД test123 и попробовал туда восстановить фулл бекап базы hrm (mdf+log).
Ошибки:

Msg 5133, Level 16, State 1, Line 1
Directory lookup for the file "D:\SQL\hrm.mdf" failed with the operating system error 2(The system cannot find the file specified.).
Msg 3156, Level 16, State 3, Line 1
File 'hrm' cannot be restored to 'D:\SQL\hrm.mdf'. Use WITH MOVE to identify a valid location for the file.
Msg 5133, Level 16, State 1, Line 1
Directory lookup for the file "D:\SQL\hrm_log.ldf" failed with the operating system error 2(The system cannot find the file specified.).
Msg 3156, Level 16, State 3, Line 1
File 'hrm_log' cannot be restored to 'D:\SQL\hrm_log.ldf'. Use WITH MOVE to identify a valid location for the file.
Msg 3119, Level 16, State 1, Line 1
Problems were identified while planning for the RESTORE statement. Previous messages provide details.
Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.

Путь D:\SQL на сервере откуда бекап. Выглядит, что по умолчанию пытается восстановиться в директорию базы откуда бекап. На тесте дефолтные пути сервера E:\DATA\ и E:\LOG\

Пункт, что не может создать снимается, это падает на этапе USE [master]; ALTER DATABASE ' + @db + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE
20 дек 18, 17:24    [21769886]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Просто так базы разработчиков перезаписать нельзя и придется ждать обращения от них.
Можно будет на hrm базе проверить работает ли ещё скрипт (у erp 2 лога и не работает), если да (а по идее ничего не менялось), то вытянуть текст запроса во время восстановления. Будет ли там конструкция с move или просто RESTORE DATABASE который получаю через принт без запуска.
20 дек 18, 17:36    [21769906]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
вот мой сервер, с единственным диском С,
и вот их бэкапчик, с их путями, которых у меня нет.
восстанавливаю в существующую базу.
на картинке успешное восстановление и диски,
к-ые видит мой сервер(всего 1 диск и видит)

К сообщению приложен файл. Размер - 48Kb
20 дек 18, 17:45    [21769920]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
в вашем эксперименте другое имя базы,
куда восстанавливаете.
20 дек 18, 17:54    [21769936]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Yasha123,

Интересно, а куда кстати восстанавливается без указания, если дефолтные пути и пути восстанавливаемой базы разные?

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

Выходит похоже на то, что у restore database свой алгоритм и иногда восстанавливает где была база (или пути в параметрах сервера), а иногда начинает в пути из бекапа.

Тогда возможно в моём случае именно после восстановления в базу с 1 лог файлом начало восстанавливать по путям бекапа и какой-то схемы с скрытыми триггерами, как подумал сначала нет. Будет задача на обновление базы, проверю точно.
А пока можно перечитать, что Microsoft пишет по этому поводу.
20 дек 18, 17:57    [21769940]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Yasha123
в вашем эксперименте другое имя базы,
куда восстанавливаете.


Ну там всегда и было другое имя. Продуктивная база в БД_фамилияРазраба.
20 дек 18, 17:58    [21769941]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
кстати, это без разницы.
и с другим именем перезапишется.
я просто сравниваю со своей ситуацией,
(у меня имя базы то же самое)

все это документировано:
RESTORE Statements (Transact-SQL)

К сообщению приложен файл. Размер - 60Kb
20 дек 18, 18:07    [21769957]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Yasha123,

Проветрился и появились идеи, но проверять буду уже завтра.
Понятно, что реплейс позволяет перезаписать базу оставив от неё только название.

В моих попытках и ошибках была закономерность: пыталось восстановить по пути из бекапа файлы с отличными от бекапа логическими именами. В попытке, где выдало ошибку только по логу 2, у mdf и первого лога были логические имена с продуктива, а когда создал руками - было вида erp_разраб.

Случаем не идёт сравнение логического имени файла перезаписываемой базы с бекапом, если совпало, то путь перезаписываемой, если нет, то путь из бекапа.
20 дек 18, 19:05    [21770009]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Вариант с проверкой логических имен похоже тоже мимо. Сделал логические имена, как на продуктиве те же ошибки.
Причем на тестовой базе разраба опять ругается только на второй файл лога (добавление к тестовой до восстановления с лог. именем прода не помогло). При этом когда открываешь окно восстановления в SSMS, выбираешь файлы бекапа, базу куда восстанавливать и переходишь на вкладку с путями, то там всё ок. Настройки для перемещения файлов по дефолтным путям сервера, где восстанавливаешь.
21 дек 18, 09:17    [21770227]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Изначальное предположение, что скрипт работал со скрытым триггером или ещё чем-то не подтвердилось.

Это именно свойства RESTORE DATABASE. Я предпочту продолжать использовать явный MOVE при восстановлении на другом сервере.

После успешного восстановления через SSMS начало нормально работать и просто через RESTORE DATABASE. При этом восстанавливает по путям перезаписываемой базы, даже если не совпадет с дефолтными путями сервера.
21 дек 18, 10:12    [21770270]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
Danion
Я предпочту продолжать использовать явный MOVE при восстановлении на другом сервере.
Это само собой. Но, конечно, интересно, какие причудливые алгоритмы заложили в RESTORE DATABASE, интересное исследование :-)

Danion
После успешного восстановления через SSMS начало нормально работать и просто через RESTORE DATABASE. При этом восстанавливает по путям перезаписываемой базы, даже если не совпадет с дефолтными путями сервера.
То есть, получается, сначала берётся путь из базы, потом из бакапа...
Кстати, есть такой вариант, что сопоставление файлов RESTORE делает не по физическим или логическим именам, а по file_id, некоторые мои эксперименты указывают на это.
21 дек 18, 13:44    [21770461]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
alexeyvg
То есть, получается, сначала берётся путь из базы, потом из бакапа...

нет, не получается.
попробуйте повторить мой эксперимент(3-ий пост от начала),
когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,
сервер полезет по путям, прописанным в бэкапе,
т.е. постарается перезаписать файлы базы первого сервера
21 дек 18, 13:50    [21770463]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
имеем 2 сервера, 2016 и 2012,
на обоих имеется база db2.
беру бэкап с 2012-ого и пытаюсь восстановить на 2016 поверх имеющейся db2.
сервер пытается перезаписать файлы исходной базы.
причем ему это не удается, ибо 2012-ый тоже запущен,
так что получаем
error
The operating system returned the error '32(The process cannot access the file because it is being used by another process.)' while attempting 'RestoreContainer::ValidateTargetForCreation' on 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL_2012\MSSQL\DATA\db2.mdf'.


К сообщению приложен файл. Размер - 55Kb
21 дек 18, 14:03    [21770479]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
Yasha123
alexeyvg
То есть, получается, сначала берётся путь из базы, потом из бакапа...

нет, не получается.
попробуйте повторить мой эксперимент(3-ий пост от начала),
когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,
сервер полезет по путям, прописанным в бэкапе,
т.е. постарается перезаписать файлы базы первого сервера
А "идентичная база" - имеется ввиду, что они обе восстановлены из одного бакапа? Или это значит, что у них просто одинаковые имена?
21 дек 18, 14:06    [21770483]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
alexeyvg
Yasha123
когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,
А "идентичная база" - имеется ввиду, что они обе восстановлены из одного бакапа? Или это значит, что у них просто одинаковые имена?

Вот, если база действительно идентичная, то есть с тем же GUID-ом:
use master
go
if exists(select * from sys.databases where name = 'db1')
	drop database db1
if exists(select * from sys.databases where name = 'db2')
	drop database db2
go
create database db1
ON   
( NAME = db1_data,  
    FILENAME = 'C:\tmp\db1\db.mdf') 
LOG ON  
( NAME = db1_log,  
    FILENAME = 'C:\tmp\db1\db.ldf');  
GO
create database db2
ON   
( NAME = db1_data,  
    FILENAME = 'C:\tmp\db2\db.mdf') 
LOG ON  
( NAME = db1_log,  
    FILENAME = 'C:\tmp\db2\db.ldf');  
GO

backup database db1 to disk='C:\tmp\db1.bak'
backup database db2 to disk='C:\tmp\db2.bak'
GO


--	Тут будет куча ошибок !!!
restore database db2 from disk='C:\tmp\db1.bak' 
WITH REPLACE;
go

--	Тогда восстанавливаем db2 из db1, то есть делаем их "идентичными"
restore database db2 from disk='C:\tmp\db1.bak' 
WITH MOVE 'db1_data' TO 'C:\tmp\db2\db.mdf',
MOVE 'db1_log' TO 'C:\tmp\db2\db.ldf',
REPLACE;
go


--	А вот тут всё нормально !
--	потому что после первого восстановления у неё поменялся GUID, 
--	и при восстановлении используются её пути, которые, заметим, 
--	отличаются от тех, которые в бакапе
restore database db2 from disk='C:\tmp\db1.bak' 
WITH REPLACE;
21 дек 18, 14:44    [21770550]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
alexeyvg
--	А вот тут всё нормально !
--	потому что после первого восстановления у неё поменялся GUID, 
--	и при восстановлении используются её пути, которые, заметим, 
--	отличаются от тех, которые в бакапе
restore database db2 from disk='C:\tmp\db1.bak' 
WITH REPLACE;
Хотя вот если ещё раз сделать бакап db1.bak, то он уже не восстановится.
Загадки сплошные :-)
21 дек 18, 14:49    [21770564]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Yasha123,

А в последнем примере путь у базы db2 2012 сервера такой и был? C:\...\MSSQL11.SQL_2012\...\db2.mdf?
Тогда на 2016 попробовало восстановиться по пути из бекапа. А попробуйте этот бекап на 2016 восстановить руками с move, а потом опять просто restore database. Скорее всего сработает.

Что точно меняется и когда начинает брать пути перезаписываемых файлов пока не понятно. Может вообще при первом восстановлении добавляет пометку в какую-то системную таблицу. Проверил msdb.dbo.restorefile, там есть информация по путям при восстановлении, но с этой таблицей скорее восстанавливало бы туда же, куда и в прошлой раз, а это не так.

Интересно, что в информации от Microsoft пояснений по логике Restore не нашел, не удивлюсь, если она ещё и от версии сервера менялась.
21 дек 18, 14:55    [21770571]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
Danion
А попробуйте этот бекап на 2016 восстановить руками с move, а потом опять просто restore database. Скорее всего сработает.
Да, я выше привёл скрипт, в первый раз срабатывает, со следующим бакапом - нет.
21 дек 18, 15:06    [21770590]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
Danion
Интересно, что в информации от Microsoft пояснений по логике Restore не нашел, не удивлюсь, если она ещё и от версии сервера менялась.
Угу, там опция REPLACE описана очень скудно.
21 дек 18, 15:06    [21770593]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
alexeyvg,

Я своё сообщение медленно в это же время набирал:)

Не очень понял, что перестало работать:

Рестор с move - всё ок.
Рестор просто - всё ок.
Один и тот же бекап.

Потом был снят новый бекап с db1 и
на db2 уже не восстановился?
21 дек 18, 15:13    [21770602]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Danion
Member

Откуда: Москва
Сообщений: 203
Попробовал на двух фулл бекапах продуктива с разницей в неделю. Первый раз хочет с move, но дальше никаких проблем не было. Достаточно было указать путь для первого бекапа только.
21 дек 18, 15:43    [21770650]     Ответить | Цитировать Сообщить модератору
 Re: Скрипт восстановления БД  [new]
Yasha123
Member

Откуда:
Сообщений: 1833
докладываю.
при ресторе в "идентичную базу",
которая получена совсем не рестором,
берутся пути базы (не бэкапа)

при ресторе в базу,
к-ая получена рестором аналогичной с другого сервера,
уже берутся пути самой базы,
т.е. как и предположил Danion:
Danion
А в последнем примере путь у базы db2 2012 сервера такой и был? C:\...\MSSQL11.SQL_2012\...\db2.mdf?
Тогда на 2016 попробовало восстановиться по пути из бекапа.
А попробуйте этот бекап на 2016 восстановить руками с move,
а потом опять просто restore database. Скорее всего сработает
.


гуид базы, разумеется, поменялся, НО совсем не на гуид базы с первого сервера.
зато что тепереь у этих баз одинаковое, так это family_guid,
упомянутый, кстати, в документации по RESTORE.

и это family_guid как раз относится к бэкапу:
BOL
Identifier of the "backup family" for the database for detecting matching restore states.


итого имеем:
при восстановлении сравнивается family_guid обеих баз,
если они совпали, значит базу уже восстанавливали из бэкапа этого семейства,
и значит, не будем лезть в пути, записанные в бэкапе, пойдем напрямуй перезаписывать имеющиеся файлы.
зато если семейства разные, перед нами НЕ копия базы, полученная предыдущим рестором,
так что раз пути не указали в команде, то пойдем и прочтем их из бэкапа и полезем по этим путям.
и горе тому, у кого по этому пути уже что-то лежит, его перезапишут,
не глядя вообще на то, что перезаписываем.

К сообщению приложен файл. Размер - 22Kb
21 дек 18, 16:16    [21770687]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить