Database
 sql >> Base de Dados >  >> RDS >> Database

Corrigindo a perda de dados usando o envio de logs com recuperação atrasada

Introdução


O envio de logs de transações é uma tecnologia muito conhecida usada no SQL Server para manter uma cópia do banco de dados ativo no site de recuperação de desastres. A tecnologia depende de três tarefas principais:a tarefa de backup, a tarefa de cópia e a tarefa de restauração. Enquanto a tarefa de backup é executada no servidor principal, as tarefas de cópia e restauração são executadas no servidor secundário. Essencialmente, o processo envolve backups periódicos do log de transações para um compartilhamento do qual o trabalho de cópia é movido para o servidor secundário; posteriormente, a tarefa de restauração aplica os backups de log ao servidor secundário. Antes de tudo isso começar, o Banco de Dados Secundário deve ser inicializado com um backup completo do servidor Primário restaurado com a opção NORECOVERY.



A Microsoft fornece um conjunto de procedimentos armazenados que podem ser usados ​​para configurar o Log Shipping de ponta a ponta, bem como equivalentes de GUI a partir do item de propriedades de cada banco de dados para o qual você deseja configurar o Log Shipping. Vale ressaltar que o Banco de Dados Secundário pode ser configurado no modo NORECOVERY ou no modo STANDBY. No modo NORECOVERY, o banco de dados nunca está disponível para consultas, mas no modo STANDBY, o banco de dados secundário pode ser consultado quando nenhuma operação de restauração do log de transações estiver em andamento.

Configurando o ambiente


Para dar o pontapé inicial, criamos duas instâncias do SQL Server na AWS com uma imagem idêntica do Amazon EC2. Esta instância do Amazon EC2 está executando o SQL Server 2017 RTM-CU5 no Windows Server 2016. Em seguida, restauramos uma cópia do banco de dados WideWorldImporters usando um conjunto de backup adquirido do GitHub para a primeira instância, nossa instância primária. Usamos o mesmo conjunto de backup para criar dois bancos de dados idênticos chamados BranchDB e CorporateDB.


Fig. 1 Versão do SQL Server




Fig. 2 BranchDB e CorporateDB na instância primária (instância secundária em branco)


Lista 1:Restaurando o banco de dados de amostra WideWorldImporters

restore filelistonly from disk='WideWorldImporters-Full.bak'

restore database CorporateDB from disk='WideWorldImporters-Full.bak' with stats=10,recovery,

move 'WWI_Primary' to 'M:\MSSQL\Data\WWI_Primary.mdf' , move 'WWI_UserData' to 'M:\MSSQL\Data\WWI_UserData.ndf' , move 'WWI_Log' to 'N:\MSSQL\Log\WWI_Log.ldf',

move 'WWI_InMemory_Data_1' to 'M:\MSSQL\Data\WWI_InMemory_Data_1.ndf'

restore database BranchDB from disk='WideWorldImporters-Full.bak' with stats=10,recovery,

move 'WWI_Primary' to 'M:\MSSQL\Data\WWI_Primary1.mdf' , move 'WWI_UserData' to 'M:\MSSQL\Data\WWI_UserData1.ndf' , move 'WWI_Log' to 'N:\MSSQL\Log\WWI_Log1.ldf',

move 'WWI_InMemory_Data_1' to 'M:\MSSQL\Data\WWI_InMemory_Data_11.ndf

