In the past, I have written about attaching data files to a SQL Server instance when log files are missing by the use of the FOR ATTACH_REBUILD_LOG clause of the CREATE DATABASE statement. Recently, I was referring the CREATE DATABASE documentation on MSDN. It’s a comprehensive document and and the following line for read-only databases caught my attention.
For a read-only database, the log cannot be rebuilt because the primary file cannot be updated. Therefore, when you attach a read-only database with a log that is unavailable, you must provide the log files, or the files in the FOR ATTACH clause.
This statement was contrary to what I had observed before. Hence, I decided to re-validate the findings via a demo.
The first step, of course is to create a database.
USE [master];
GO
CREATE DATABASE ReadOnlyDBForAttach
ON PRIMARY (NAME = ReadOnlyDBForAttach_Data,
FILENAME='C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_Data.mdf'),
FILEGROUP RODefault (NAME = ReadOnlyDBForAttach_RODefault,
FILENAME='C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_RODefault.mdf')
LOG ON (NAME = ReadOnlyDBForAttach_Log,
FILENAME='C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_Log.ldf');
GO
As can be seen from the script referenced above, the database we created as 2 data file groups, one is the default PRIMARY filegroup. Because we cannot make the PRIMARY filegroup READ_ONLY, we will be making the other filegroup (RODefault) READ_ONLY. To add complexity, we will also make it the default filegroup, i.e. any new objects created without specifying a filegroup, it will be created in the filegroup marked as default.
Finally, we will also mark the database as READ_ONLY.
USE [master];
GO
ALTER DATABASE ReadOnlyDBForAttach
MODIFY FILEGROUP [RODefault] DEFAULT;
GO
ALTER DATABASE ReadOnlyDBForAttach
MODIFY FILEGROUP [RODefault] READ_ONLY;
GO
ALTER DATABASE ReadOnlyDBForAttach SET READ_ONLY;
GO
Now, let us check out the database and filegroup properties.
USE ReadOnlyDBForAttach;
GO
SELECT 'Database Properties',
sd.[name],
sd.is_read_only,
sd.is_cleanly_shutdown
FROM sys.databases AS sd
WHERE sd.[name] = 'ReadOnlyDBForAttach';
SELECT 'File properties',
sdf.file_id,
sdf.type,
sdf.data_space_id,
sdf.type_desc,
sdf.name,
sdf.is_read_only,
sdf.is_media_read_only
FROM sys.database_files AS sdf;
GO
![Image showing database and database file properties for the read-only database - ReadOnlyDBForAttach]()
Read Only database and database file properties
Now, let us detach the database, and delete the log file. (NOTE: We are removing the log file for the purposes of this demo only. Please do not do this in your QA or production environments).
USE [master];
GO
EXEC sp_detach_db @dbname = 'ReadOnlyDBForAttach';
GO
![Image showing the log file physically removed from the file system]()
Read Only Database – Log File Removed
Finally, let us attach the database back to the SQL Server instance using the CREATE DATABASE…FOR ATTACH_REBUILD_LOG clause.
USE [master]
GO
CREATE DATABASE [ReadOnlyDBForAttach]
ON PRIMARY ( NAME = N'ReadOnlyDBForAttach_Data',
FILENAME = N'C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_Data.mdf')
FOR ATTACH_REBUILD_LOG
GO
File activation failure. The physical file name "C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_Log.ldf" may be incorrect.New log file 'C:\SQLData\MSSQL12.SQL2014\MSSQL\DATA\ReadOnlyDBForAttach_log.ldf' was created.
As can be seen from the message above, the log file was successfully created and the database was successfully attached to the SQL Server instance.
Let us cross-check the database and file properties again:
USE ReadOnlyDBForAttach;
GO
SELECT 'Database Properties',
sd.[name],
sd.is_read_only,
sd.is_cleanly_shutdown
FROM sys.databases AS sd
WHERE sd.[name] = 'ReadOnlyDBForAttach';
SELECT 'File properties',
sdf.file_id,
sdf.type,
sdf.data_space_id,
sdf.type_desc,
sdf.name,
sdf.is_read_only,
sdf.is_media_read_only
FROM sys.database_files AS sdf;
GO
![Read Only Database and Data File Properties After Attach showing that the database is no longer Read Only]()
Read Only Database and Data File Properties After Attach
Conclusion
- Contrary to the MSDN remark, a read-only database can be successfully attached to a SQL Server instance even when the log file does not exist by the use of CREATE DATABASE…FOR ATTACH_REBUILD_LOG
- A read-only database becomes a read/write database if it has been attached to the SQL Server using FOR ATTACH_REBUILD_LOG and the log file was rebuilt
My findings above do not agree with the MSDN remark. At the moment, I am inclined to believe that this is a bug in the documentation as I have found a couple of years ago as well (see references). Please do share your views on the same in the post comments.
References/Further Reading
- SQL Server Myth: Log files are removed when a database is made READ_ONLY [Link]
- Creating a database without the log backup file – Error Msg. 5120 [Link]
- CREATE DATABASE…ATTACH_REBUILD_LOG resets database recovery mode to SIMPLE [Link]
- Setting database to READ_ONLY does not change the file-group properties [Link]
- sp_attach_db v/s CREATE DATABASE FOR ATTACH – Number of files limitation; Msg. 8144 (Procedure has too many arguments specified) [Link]
- CREATE DATABASE [MSDN Documentation]
Until we meet next time,
Be courteous. Drive responsibly.
Filed under:
#SQLServer,
#TSQL,
Administration,
DBA,
Guidance,
Myths,
Tips![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()