How to Attach a SQL Server Database without a Transaction Log and with Open Transactions

By:   |   Comments (41)   |   Related: More > Database Administration


Problem

You want to attach a SQL Server database that does not have the transaction log file and you get the following error when you try to attach the data file:

"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."

In this tip I will show how you two methods that can successfully attach a database when you get this error.

Solution

Here I will cover the not so uncommon scenario where someone gives you a SQL Server database to attach to your instance, but only gives you the *.mdf file. Unfortunately, when you try to attach the database the SQL Server engine complains about the missing transaction log and aborts the attachment process.

Test Environment Setup

First, we will create our sample database and set the recovery model to Full by running the scripts below in SQL Server Management Studio.

USE [master]
GO

CREATE DATABASE [TestDB]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'TestDB_file1', 
			FILENAME = N'E:\MSSQL\TestDB_1.mdf',
			SIZE = 128MB , 
			MAXSIZE = UNLIMITED, 
			FILEGROWTH = 64MB) 
 LOG ON 
( NAME = N'TestDB_log_file1',
			 FILENAME = N'E:\MSSQL\TestDB_1.ldf',
			 SIZE = 8MB,
			 MAXSIZE = 2048GB,
			 FILEGROWTH = 8MB)
GO

ALTER DATABASE TestDB SET RECOVERY FULL
GO

The next script will create our sample table.

USE TestDB
GO

SELECT  *
INTO    TestTable
FROM    sys.objects	   

Now we are going to add some sample data. We want the insert statement to take enough time to let us force the shutdown of the test instance while it is still running. This will let the database be in an inconsistent state needing to perform recovery at the next database startup.

USE TestDB;
GO

INSERT INTO dbo.TestTable
SELECT  a.*
FROM    TestTable a
        CROSS JOIN sys.objects b
        CROSS JOIN sys.objects c
        CROSS JOIN sys.objects d

In another window in SQL Server Management Studio execute the following statement to force the instance shutdown.

SHUTDOWN WITH NOWAIT

After stopping the instance, delete the log file then start up the SQL Server service. If you refresh the Databases view in SQL Server Management Studio you will see that our test database is inaccessible because it is marked as Recovery Pending, as shown on the next image.

Recovery Pending Database.

At this point we have an orphaned and inconsistent database file.

First, let's clean the system catalog by dropping the database. We must set the database offline to copy or rename the data file that will be the subject for our tests.

USE master
GO

ALTER DATABASE TestDB SET OFFLINE 
GO

Then we must clean the system catalog metadata by dropping the database.

USE master
GO

DROP DATABASE TestDB
GO

Trying to Attach the Damaged SQL Server Database

When you are asked to attach a database with one data file and no log, the first thing that may come to mind is the old and deprecated sp_attach_single_file_db.

USE master 
GO 

EXEC sys.sp_attach_single_file_db @dbname = 'TestDB', 
    @physname = N'E:\MSSQL\TestDBCopy.mdf' 
GO

But after you execute the previous script you will see that it fails with this 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."

See the image below as a point of reference.

Failed Attempt To Attach the Database.

Since sp_attach_single_file_db is deprecated and has been replaced with CREATE DATABASE..FOR ATTACH, let's try this to see if we have more luck.

USE [master]
GO
CREATE DATABASE [TestDB] ON 
( FILENAME = N'E:\MSSQL\TestDBCopy.mdf' )
 FOR ATTACH_REBUILD_LOG 
GO

We face the same error message telling us that the log of the database cannot be rebuilt.

Another Failed Attempt To Attach the Database.

At this point we tried everything, but there are two methods we can use to recover the database, and I will cover both. The first method requires the usage of an undocumented command in the CREATE DATABASE statement. As you may know, the use of undocumented statements is not supported by Microsoft, so if something goes wrong you can't contact them. The other method is trickier, but does not use undocumented features.

The Undocumented ATTACH_FORCE_REBUILD_LOG Command

By now we know that if we use the CREATE DATABASE..FOR ATTACH statement to recover the database it will fail because we do not have the transaction log file. Also, since there were open transactions in the database, we cannot use the ATTACH_ REBUILD_LOG command. There is an undocumented ATTACH_FORCE_REBUILD_LOG Command that as its name suggests, forces the CREATE DATABASE..FOR ATTACH statement to recover the database even when there were orphaned opened transactions. Basically, it creates a new log file.