Agora temos duas instâncias, a Instância Primária que hospeda os dois bancos de dados Primários (BranchDB e CorporateDB e a instância Secundária sem bancos de dados de usuário. Continuamos com a configuração de Envio de Log de Transação em ambos os bancos de dados, mas os diferenciamos aplicando um atraso à configuração de restauração do primeiro banco de dados. Lembre-se que os bancos de dados são realmente idênticos em termos de dados que contêm. Os gráficos a seguir mostram as principais opções selecionadas na configuração de envio de logs.


Fig. 3 Configurações de backup para BranchDB




Fig. 4 Copiar configurações para BranchDB




Fig. 5 Restaurar configurações para BranchDB

Cada trabalho de envio de log é configurado para ser executado a cada cinco minutos. Para processar “Delay Restoring Backups”, devemos usar o modo Standby Recovery na configuração de Log Shipping. É lógico, pois tem o Banco de Dados Secundário em modo de espera e indica que podemos consultar o Banco de Dados Secundário sempre que uma Restauração do Log de Transação não estiver em andamento. O valor que especificamos nesta opção (30 minutos neste caso) nos dá uma boa janela durante a qual podemos executar relatórios do Banco de Dados Secundário, além do requisito principal deste artigo, que é ser capaz de se recuperar de um erro do usuário.

Além disso, devemos mencionar que a restauração dos backups do log de transações está realmente atrasada. Seu carimbo de data/hora é posterior ao valor de atraso. Isso significa que todos os backups de log de transações serão copiados para o servidor secundário, que é baseado no agendamento e especificado na tarefa de cópia. Na verdade, a tarefa de restauração ainda será executada conforme a programação, mas os backups de log de transações (com menos de 30 minutos) não serão restaurados. Em essência, o banco de dados BranchDB Standby está 30 minutos atrás do banco de dados principal BranchDB. Para demonstrar essa defasagem, na próxima seção, criaremos uma tabela nos dois bancos de dados e criaremos um trabalho que insere um registro a cada minuto. Examinaremos esta tabela nas Bases de Dados Secundárias.

As configurações para o banco de dados CorporateDB são as mesmas das Figs. 3 a 5, exceto para o trabalho de restauração que NÃO está definido para atrasar os backups do log de transações.


Fig. 6 Restaurar configurações para CorporateDB


Verificando a configuração


Feita a configuração, podemos verificar se a configuração está OK e começar a observar o seu funcionamento. O relatório de envio do log de transações nos mostra que o banco de dados da filial está realmente atrasado em relação ao CorporateDB em termos de restaurações:


Fig. 7a Relatório de envio de log de transações no servidor principal




Fig. 7b Relatório de envio de log de transações no servidor secundário

Além disso, você notará a mensagem abaixo no histórico de tarefas de restauração para o BranchDB:




Fig. 8 Restaurações de log de transações ignoradas no servidor secundário



Podemos ir mais longe com essa verificação criando uma tabela e usando um trabalho para preencher essa tabela com linhas a cada minuto. O trabalho é uma maneira simples de simular o que um aplicativo pode estar fazendo em uma tabela de usuário. Isso pode nos mostrar que esse atraso é definitivamente mostrado nos dados do usuário.


Lista 2 – Criar tabela de rastreamento de log

use BranchDB

go

create table log_ship_tracker

( ID int identity (100,1)

,Database_Name sysname default db_name()

,RecordTime datetime default getdate()

,ServerName sysname default @@servername)



use CorporateDB

go

create table log_ship_tracker

( ID int identity (100,1)

,Database_Name sysname default db_name()

,RecordTime datetime default getdate()

,ServerName sysname default @@servername)

Lista 3 – Criar trabalho para preencher a tabela do rastreador de log

/* ==Scripting Parameters==

Source Server Version : SQL Server 2017 (14.0.3023)
Source Database Engine Edition : Microsoft SQL Server Standard Edition
Source Database Engine Type : Standalone SQL Server

Target Server Version : SQL Server 2017

Target Database Engine Edition : Microsoft SQL Server Standard Edition
Target Database Engine Type : Standalone SQL Server
*/

USE [msdb]

GO

/****** Object: Job [InsertRecords] Script Date: 7/2/2018 3:32:00 PM ******/

BEGIN TRANSACTION

DECLARE @ReturnCode INT

SELECT @ReturnCode = 0

/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 7/2/2018 3:32:00 PM ******/

IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)

BEGIN

EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)

EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'InsertRecords', @enabled=1,

@notify_level_eventlog=0,

@notify_level_email=0,

@notify_level_netsend=0,

@notify_level_page=0,

@delete_level=0,

@description=N'No description available.',

@category_name=N'[Uncategorized (Local)]',

@owner_login_name=N'kairos\kigiri', @job_id = @jobId OUTPUT

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

/****** Object: Step [InsertRecords] Script Date: 7/2/2018 3:32:00 PM ******/

EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected],

@step_name=N'InsertRecords',

@step_id=1,

@cmdexec_success_code=0,

@on_success_action=1,

@on_success_step_id=0,

@on_fail_action=2,

@on_fail_step_id=0,

@retry_attempts=0,

@retry_interval=0,

@os_run_priority=0, @subsystem=N'TSQL',

@command=N'use BranchDB

go

insert into

log_ship_tracker

values

(db_name(),getdate(),@@servername)



use CorporateDB

go

insert into

log_ship_tracker

values

(db_name(),getdate(),@@servername)

GO',

@database_name=N'master',

@flags=0

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @[email protected], @name=N'Schedule', @enabled=1,

@freq_type=4,

@freq_interval=1,

@freq_subday_type=4,

@freq_subday_interval=1,

@freq_relative_interval=0,

@freq_recurrence_factor=0,

@active_start_date=20180702,

@active_end_date=99991231,

@active_start_time=0,

@active_end_time=235959,

