unable to restore database in sql server (single_user) - sql-server

I am trying to restore a database in my sql server 2005 express edition. I know that to restore the database I need to make it to single user. I am giving this command to make it to single user
USE [master]
ALTER DATABASE database_name SET SINGLE_USER WITH ROLLBACK IMMEDIATE
This command executed properly and I can even see a small image in the object explorer on this database showing that this is now single user.
Now I am trying to restore the database, by following these steps
->right click on the database and tasks and then to restore database. I am selecting the path where the backup file is located and clicking on restore.
But I still get that error "Exclusive access could not be obtained because database is in use(microsoft.sqlserver.smo). Am I missing anything. I have googled it and all most all the sites suggest that database needs to be in single user mode and nothing else.
I did not try the detach and attaching of database method. I have never done that before and would like to know if that is safe to do.
edit: thanks for the answers. Both suggested me same answer so I am marking one answer as chosen.
I even selected overwrite the existing database from options.

First, it's best to back up and restore rather than detach and attach.
Second, it's most likely that the session you're using to set the database to SINGLE_USER is the one that still has it when you try to run the restore (since you're using the GUI, it's connecting under its own session so it's unable to get access).
Either do the restore as a text command or switch the query window to use another database first, such as master. Or you could just close the query window so it's no longer connected.
You can always check who's connected with select * from master.dbo.sysprocesses.
Update
Assuming the database you want to restore already exists, and if you have a single backup file on disk (that doesn't have multiple backups in it) and there's no need to restore log files after restoring the full backup, then restoring via script is super, super easy:
RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak';
Learning this syntax will make your life easier because then when you set SINGLE_USER you're already in the sole session that is connected. Plus, I find that typing the restore command is faster than using the GUI, and I like the control I have over things. Repetition of this eventually cements it in your mind and you don't have to look up the syntax any more.
It's not even that difficult to restore log files. Just one simple thing to remember, WITH NORECOVERY:
RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup1.log' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup2.log' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup3.log' WITH NORECOVERY;
... 4 5 6 7 and so on
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackupX.log' WITH RECOVERY;
There... you've restored your log files, very easily. You can even restore to an exact point in time using WITH STOPAT! Also, if you forget and accidentally submit the last log restore statement WITH NORECOVERY then you just issue RESTORE DATABASE DBName WITH RECOVERY; to perform the final steps to make the database usable (rolling back uncommitted transactions, etc.).

You can use this script to kill all processes using the database and then try to restore it again:
declare #sql as varchar(20), #spid as int
select #spid = min(spid) from master..sysprocesses where dbid = db_id('<database_name>')
and spid != ##spid
while (#spid is not null)
begin
print 'Killing process ' + cast(#spid as varchar) + ' ...'
set #sql = 'kill ' + cast(#spid as varchar)
exec (#sql)
select
#spid = min(spid)
from
master..sysprocesses
where
dbid = db_id('<database_name>')
and spid != ##spid
end
print 'Process completed...'

Go to "Options" item just under "General" on the left hand side list.
Make sure that "Overwrite the existing database" is checked ("Restore Options" section).
Good luck.

Related

Restoring database from script

I have created a small scrip to restore databases from backups. Once the script is run it displays
RESTORE DATABASE successfully processed 28818 pages in 1.568 seconds
(143.584 MB/sec).
I have more code to alter the database, alter a few views and sp too but I am getting the following error; User does not have permission to alter database 'GreyGoo', the database does not exist, or the database is not in a state that allows access checks.
I have noticed too that I cannot see the database in the object explorer
this is what I use to restore the DB from a backup
if DB exists set to a single user
if DB exist drop database
Ran the below script
RESTORE DATABASE GreyGoo FROM DISK = 'C:\Bkp\GreyGoo_backup_2020_03_02_180002_5403592.bak'
WITH
MOVE 'GreyGoo' TO 'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\GreyGoo.mdf',
MOVE 'GreyGoo_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\GreyGoo.ldf',
REPLACE;
set DB to multi-users and other properties
So what is the problem and how can I solve it, I am currently testing my code on SQL Server 2008
Thanks
During your restore process, you will need to ensure your
login / permissions are correct.
if another previous database with same name is not there, if so delete it. Perhaps from a previous attempt
You can also turn off recovery option like below, recovery is default
RESTORE FILELISTONLY
Sample -- MSDN
USE master;
GO
-- First determine the number and names of the files in the backup.
-- AdventureWorks2012_Backup is the name of the backup device.
RESTORE FILELISTONLY
FROM AdventureWorks2012_Backup;
-- Restore the files for MyAdvWorks.
RESTORE DATABASE MyAdvWorks
FROM AdventureWorks2012_Backup
WITH RECOVERY,
MOVE 'AdventureWorks2012_Data' TO 'D:\MyData\MyAdvWorks_Data.mdf',
MOVE 'AdventureWorks2012_Log' TO 'F:\MyLog\MyAdvWorks_Log.ldf';
GO
EXEC msdb.dbo.sp_delete_database_backuphistory #database_name = N'MYDB'
GO
USE [master]
GO
/* Database [MYDB] */
DROP DATABASE [MYDB]
GO
USE [master]
RESTORE DATABASE [MYDB] FROM DISK = N'E:\FTP\local_MYDB_01.bak' WITH FILE = 1, MOVE N'blank' TO N'E:\DBs\2019\MYDB.mdf', MOVE N'blank_log' TO N'E:\DBs\2019\MYDB.ldf', NOUNLOAD, STATS = 5
GO

how to change log_reuse_wait and log_reuse_wait_desc

I have been created new database and the log file groth very past, and I get error mesaage that the log is full due to 'BACKUP'.
I looked in the differences between this Database and other databases in the SERVER, and I seen that in all databases log_reuse_wait is 0 and log_reuse_wait_desc is NOTHING and in my database log_reuse_wait is 0 and log_reuse_wait_desc is LOG_BACKUP.
I want to change this property in my database to 0 and NOTHING.
How can I do that?
This is a read-only status variable. It tells you why the log cannot be truncated at this point.
You have to remove the cause of that condition instead of just changing the value (which isn't even possible).
Either backup the database log or switch to SIMPLE recovery mode. You should probably read a little on both just to understand the implications.
David W.'s script did not quite work for me. (SQL Server 2008 r2)
I needed to modify it slightly. Using the script as is I got the message that there was no such file for database [master]. Alter the DATABASE as David W. recommends and then switch to the target database and run the DBCC SHRINKFILE() command.
Also the first argument to DBCC SHRINKFILE() must be the logical name of the database log file, which is represented in the following script as logical_file_name_for_LOG
USE [master]
GO
ALTER DATABASE <db name> SET RECOVERY full
GO
ALTER DATABASE <db name> SET RECOVERY SIMPLE WITH NO_WAIT;
GO
USE [db name]
GO
DBCC SHRINKFILE('<logical_file_name_for_LOG>', 0, TRUNCATEONLY)
i found the solution.
even the database is in SIMPLE mode is wait to BACKUP_LOG, so you need to change the recovery mode to FULL and then back to SIMPLE with no wait
USE [master]
GO
ALTER DATABASE <db name> SET RECOVERY full
GO
ALTER DATABASE <db name> SET RECOVERY SIMPLE WITH NO_WAIT;
GO
USE [db name]
GO
DBCC SHRINKFILE('<log file name>', 0, TRUNCATEONLY)
I know this is old, but the answers are wrong.
If the database has recovery mode FULL and that is intended, then do not change it to simple.
The log_reuse_wait_desc says what the state is before the log can be reused or shrinked. In this case it is LOG_BACKUP, meaning that, to shrink the transaction log, you need to backup the transaction log first and shrink it or backup the log and let the SQLServer reuse the log space.
A description of the log_reuse_wait_desc states can be found here

Trying to restore via t-sql script. Exclusive access could not be obtained because the database is in use

I'm trying to restore backups of our production databases to our development server. When I run the following script which has previously worked:
RESTORE DATABASE M2MDATA01 FROM DISK = 'C:\Install\SQLBackup\M2MDATA01.SQLBackup' WITH REPLACE,
MOVE 'M2MDATA01' TO 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\M2MData01.mdf',
MOVE 'M2MDATA01_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\M2MData01.ldf'
I get the following error:
Error 12/21/2009 9:06:09 AM 0:00:00.000 SQL Server Database Error: Exclusive access could not be obtained because the database is in use. 5 0
However, I have no idea how what could possibly be using it. How can I tell?
Check what's connected (the easy way)
SELECT * FROM sys.sysprocesses S WHERE S.dbid = DB_ID('M2MDATA01')
Note: sysprocesses can not be emulated using dmvs...
Edit, check for locks too
SELECT * FROM sys.dm_tran_locks L WHERE L.resource_type = 'DATABASE' AND L.resource_database_id = DB_ID('M2MDATA01')
In SQL Server Management Studio, go to Management => Activity Monitor. This will show you all processes that are connected to all databases, and allow you to kill these processes (only recommended as a last resort).
Profiler is one option.
From Sql Server Management Studio, select Tools|Sql Server Profiler.
Connect to the server instance that the database you are working with is on.
Switch to the Event Selection tab
check the checkbox below the grid labeled "Show all columns"
In the grid find the DatabaseName column and check the entire column.
(optional) press the Column Filters button and filter to the database name you are working with.
This should at least tell you if something is using the database in question.
Easiest solution here is to delete the database and select the "close existing connections" checkbox before hitting okay. Then the restore will work just fine. It's just DEV right? :}
If you're restoring a db, do you really care who is connected? Or what is being done with those connections? I would think not. Just "kick everyone out" by setting the database into single user mode and then restore the database.
USER master
GO
ALTER DATABASE M2MDATA01
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO
RESTORE DATABASE M2MDATA01
FROM DISK = 'C:\Install\SQLBackup\M2MDATA01.SQLBackup'
WITH REPLACE,
MOVE 'M2MDATA01' TO 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\M2MData01.mdf',
MOVE 'M2MDATA01_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\M2MData01.ldf'
GO
Now, one additional item to be aware of. After you set the db into single user mode, someone else may attempt to connect to the db. If they succeed, you won't be able to proceed with your restore. It's a race! My suggestion is to run all three statements at once in a single batch.

Checking If Database In Restoring State

I'm running a T-SQL script that drops a database and then restores it. The script runs against a SQL Server 2008 database. Sometimes there is a problem with the backup file and the database gets stuck in the restoring state.
IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases WHERE name = 'dbname')
BEGIN
ALTER DATABASE [dbname]
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
END
IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases WHERE name = 'dbname')
BEGIN
DROP DATABASE [dbname]
END
RESTORE DATABASE [dbname]
FROM DISK = N'C:\dbname.bak'
WITH FILE = 1,
NOUNLOAD,
STATS = 10
The next time the script runs the script generates the error message
ALTER DATABASE is not permitted while a database is in the Restoring state.
What is the best way to check if the database is in the restoring state before trying to run the ALTER DATABASE command?
EDIT: The RESTORE DATABASE command that I'm running doesn't use the NO RECOVERY option.
It sounds as though you are performing a database restore with the NORECOVERY option. The reason you would want to do this is if you were planning to apply subsequent transaction log backups after the initial restore.
If you only wish to restore a single database backup then remove the NORECOVERY clause. If you are restoring transaction log backups, the final restore must be done without the NORECOVERY clause or if the last was applied with NORECOVERY you can RESTORE DATABASE DbName WITH RECOVERY to finalize.
To answer your question:
Method 1
SELECT DATABASEPROPERTYEX ('DatabaseName', 'Status')
See SQL Server Books Online: DATABASEPROPERTYEX (Transact-SQL)
Method 2
Review the sys.databases system view in order to determine the current state of a database. For example:
SELECT
state,
state_desc
FROM sys.databases
WHERE [name] = 'DatabaseName'
A state of 1 = RESTORING
See Sys.Databases for documentation regarding this system view.
SELECT DATABASEPROPERTYEX ('MyDb', 'Status')
Others had a similar problem doing a RESTORE with pyodbc. My variation of the problem (with similar symptoms to yours) turned out to be an incorrect bak file. This can be discovered with the following T-SQL, looking for incorrect .mdf or .ldf file names or database names:
RESTORE FILELISTONLY FROM DISK = N'C:\dbname.bak'
Method 2:
SELECT
state,
state_desc
FROM sys.databases
WHERE [name] = 'Databasename'
It is give me exact result.

How to recover database from MDF in SQL Server 2005?

I have an MDF file and no LDF files for a database created in MS SQL Server 2005. When I try to attach the MDF file to a different SQL Server, I get the following error message.
The log cannot be rebuilt because there were open transactions/users when the database was shutdown, no checkpoint occurred to the database, or the database was read-only. This error could occur if the transaction log file was manually deleted or lost due to a hardware or environment failure.
I would like to accomplish any one of the following options:
Attach the database without data loss (unlikely but would save me some time).
Attach the database with data loss (whatever transactions were open are lost).
Recover the schema only (no data) from the MDF file.
What SQL commands can I try to get my database going again?
I found the following document on Experts Exchange.
patrikt:
You will have data loss but it can be done.
1. Detach database and move your mdf to save location.
2. Create new databse of same name, same files, same file location and same file size.
3. Stop SQL server.
4. Swap mdf file of just created DB to your save one.
5. Start SQL. DB will go suspect.
6. ALTER DATABASE yourdb SET EMERGENCY
7. ALTER DATABASE yourdb SET SINGLE_USER
8. DBCC CHECKDB (yourdb, REPAIR_ALLOW_DATA_LOSS)
9. ALTER DATABASE yourdb SET MULTI_USER
10. ALTER DATABASE yourdb SET ONLINE
Here are details that cover parts 2) and 3) in case re-creating log doesn’t work which can happen if MDF file is corrupted.
You can recover data and structure only by reading MDF file with some third party tool that can de-code what’s written as binary data but even with such tools you can’t always do the job completely.
In such cases you can try ApexSQL Recover. From what I know this is the only tool that can do this kind of job but it’s quite expensive.
Much better idea is to try to recover these from any old backups if you have any.
FROM a post at SQL Server Forums Attaching MDF without LDF:
If you want to attach a MDF without LDF you can follow the steps below
It is tested and working fine
Create a new database with the same name and same MDF and LDF files
Stop sql server and rename the existing MDF to a new one and copy the original MDF to this location and delete the LDF files.
Start SQL Server
Now your database will be marked suspect 5. Update the sysdatabases to update to Emergency mode. This will not use LOG files in start up
Sp_configure "allow updates", 1
go
Reconfigure with override
GO
Update sysdatabases set status = 32768 where name = "BadDbName"
go
Sp_configure "allow updates", 0
go
Reconfigure with override
GO
Restart sql server. now the database will be in emergency mode
Now execute the undocumented DBCC to create a log file
DBCC REBUILD_LOG(dbname,'c:\dbname.ldf') -- Undocumented step to
create a new log file.
(replace the dbname and log file name based on ur requirement)
Execute sp_resetstatus
Restart SQL server and see the database is online.
UPDATE: DBCC REBUILD_LOG does not existing SQL2005 and above. This should work:
USE [master]
GO
CREATE DATABASE [Test] ON
(FILENAME = N'C:\MSSQL\Data\Test.mdf')
FOR ATTACH_REBUILD_LOG
GO
have you tried to ignore the ldf and just attach the mdf:
sp_attach_single_file_db [ #dbname = ] 'dbname' , [ #physname = ] 'physical_name'
i don't know exactly what will happen to your open transactions (probably just lost), but it might get your data back online.
-don
See here : Rebuild master and restore system databases from complete disk failure which has a very nice explanation
Just had this problem myself, but none of the above answers worked for me.
But instead, I found this which worked a treat and so I thought I'd share this for everyone else:
http://www.kodyaz.com/articles/sql-server-attach-database-mdf-file.aspx
Found a another way that works completely:
Create new database with same name to default database location.
Stop SQL server.
Copy old mdf file to overwrite newly created mdf file and delete new ldf file
Start SQL Server, database will be in emergency mode
Detach the emergency mode database
Copy original ldf file to default database location (where new LDF file as created and deleted under step 3 above.
Attach the database MDF file.
I got a working database after trying all of the above that failed for me.
I hope it is easy to do so,
Open SQL Server
Click New Query
Execute the following query
sp_attach_single_file_db #dbname='dbname',#physname='C:\Database\dbname.MDF'
Where dbname is you want to show in Object Explorer, where #physname is the local filepath location of your mdf file.
Hope it will help someone, i done by above, got both structure and also data.
Tested in Sql Server 2000 and 2008. In Sql Server 2000 it is not working, but works perfectly in 2008.

Resources