USE master;

CREATE DATABASE [TestDB]
    ON  ( FILENAME = N'E:\MSSQL\TestDB_1.mdf' )
    FOR ATTACH_FORCE_REBUILD_LOG;
GO

In the next image we can see the execution of the previous command.

The Database was recovered successfully.

Attaching the Damaged SQL Server Database Without Using Undocumented Features

The first step is to create a new database.

USE [master]
GO

CREATE DATABASE [TestDB_Repair]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'TestDB_Repair_file1', 
			FILENAME = N'E:\MSSQL\TestDB_Repair_1.mdf',
			SIZE = 8MB , 
			MAXSIZE = UNLIMITED, 
			FILEGROWTH = 64MB) 
 LOG ON 
( NAME = N'TestDB_Repair_log_file1',
			 FILENAME = N'E:\MSSQL\TestDB_Repair_1.ldf',
			 SIZE = 8MB,
			 MAXSIZE = 2048GB,
			 FILEGROWTH = 32MB)
GO

Now we set the database offline.

USE master
GO

ALTER DATABASE [TestDB_Repair] SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

At this point we can change the file location of our new database to point to our orphaned mdf file and set the location of the log file to a non-existent file.

USE master
GO

ALTER DATABASE [TestDB_Repair] MODIFY FILE(NAME='TestDB_Repair_file1', FILENAME= 'E:\MSSQL\TestDBCopy.mdf')
ALTER DATABASE [TestDB_Repair] MODIFY FILE(NAME='TestDB_Repair_log_file1', FILENAME= 'E:\MSSQL\TestDBCopy.ldf')
GO

Let's bring the database back online.

USE master
GO

ALTER DATABASE [TestDB_Repair] SET ONLINE
GO

We do not have to be SQL Server gurus to know that the previous script will fail. But if you take a look at the error message of the next screen capture you will see that when SQL Server does not find the transaction log file (remember that we changed the system catalog to point to a file that does not exist) it tries to rebuild it. And of course, its attempt to rebuild the log fails with the same error message we had while trying to attach our orphaned *.mdf file, only in this case the *.mdf was successfully attached leaving us one step closer to our objective.

Bringing the Database Online.

Rebuilding the SQL Server Transaction Log

Now you will see that it is not very complicated to rebuild the SQL Server transaction log, but you must accept the fact that you will lose data. In fact, you should use this method to recover a damaged database if restoring the database from a backup is not possible. The reason behind this is that you can lose data other than the last user activity. For example, if a transaction was updating an index and the update operation performed a page split, you may lose the previously committed transactions that were no longer in the transaction log because page splits are a logged operation.

The next script includes several commands that I put together to bring our sample database back online. Further on I will explain the commands and why I decided to execute all of them in a single script, but first let's take a look.

USE master
GO

DBCC TRACEON(3604)
GO

ALTER DATABASE TestDB_Repair SET EMERGENCY
GO

ALTER DATABASE TestDB_Repair SET SINGLE_USER
GO

DBCC CHECKDB('TestDB_Repair', REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS
GO

ALTER DATABASE TestDB_Repair SET MULTI_USER
GO

The first step in the previous script is to send all output from the DBCC commands to the query results instead of to the error log. The next two steps set the database to emergency mode and single user mode respectively, so we can execute DBCC CHECKDB with the REPAIR_ALLOW_DATA_LOSS option. Finally, the last command is to bring the database back to multi user mode.

In the next image you can see a screen capture of the execution of the previous script. I marked in red one of the output messages which states that the error log has been rebuilt.

CheckDB Execution.
Next Steps


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Daniel Farina Daniel Farina was born in Buenos Aires, Argentina. Self-educated, since childhood he showed a passion for learning.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips



Comments For This Article




Tuesday, May 31, 2022 - 6:54:04 PM - Mebtu Abebe Back To Top (90128)
Great contribution. The undocumented command saved my business today.

Thursday, March 24, 2022 - 1:39:30 AM - raze Back To Top (89922)
What a life saver information!

Monday, June 21, 2021 - 11:38:41 PM - prashant Back To Top (88882)
"FOR ATTACH_FORCE_REBUILD_LOG;"
You are the best! This single line was what I was missing. Thanks mate.

Wednesday, December 30, 2020 - 4:03:13 AM - Jörg Back To Top (87977)
... you saved my life ;) - many thx & greets to Argentina

