Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Скрипт восстановления БД / 25 сообщений из 27, страница 1 из 2
20.12.2018, 16:36
    #39750946
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Добрый день.

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

Текст запроса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
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 похоже работал.
Вообще выглядит как будто есть объект в котором есть имя базы и пути файлов для перемещения и при ресторе через скрипт автоматом мувит.
у кого какие идеи насчёт возможной реализации, интересно как такое реализовано.
...
Рейтинг: 0 / 0
20.12.2018, 17:09
    #39750960
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
а какие проблемы вы нашли в скрипте?
вот такое генерится:

Код: sql
1.
2.
3.
4.
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 уже существующей базе,
все пути к вашей базе берутся из метаданных самой базы, а не бэкапа.

я на свой ноут (с единственным диском С) так таскаю базы,
хотя на сервере, откуда беру, файлы разнесены по дискам О и Р
...
Рейтинг: 0 / 0
20.12.2018, 17:16
    #39750963
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
хотя да,
если например имеем 2 сервера на одном компе,
на обоих база существует,
пути к базам разные,
то попытка восстановить с одного на другой,
указав лишь with replace,
закончится плачевно, ибо попытается восстановить поверх файлов базы-исходника.

т.е. какая-то неконсистентность все же есть:
сперва он пытается восстановить по путям, взятым из бэкапа,
и только если таких нет, восстанавливает по путям текущей базы
...
Рейтинг: 0 / 0
20.12.2018, 17:24
    #39750968
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
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
...
Рейтинг: 0 / 0
20.12.2018, 17:36
    #39750976
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Просто так базы разработчиков перезаписать нельзя и придется ждать обращения от них.
Можно будет на hrm базе проверить работает ли ещё скрипт (у erp 2 лога и не работает), если да (а по идее ничего не менялось), то вытянуть текст запроса во время восстановления. Будет ли там конструкция с move или просто RESTORE DATABASE который получаю через принт без запуска.
...
Рейтинг: 0 / 0
20.12.2018, 17:45
    #39750979
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
вот мой сервер, с единственным диском С,
и вот их бэкапчик, с их путями, которых у меня нет.
восстанавливаю в существующую базу.
на картинке успешное восстановление и диски,
к-ые видит мой сервер(всего 1 диск и видит)
...
Рейтинг: 0 / 0
20.12.2018, 17:54
    #39750987
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
в вашем эксперименте другое имя базы,
куда восстанавливаете.
...
Рейтинг: 0 / 0
20.12.2018, 17:57
    #39750990
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Yasha123,

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

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

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

Тогда возможно в моём случае именно после восстановления в базу с 1 лог файлом начало восстанавливать по путям бекапа и какой-то схемы с скрытыми триггерами, как подумал сначала нет. Будет задача на обновление базы, проверю точно.
А пока можно перечитать, что Microsoft пишет по этому поводу.
...
Рейтинг: 0 / 0
20.12.2018, 17:58
    #39750991
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Yasha123в вашем эксперименте другое имя базы,
куда восстанавливаете.

Ну там всегда и было другое имя. Продуктивная база в БД_фамилияРазраба.
...
Рейтинг: 0 / 0
20.12.2018, 18:07
    #39750998
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
кстати, это без разницы.
и с другим именем перезапишется.
я просто сравниваю со своей ситуацией,
(у меня имя базы то же самое)

все это документировано:
RESTORE Statements (Transact-SQL)
...
Рейтинг: 0 / 0
20.12.2018, 19:05
    #39751029
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Yasha123,

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

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

Случаем не идёт сравнение логического имени файла перезаписываемой базы с бекапом, если совпало, то путь перезаписываемой, если нет, то путь из бекапа.
...
Рейтинг: 0 / 0
21.12.2018, 09:17
    #39751145
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Вариант с проверкой логических имен похоже тоже мимо. Сделал логические имена, как на продуктиве те же ошибки.
Причем на тестовой базе разраба опять ругается только на второй файл лога (добавление к тестовой до восстановления с лог. именем прода не помогло). При этом когда открываешь окно восстановления в SSMS, выбираешь файлы бекапа, базу куда восстанавливать и переходишь на вкладку с путями, то там всё ок. Настройки для перемещения файлов по дефолтным путям сервера, где восстанавливаешь.
...
Рейтинг: 0 / 0
21.12.2018, 10:12
    #39751176
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Изначальное предположение, что скрипт работал со скрытым триггером или ещё чем-то не подтвердилось.

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

После успешного восстановления через SSMS начало нормально работать и просто через RESTORE DATABASE. При этом восстанавливает по путям перезаписываемой базы, даже если не совпадет с дефолтными путями сервера.
...
Рейтинг: 0 / 0
21.12.2018, 13:44
    #39751303
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
DanionЯ предпочту продолжать использовать явный MOVE при восстановлении на другом сервере.Это само собой. Но, конечно, интересно, какие причудливые алгоритмы заложили в RESTORE DATABASE, интересное исследование :-)