@schedule_uid=N'03e5f1b2-2e0b-4b30-8d60-3643c84aa08d' IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

COMMIT TRANSACTION

GOTO EndSave

QuitWithRollback:

IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION

EndSave:

GO



Quando consultamos a tabela nos Bancos de Dados Primários, respectivamente, podemos confirmar (usando a coluna RecordTime) que as linhas correspondem em BranchDB e CorporateDB. Quando examinamos a tabela nos Bancos de Dados Secundários, da mesma forma, vemos claramente que temos um intervalo de 30 minutos entre BranchDB e CorporateDB.

Listagem 4 – Como consultar a tabela do rastreador de registros

select top 10 @@servername [Current_Server],* from BranchDB.dbo.log_ship_tracker order by RecordTime desc

select top 10 @@servername [Current_Server], * from CorporateDB.dbo.log_ship_tracker order by RecordTime desc




Fig. 9 correspondências de tabelas do rastreador de registros em bancos de dados primários




Fig. 10 tabelas do rastreador de logs têm um intervalo de aproximadamente 30 minutos em bancos de dados secundários


Recuperando do erro do usuário


Agora vamos falar sobre o principal benefício desse atraso. No cenário em que um usuário descarta inadvertidamente uma tabela, podemos recuperar os dados rapidamente do Banco de Dados Secundário, desde que o período de atraso não tenha decorrido. Neste exemplo, descartamos a tabela Sales.Orderlines em AMBOS os bancos de dados e verificamos se a tabela não existe mais em AMBOS os bancos de dados.

Lista 5 – Tabela de Descarte de Linhas de Pedido

drop table BranchDB.Sales.Orderlines

drop table CorporateDB.Sales.Orderlines

GO



use BranchDB

go

select

@@servername [Current_Server]

, db_name() [Database_Name]

, name

, schema_name(schema_id) [schema]

, type_desc

, create_date

, modify_date

from sys.tables where name='Orderlines'

GO



use CorporateDB

go

select

@@servername [Current_Server]

, db_name() [Database_Name]

, name

, schema_name(schema_id) [schema]

, type_desc

, create_date

, modify_date

from sys.tables where name='Orderlines'

GO




Fig. 11 Queda de Vendas de Mesa. Linhas de Pedido



Quando procuramos a tabela no Servidor Secundário, descobrimos que a tabela ainda está disponível em AMBOS os bancos de dados. Assim, para o CorporateDB temos menos de cinco minutos para recuperar os dados. (Fig. 12). Mas uma vez que o próximo ciclo de restauração é executado, perdemos a tabela no banco de dados Corporate DB. Para recuperar essa tabela, precisamos fazer uma recuperação pontual usando um backup completo em um ambiente separado e, em seguida, extrair essa tabela específica. Você vai concordar que vai levar algum tempo. Para a tabela BranchDB Orderlines, temos um pouco mais de tempo e podemos recuperar a tabela com uma única instrução SQL em um servidor vinculado (consulte a Listagem 6).


Fig. Contagem regressiva de 12 minutos:a tabela existe em ambos os bancos de dados secundários




Fig. 13 25 minutos adicionais para recuperar a tabela BranchDB


Listagem 6 – Tabela de Recuperação de Pedidos

USE [master]

GO

/****** Object: LinkedServer [10.2.1.84] Script Date: 7/2/2018 4:14:59 PM ******/

EXEC master.dbo.sp_addlinkedserver @server = N'10.2.1.84', @srvproduct=N'SQL Server'

/* For security reasons the linked server remote logins password is changed with ######## */

EXEC master.dbo.sp_addlinkedsrvlogin

@rmtsrvname=N'10.2.1.84',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpasswo rd=NULL

GO

select * into BranchDB.Sales.Orderlines from [10.2.1.84].BranchDB.Sales.Orderlines




Fig. 14 Recupere a tabela BranchDB Sales.Orderlines

Em seguida, verificamos no Servidor Principal (Banco de Dados BranchDB) que a tabela foi restaurada.


Fig. 15 Recupere a tabela BranchDB Sales.Orderlines

Conclusão


O SQL Server oferece várias maneiras de se recuperar da perda de dados de uma variedade de causas principais – falha de disco, corrupção, erro do usuário etc. A recuperação pontual de backups é provavelmente o mais conhecido desses métodos. Para certos casos simples de erro do usuário ou caso semelhante, onde um ou dois objetos são perdidos, o uso do Transaction Log Shipping com Recuperação Atrasada é uma boa abordagem a ser considerada. No entanto, deve-se observar que um banco de dados secundário, configurado estritamente para necessidades de DR, deve ser selecionado para RPOs mais baixos.