Hi
I am not able to test the recovery of readonly filegroup from database file, without restoring it from backup, according to
this MS article.
In two code examples bellow I have created a database with three custom filegroups. Two of them I set as readonly, then I made appropriate backups. After setting the database offline (option 1) or detaching it (option 2) I started to restore it. Restoring
of the read/write filegroups worked, as well as restoring a readonly filegroup from the backup. However I was not able to recover the second readonly filegroup just from the database file, without using a backup. The error I got differed for option 1 and 2,
please see SQL code bellow.
The server is SQL Server 2017 Enterprise Edition, the database was in simple recovery mode.
What do I do wrong?
Thank you, Martin
Option 1: restore after setting database offline
use master
go
xp_cmdshell 'mkdir T:\MSSQL\READONLY_FG_TEST_DB' ;
go
CREATE DATABASE [READONLY_FG_TEST_DB]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'READONLY_FG_TEST_DB__PRIMARY', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__PRIMARY.mdf' , SIZE = 5MB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2018]
( NAME = N'READONLY_FG_TEST_DB__DATA_2018', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2018.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2019]
( NAME = N'READONLY_FG_TEST_DB__DATA_2019', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2019.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2020]
( NAME = N'READONLY_FG_TEST_DB__DATA_2020', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2020.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB )
LOG ON
( NAME = N'READONLY_FG_TEST_DB_log', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB_log.ldf' , SIZE = 512KB , MAXSIZE = UNLIMITED , FILEGROWTH = 512KB)
GO
ALTER DATABASE [READONLY_FG_TEST_DB] SET RECOVERY SIMPLE
go
ALTER DATABASE [READONLY_FG_TEST_DB] MODIFY FILEGROUP [FG_2018] READONLY;
GO
ALTER DATABASE [READONLY_FG_TEST_DB] MODIFY FILEGROUP [FG_2019] READONLY;
GO
--backup of readonly filegroup FG_2018
BACKUP DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2018'
TO DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__FG_2018.bak'
go
--readonly filegroup FG_2019 intentionally without backup, target is recovery without restore from undamaged db file
--backup of read/write filegroups
BACKUP DATABASE [READONLY_FG_TEST_DB]
READ_WRITE_FILEGROUPS
TO DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__RW.bak'
go
alter database READONLY_FG_TEST_DB
set restricted_user
with rollback immediate
go
alter database READONLY_FG_TEST_DB
set offline
go
--damage of files of read/write filegroups and one readonly filegroup FG_2018
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__PRIMARY.mdf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2018.ndf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2020.ndf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB_log.ldf' ;
go
--partially restore of read/wrire filegroups
RESTORE DATABASE [READONLY_FG_TEST_DB]
READ_WRITE_FILEGROUPS
FROM DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__RW.bak'
WITH
PARTIAL, RECOVERY
go
--restore of readonly filegroup FG_2018 from backup
RESTORE DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2018'
FROM DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__FG_2018.bak'
WITH RECOVERY
go
--recovery of readonly filegroup from undamaged db file, without restore from backup, according to (https://docs.microsoft.com/en-us/sql/relational-databases/backup-restore/example-piecemeal-restore-of-only-some-filegroups-simple-recovery-model?view=sql-server-ver15)
RESTORE DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2019'
WITH NORECOVERY
go
/*
Msg 5173, Level 16, State 1, Line 90
One or more files do not match the primary file of the database. If you are attempting to attach a database, retry the operation with the correct files. If this is an existing database, the file may be corrupted and should be restored from a backup.
Msg 3013, Level 16, State 1, Line 90
RESTORE DATABASE is terminating abnormally.
*/
Option 2: restore after detaching database
Please see that in this this option the error states that the file should be in RECOVERY_PENDING state, however it is exactly the case.
use master
go
xp_cmdshell 'mkdir T:\MSSQL\READONLY_FG_TEST_DB' ;
go
CREATE DATABASE [READONLY_FG_TEST_DB]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'READONLY_FG_TEST_DB__PRIMARY', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__PRIMARY.mdf' , SIZE = 5MB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2018]
( NAME = N'READONLY_FG_TEST_DB__DATA_2018', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2018.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2019]
( NAME = N'READONLY_FG_TEST_DB__DATA_2019', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2019.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB ),
FILEGROUP [FG_2020]
( NAME = N'READONLY_FG_TEST_DB__DATA_2020', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2020.ndf' , SIZE = 512KB , MAXSIZE = UNLIMITED, FILEGROWTH = 512KB )
LOG ON
( NAME = N'READONLY_FG_TEST_DB_log', FILENAME = N'T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB_log.ldf' , SIZE = 512KB , MAXSIZE = UNLIMITED , FILEGROWTH = 512KB)
GO
ALTER DATABASE [READONLY_FG_TEST_DB] SET RECOVERY SIMPLE
go
ALTER DATABASE [READONLY_FG_TEST_DB] MODIFY FILEGROUP [FG_2018] READONLY;
GO
ALTER DATABASE [READONLY_FG_TEST_DB] MODIFY FILEGROUP [FG_2019] READONLY;
GO
--backup of readonly filegroup FG_2018
BACKUP DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2018'
TO DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__FG_2018.bak'
go
--readonly filegroup FG_2019 intentionally without backup, target is recovery without restore from undamaged db file
--backup of read/write filegroups
BACKUP DATABASE [READONLY_FG_TEST_DB]
READ_WRITE_FILEGROUPS
TO DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__RW.bak'
go
alter database READONLY_FG_TEST_DB
set restricted_user
with rollback immediate
go
EXEC sp_detach_db 'READONLY_FG_TEST_DB', 'true';
go
--damage of files of read/write filegroups and one readonly filegroup FG_2018
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__PRIMARY.mdf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2018.ndf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB__DATA_2020.ndf' ;
go
xp_cmdshell 'del T:\MSSQL\READONLY_FG_TEST_DB\READONLY_FG_TEST_DB_log.ldf' ;
go
--partially restore of read/wrire filegroups
RESTORE DATABASE [READONLY_FG_TEST_DB]
READ_WRITE_FILEGROUPS
FROM DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__RW.bak'
WITH
PARTIAL, RECOVERY
go
--restore of readonly filegroup FG_2018 from backup
RESTORE DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2018'
FROM DISK = N'T:\MSSQL\READONLY_FG_TEST_DB\backup__READONLY_FG_TEST_DB__FG_2018.bak'
WITH RECOVERY
go
--recovery of readonly filegroup from undamaged db file, without restore from backup, according to (https://docs.microsoft.com/en-us/sql/relational-databases/backup-restore/example-piecemeal-restore-of-only-some-filegroups-simple-recovery-model?view=sql-server-ver15)
RESTORE DATABASE [READONLY_FG_TEST_DB]
FILEGROUP = 'FG_2019'
WITH NORECOVERY
go
/*
Msg 3149, Level 16, State 3, Line 89
The file or filegroup "FG_2019" is not in a valid state for the "Recover Data Only" option to be used. Only secondary files in the OFFLINE or RECOVERY_PENDING state can be processed.
Msg 3013, Level 16, State 1, Line 89
RESTORE DATABASE is terminating abnormally.
*/
select filegroup_name = substring(FG.name,1,10), FG.data_space_id, FG.is_read_only, file_name = substring(F.name,1,40), file_state_desc = substring(F.state_desc,1,20)
from READONLY_FG_TEST_DB.sys.filegroups FG join READONLY_FG_TEST_DB.sys.database_files F on F.data_space_id=FG.data_space_id
go
/*
filegroup_name data_space_id is_read_only file_name file_state_desc
-------------- ------------- ------------ ---------------------------------------- --------------------
PRIMARY 1 0 READONLY_FG_TEST_DB__PRIMARY ONLINE
FG_2018 2 1 READONLY_FG_TEST_DB__DATA_2018 ONLINE
FG_2019 3 1 READONLY_FG_TEST_DB__DATA_2019 RECOVERY_PENDING
FG_2020 4 0 READONLY_FG_TEST_DB__DATA_2020 ONLINE
*/