DanionПосле успешного восстановления через SSMS начало нормально работать и просто через RESTORE DATABASE. При этом восстанавливает по путям перезаписываемой базы, даже если не совпадет с дефолтными путями сервера.То есть, получается, сначала берётся путь из базы, потом из бакапа...
Кстати, есть такой вариант, что сопоставление файлов RESTORE делает не по физическим или логическим именам, а по file_id, некоторые мои эксперименты указывают на это.
...
Рейтинг: 0 / 0
21.12.2018, 13:50
    #39751305
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
alexeyvgТо есть, получается, сначала берётся путь из базы, потом из бакапа...

нет, не получается.
попробуйте повторить мой эксперимент(3-ий пост от начала),
когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,
сервер полезет по путям, прописанным в бэкапе,
т.е. постарается перезаписать файлы базы первого сервера
...
Рейтинг: 0 / 0
21.12.2018, 14:03
    #39751317
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
имеем 2 сервера, 2016 и 2012,
на обоих имеется база db2.
беру бэкап с 2012-ого и пытаюсь восстановить на 2016 поверх имеющейся db2.
сервер пытается перезаписать файлы исходной базы.
причем ему это не удается, ибо 2012-ый тоже запущен,
так что получаем
errorThe 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'.
...
Рейтинг: 0 / 0
21.12.2018, 14:06
    #39751321
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Yasha123alexeyvgТо есть, получается, сначала берётся путь из базы, потом из бакапа...

нет, не получается.
попробуйте повторить мой эксперимент(3-ий пост от начала),
когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,
сервер полезет по путям, прописанным в бэкапе,
т.е. постарается перезаписать файлы базы первого сервераА "идентичная база" - имеется ввиду, что они обе восстановлены из одного бакапа? Или это значит, что у них просто одинаковые имена?
...
Рейтинг: 0 / 0
21.12.2018, 14:44
    #39751367
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
alexeyvgYasha123когда оба сервера находятся на одном физическом и на обоих есть идентичная база.
если взять бэкап базы с первого сервера и попробовать восстановить
в уже имеющуюся базу без указания with move,А "идентичная база" - имеется ввиду, что они обе восстановлены из одного бакапа? Или это значит, что у них просто одинаковые имена?
Вот, если база действительно идентичная, то есть с тем же GUID-ом:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
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;
...
Рейтинг: 0 / 0
21.12.2018, 14:49
    #39751380
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
alexeyvg
Код: sql
1.
2.
3.
4.
5.
6.
--	А вот тут всё нормально !
--	потому что после первого восстановления у неё поменялся GUID, 
--	и при восстановлении используются её пути, которые, заметим, 
--	отличаются от тех, которые в бакапе
restore database db2 from disk='C:\tmp\db1.bak' 
WITH REPLACE;

Хотя вот если ещё раз сделать бакап db1.bak, то он уже не восстановится.
Загадки сплошные :-)
...
Рейтинг: 0 / 0
21.12.2018, 14:55
    #39751385
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Yasha123,

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

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

Интересно, что в информации от Microsoft пояснений по логике Restore не нашел, не удивлюсь, если она ещё и от версии сервера менялась.
...
Рейтинг: 0 / 0
21.12.2018, 15:06
    #39751398
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
DanionА попробуйте этот бекап на 2016 восстановить руками с move, а потом опять просто restore database. Скорее всего сработает.Да, я выше привёл скрипт, в первый раз срабатывает, со следующим бакапом - нет.
...
Рейтинг: 0 / 0
21.12.2018, 15:06
    #39751401
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
DanionИнтересно, что в информации от Microsoft пояснений по логике Restore не нашел, не удивлюсь, если она ещё и от версии сервера менялась.Угу, там опция REPLACE описана очень скудно.
...
Рейтинг: 0 / 0
21.12.2018, 15:13
    #39751406
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
alexeyvg,

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

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

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

Потом был снят новый бекап с db1 и
на db2 уже не восстановился?
...
Рейтинг: 0 / 0
21.12.2018, 15:43
    #39751429
Danion
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
Попробовал на двух фулл бекапах продуктива с разницей в неделю. Первый раз хочет с move, но дальше никаких проблем не было. Достаточно было указать путь для первого бекапа только.
...
Рейтинг: 0 / 0
21.12.2018, 16:16
    #39751451
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скрипт восстановления БД
докладываю.
при ресторе в "идентичную базу",
которая получена совсем не рестором,
берутся пути базы (не бэкапа)

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


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

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

итого имеем:
при восстановлении сравнивается family_guid обеих баз,
если они совпали, значит базу уже восстанавливали из бэкапа этого семейства,
и значит, не будем лезть в пути, записанные в бэкапе, пойдем напрямуй перезаписывать имеющиеся файлы.
зато если семейства разные, перед нами НЕ копия базы, полученная предыдущим рестором,
так что раз пути не указали в команде, то пойдем и прочтем их из бэкапа и полезем по этим путям.
и горе тому, у кого по этому пути уже что-то лежит, его перезапишут,
не глядя вообще на то, что перезаписываем.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Скрипт восстановления БД / 25 сообщений из 27, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]