Friday, May 8, 2020 - 6:17:20 AM - Ajeet Singh Back To Top (85602)

This is a good exercise  bbut at the end we see that transactional file is rebuild 

. transactional consistancy is lost. 

so if we cant have a consistent data transaction why anyone would do all this hec of a thing where we have a database of size spanning to TBs.

Let me know your thoughts


Wednesday, February 12, 2020 - 5:23:39 PM - David Orr Back To Top (84398)

Thanks Daniel. I have just had to use your method to restore a databse that had no LDF file, and it worked perfectly. You have saved me some major headaches.


Thursday, February 6, 2020 - 3:35:42 PM - Peter Klosky Back To Top (84227)

Or we can simply force to create a ldf by using 'ATTACH_FORCE_REBUILD_LOG' as below

USE [master]
GO
CREATE DATABASE [TestDB] ON
( FILENAME = N'E:\MSSQL\TestDBCopy.mdf' )
FOR ATTACH_FORCE_REBUILD_LOG

GO

Thursday, September 19, 2019 - 6:43:22 AM - fabien Back To Top (82507)

Merci beaucoup
Thank you so much


Monday, July 1, 2019 - 9:57:08 AM - Manoj Back To Top (81650)

Great explaination. Really helpful....

Thank you so much sir...

This comment helped me also....Thanks Ross too

"Note that the path of the original LDF file must exist. For example, if it was D:\SQL\DATA on the original server, you must have a D:\SQL\DATA path on the recovery server. Otherwise the DBCC CHECKDB step will fail."


Tuesday, May 21, 2019 - 10:27:32 PM - Ayman Malkawi Back To Top (80150)

Question please: which way is better in deploying application c# with database  sql server, to attach mdf file to the client computer or to execute the sql script in deploying a software ? Your help is highly appreciated.


Tuesday, May 21, 2019 - 10:24:20 PM - Ayman Malkawi Back To Top (80149)

Welldone man... thanks :)


Tuesday, October 16, 2018 - 9:58:03 PM - Darren Back To Top (77965)

 Wow dude! This seriously saved me!! Thank you so much!!

 


Thursday, October 4, 2018 - 1:38:18 PM - Allen Back To Top (77847)

 Thanks.  DPM restored the .mdf and .ldf with transactions in flight. 
Also - had to change security for the files so MSSQLSERVER could use the files. 


Monday, August 20, 2018 - 11:09:12 AM - John Smith Back To Top (77245)

Excellent guide, got us out of a really sticky situation where the log file in a backup was corrupted/too large to restore.

Thanks!


Thursday, July 12, 2018 - 6:19:33 AM - Tajudeen Back To Top (76621)

Hi,

I tried the steps that you have mentioned. 

I am receiving the below error after executing the command

"

  DBCC CHECKDB('TestDB_Repair', REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS

  GO

"

error msg:

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.

No luck for me. It will be very helpful if you provide any lead on this issue.

Thanks in advance.


Wednesday, March 14, 2018 - 2:08:53 PM - Divya Back To Top (75418)

 Thank you so much this post saved my life!!!

 


Thursday, January 25, 2018 - 6:20:22 PM - Ryan Back To Top (75039)

Wow, this worked for me.  I really appreciate it.

Not sure if it should have mattered, but for attaching a MDF with missing LDF.  I had to put the file at the same local path as the original computer initially.  Such as "Program Files" vs "Program Files(x86)".  Both were 32-bit SQL 2012.

Thank you!

-Ryan 


Sunday, December 17, 2017 - 4:32:31 AM - Oleg Kovalev Back To Top (74176)

Thank you !


Wednesday, November 15, 2017 - 2:43:17 PM - Gabriel Uribe Back To Top (69785)

Thank you, great tip


Friday, November 3, 2017 - 6:34:03 PM - João Paulo Back To Top (69169)

Hello Daniel, thank you a lot, you saved my life =)


Tuesday, September 26, 2017 - 2:57:05 PM - Sunil Choudhary Back To Top (66630)

 

 Thanks allot you save my life.. :)


Wednesday, September 20, 2017 - 6:59:54 AM - Shivanand Koli Back To Top (66443)

Thnx a lot  

 


