RESTORE BD:Exclusive access could not be obtained because the database is in use.

Мордор Держимордов
Дата: 23.01.2009 03:50:12
SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO





ALTER      PROCEDURE RESTORE_BD_BY_BACKUP
   @basename  [nvarchar] (200)
 , @path_to_restore [nvarchar] (4000)
 , @backup_path_and_file [nvarchar] (4000)
 , @Nt_UserName [nvarchar] (50) = NULL
as
if right(@path_to_restore,1) <> '\' or right(@path_to_restore,1) <> '/'
 set  @path_to_restore = @path_to_restore + '\'
declare @SQL [nvarchar] (4000)
declare @Log_LogicalName [nvarchar](128)
declare @Data_LogicalName [nvarchar](128)
/*Вытаскиваем логические имена*/
create table #t
		(
		LogicalName nvarchar(128)
		, PhysicalName nvarchar(260)
		, Type char(1)
		, FileGroupName nvarchar(128)
		, [Size] numeric(20,0)
		, [MaxSize] numeric(20,0)
		)
set @SQL = N'RESTORE FILELISTONLY from DISK = N''' + @backup_path_and_file + ''''
insert	#t exec(@SQL)
select @Log_LogicalName = LogicalName from #t where Type = 'L'
select @Data_LogicalName = LogicalName from #t where Type = 'D'
drop table #t
/*Вытаскиваем логические имена*/
 set @SQL = 
 'RESTORE DATABASE [' + @basename + ']'
 + ' FROM  DISK = N''' + @backup_path_and_file + ''''
 + ' WITH  FILE = 1,  NOUNLOAD ,  STATS = 10,  RECOVERY , REPLACE '
 + ', MOVE N''' + @Log_LogicalName + ''' TO N''' + @path_to_restore + @basename + '_log.ldf'''
+ ', MOVE N''' + @Data_LogicalName + ''' TO N''' + + @path_to_restore + @basename + '.mdf'''
exec(@SQL)
set @SQL = @basename 
+ ': Востановлена из бэкапа - ' + @backup_path_and_file

exec p_insert_t_event_log  @SQL

if not(@Nt_UserName is NULL) 
 BEGIN
  set @SQL = ' exec master..xp_cmdshell N''net send ' + @Nt_UserName + ' " ' + 'База ' 
  + @basename + ' востановлена из бэкапа : ' + @backup_path_and_file + ' "'''
exec(@SQL)
 END

/*
exec PAM_WORK_..RESTORE_BD_BY_BACKUP 
'Bd_cont90'
,'D:\DATA\'
,'F:\BackUp\EMPTY_BASE\BDCont240.bk'
,'user0700_11'
/*

(2 row(s) affected)

Server: Msg 3101, Level 16, State 2, Line 1
Exclusive access could not be obtained because the database is in use.
Server: Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.

(1 row(s) affected)


(3 row(s) affected)


*/
*/
GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

Запускаю процедуру:
exec PAM_WORK_..RESTORE_BD_BY_BACKUP 
'Bd_cont90'
,'D:\DATA\'
,'F:\BackUp\EMPTY_BASE\BDCont240.bk'
,'user0700_11'

Результат:

Server: Msg 3101, Level 16, State 2, Line 1
Exclusive access could not be obtained because the database is in use.
Server: Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.

(1 row(s) affected)


(3 row(s) affected)

Каким образом отключить всех пользователей от БД перед восстановлением?
Кудряшка
Дата: 23.01.2009 03:58:54
Установить базу в SINGLE_USER mode

IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'DB_NAME')
	ALTER DATABASE [DB_NAME] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

DB_NAME - имя ВАШЕЙ базы.
Кудряшка
Дата: 23.01.2009 04:02:16
Да, а еще убедиться, что скрипт восстановления запускается не на той базе, которую восстанавливаете, а на базе master, например.
Мордор Держимордов
Дата: 23.01.2009 04:26:28
Кудряшка
Да, а еще убедиться, что скрипт восстановления запускается не на той базе, которую восстанавливаете, а на базе master, например.


exec PAM_WORK_..RESTORE_BD_BY_BACKUP 
'Bd_cont90'
,'D:\DATA\'
,'F:\BackUp\EMPTY_BASE\BDCont240.bk'
,'user0700_11'

То есть Процедура RESTORE_BD_BY_BACKUP запускается с БД PAM_WORK_, а имя восстанавливаемой базы - Bd_cont90.
Мордор Держимордов
Дата: 23.01.2009 04:36:44
Я вот в профайлере посмотрел как он делает ЭТО:

sp_MSget_current_activity 1228,1 
KILL 106

где 106 это ProcessID, а 1228 откуда берётся?
из sp_MSget_current_activity наковырял:

set @locktab = N'##lockinfo' + rtrim(convert(nvarchar(5), @id))
    set @stmt = N'select [Process ID], [User], [Database], [Status], [Open Transactions], [Command], [Application], [Wait Time], [Wait Type], [Wait Resource], [CPU], [Physical IO], [Memory Usage], [Login Time], [Last Batch], [Host], [Net Library], [Net Address], [Blocked By], [Blocking], [Execution Context ID] from ' + @proctab + ' order by [Process ID],[Execution Context ID]'
exec(@stmt)
То есть всё смотрим из  временной таблицы ##lockinfo1228
Как узнать какой свой ID?
Мордор Держимордов
Дата: 23.01.2009 04:40:30
Угу, а прога которая заливает в БД инфу запускается под другим юзером...
Кудряшка
Дата: 23.01.2009 05:01:43
--Как узнать какой свой ID?

ID в смысле ID процесса?
SELECT @@SPID

--Я вот в профайлере посмотрел как он делает ЭТО:

Он - это кто?:) Профаилер? :)

И ваще что вы страдаете... перед RESTORE DATABASE напишите:

set @SQL = 'ALTER DATABASE [' + @basename + ']' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
exec(@SQL)

Кудряшка
Дата: 23.01.2009 05:05:46
Ковычка лишняя...

set @SQL = 'ALTER DATABASE [' + @basename + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
exec(@SQL)

После восстановления можно в Мульти-юзер на всякий случай обратно установить.

П.С.: вышенаписанное надо вставить в процедуру RESTORE_BD_BY_BACKUP
перед кодом:

 set @SQL = 
 'RESTORE DATABASE [' + @basename + ']'
 + ' FROM  DISK = N''' + @backup_path_and_file + ''''
 + ' WITH  FILE = 1,  NOUNLOAD ,  STATS = 10,  RECOVERY , REPLACE '
 + ', MOVE N''' + @Log_LogicalName + ''' TO N''' + @path_to_restore + @basename + '_log.ldf'''
+ ', MOVE N''' + @Data_LogicalName + ''' TO N''' + + @path_to_restore + @basename + '.mdf'''
exec(@SQL)

Кудряшка
Дата: 23.01.2009 05:07:54
Мордор Держимордов
Угу, а прога которая заливает в БД инфу запускается под другим юзером...


А это и неважно...
Мордор Держимордов
Дата: 23.01.2009 08:09:54
Мож у кого ещё какие идеи?