jueves, 7 de julio de 2011

Restore de FILESTREAM

El filestream es una funcionalidad nueva del SQL2008 que a veces es discutida pero a mi ver es muy buena en muchos casos. En esta oportunidad me gustaría hablar sobre un caso interesante y es como hacer para restorear una base que tiene campos filestream pero que no ha sido diseñado pensando en esto. ¿A que me refiero? Uno puede diseñar la base desde un principio alojando las tablas que contienen archivos en filegroups diferentes para asegurarse que en un restore parcial no afecten, pero no siempre las cosas nacen en este orden, muchas veces las aplicaciones vienen de hace tiempo y "llegan" al sql 2008 y en la tabla que se encuentra el binario tambien se encuentra otra información indispensable para el funcionamiento del sisetema. En estos casos no restorear el filegroup en cuestión es lo mismo que no restorear nada. Para estos casos el filestream es una buena solución visto que en cierto modo puedo hacer un filegroup "vertical".
Supongamos una tabla "cliente" que tenga los campos id, nombre, apellido, Documento, siendo el último un VARBINARY(MAX). Si esta tabla la pongo en un filegroup diferente y hago un restore del resto obtendría error al realizar la siguiente consulta:

SELECT id, nombre, apellido FROM Cliente


Restore con PARTIAL

Ahora supongamos que mi campo base tiene definido FILESTREAM y el campo Documento se encuentra albergado de esa forma. En este caso ante un problema por el cual deseo recuperar mi base podría hacer lo siguiente:

RESTORE DATABASE [AIELLO_DBA]
FROM DISK = N'D:\Prueba_fs.bak'
WITH REPLACE, PARTIAL, RECOVERY


Y ahora la consulta antes mencionada funcionaría sin problemas, solamente obtendría un error si intento acceder al campo documento, como sería con la siguiente consulta:

SELECT id, nombre, apellido, Documento FROM Cliente

Msg 670, Level 16, State 1, Line 2
Large object (LOB) data for table "dbo.Cliente" resides on an offline filegroup ("AIELLO_DBA_FS") that cannot be accessed.

Lo que logré es poner mi base en linea en un tiempo mucho menor. Pero lamentablemente para recuperar todo debo volver a hacer el restore full en otro momento.


Restore operativo por partes
No todo está perdido!! como dice el dicho, hecha la ley hecha la trampa, entonces lo que hice es lo siguiente.

En mi backup nocturno hago lo siguiente:

-- =============================================
-- Author: Andrés Aiello
-- Create date: 07/07/2011
-- Backup full poniendo readonly el filestream
-- =============================================

ALTER DATABASE [AIELLO_DBA] MODIFY FILEGROUP [AIELLO_DBA_FS] READONLY
BACKUP DATABASE [AIELLO_DBA]
TO DISK = N'D:\Prueba_fs_readonly.bak'
WITH NOFORMAT, NOINIT, NAME = N'PRUEBA FS', SKIP, NOREWIND, NOUNLOAD, STATS = 10
ALTER DATABASE [AIELLO_DBA] MODIFY FILEGROUP [AIELLO_DBA_FS] READWRITE


Por lo tanto el filegroup de los documentos es guardado como readonly. Al momento de hacer restore lo puedo hacer de dos formas:

--============== MODO 1 - Full
-- 7:38 min

RESTORE DATABASE [AIELLO_DBA]
FROM DISK = N'D:\Prueba_fs_readonly.bak'
WITH REPLACE, RECOVERY
ALTER DATABASE [AIELLO_DBA] MODIFY FILEGROUP [AIELLO_DBA_FS] READWRITE


Esta forma hace un restore completo de la forma tradicional, dejando el servicio bajo el tiempo que dure el restore (en una base donde el mayor porcentaje del espacio son archivos esto puede crecer mucho).
Y el plan b...

-- =============================================
-- Author: Andrés Aiello
-- Create date: 07/07/2011
-- Restore inteligente
-- =============================================
--============== MODO 2 - Sin los binarios
-- 0:46 
RESTORE DATABASE [AIELLO_DBA]
FROM DISK = N'D:\Prueba_fs_readonly.bak'
WITH REPLACE, PARTIAL, RECOVERY
ALTER DATABASE [AIELLO_DBA] SET RECOVERY FULL WITH NO_WAIT
-- Base online sin los binarios!!!
-- Recuperar todo...
-- 8:30
RESTORE DATABASE [AIELLO_DBA]
FILEGROUP='AIELLO_DBA_FS'
FROM DISK = N'D:\Prueba_fs_readonly.bak'
WITH REPLACE, RECOVERY
ALTER DATABASE [AIELLO_DBA] MODIFY FILEGROUP [AIELLO_DBA_FS] READWRITE
De esta forma la base en solo 45 segundos se encuentra operativa!!! y mientras se va utilizando se va recuperando en background los documentos del otro filegroup. Para evitar inconsistencias mientras se recupera esa parte el filegroup se mantiene en readonly.
Andrés