Wednesday, May 24, 2017 - 7:55:27 AM - Ragav Back To Top (56000)

Or we can simply force to create a ldf by using 'ATTACH_FORCE_REBUILD_LOG' as below

 

USE [master]
GO
CREATE DATABASE [TestDB] ON 
( FILENAME = N'E:\MSSQL\TestDBCopy.mdf' )
 FOR ATTACH_FORCE_REBUILD_LOG  

GO 

 

 


Sunday, April 30, 2017 - 11:21:59 AM - Dennis Back To Top (55324)

These detailed steps helped me when I lost any hope!

 Thank you very much, Daniel!!

 


Thursday, January 5, 2017 - 9:38:29 AM - YMO Back To Top (45142)

 This is awesome, thank you!!! It help me attached the databases I thought it's not possible to attchach again. 

 


Sunday, October 23, 2016 - 12:52:51 PM - MT Back To Top (43616)

This tip has helped me restore our client database. Thank you so much for publishing such a wonderful step-by-step approach!


Friday, September 16, 2016 - 2:02:59 AM - Jyoti Varma Back To Top (43341)

Thanks Daniel, your detailed steps made me recover my corrupted database which was down since 3 weeks. Your instructions and errors described in each steps helped me understand each step.

 


Friday, July 29, 2016 - 2:39:38 PM - TF Back To Top (43009)

 Thank you very much for putting this together.  Worked perfectly!

 


Wednesday, April 20, 2016 - 6:44:13 AM - Dar Back To Top (41278)

Brilliant


Friday, March 25, 2016 - 4:26:45 PM - Ross Presser Back To Top (41062)

Note that the path of the original LDF file must exist. For example, if it was D:\SQL\DATA on the original server, you must have a D:\SQL\DATA path on the recovery server. Otherwise the DBCC CHECKDB step will fail.  

 


Wednesday, February 24, 2016 - 3:50:49 AM - sepehr Back To Top (40770)

thank you soooo much sir,

in the last step I receive the  error below:

'DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Msg 5180, Level 22, State 1, Line 7

Could not open File Control Block (FCB) for invalid file ID 3 in database 'TestDB_Repair'. Verify the file location. Execute DBCC CHECKDB.'

 

would you mind helping me again please?

thanks in advance


Monday, February 22, 2016 - 7:01:38 AM - Arvind Back To Top (40743)

 Thank you very much for this post. really helped save hours of my time. 


Wednesday, February 3, 2016 - 10:09:43 PM - Vivien Back To Top (40586)

 This article helped me a lot. Thank you for the time and effort you put into creating this. Very much appreciated. Really great and detailed. Thanks!!!

 


Friday, November 6, 2015 - 12:24:54 PM - Ariel Back To Top (39036)

Este genial artículo me acaba de salvar de un buen problema. Muchas gracias.


Wednesday, September 16, 2015 - 8:27:11 AM - Andreas Back To Top (38691)

Hi,

thanks for this tip, I think it safed my life. I try 3 days to restore a database. And with your tips, everything works fine.

Thanks a lot

Best regards,

Andreas


Friday, May 1, 2015 - 5:35:54 AM - Stephen Back To Top (37079)

Welcome Greg


Wednesday, April 29, 2015 - 6:51:35 AM - Greg Robidoux Back To Top (37062)

Stephen, thanks for letting us know the tip was copied onto another site.

-Greg Robidoux


Wednesday, April 29, 2015 - 12:52:59 AM - Stephen Back To Top (37058)

This post is also at MSDN blog.

http://blogs.msdn.com/b/sql/archive/2015/04/23/how-to-attach-a-sql-server-database-without-a-transaction-log-and-with-open-transactions.aspx?CommentPosted=true#commentmessage

 


Thursday, April 23, 2015 - 4:00:58 PM - Jan Back To Top (37014)

You da man!


Thursday, April 23, 2015 - 9:54:03 AM - Jeff Back To Top (37009)
This is a great article and I will keep it as part of my disaster recovery plan and knowledge

Thank you very much

Thursday, April 23, 2015 - 1:03:10 AM - Patrick Flynn Back To Top (37002)

This tip is a specific case of a more general technique that was covered in
http://www.sqlskills.com/blogs/paul/disaster-recovery-101-hack-attach-a-damaged-database/

 

This covers the risks involved in this procedure in more detail















get free sql tips
agree to terms