Database
 sql >> Baza danych >  >> RDS >> Database

Naprawianie utraty danych za pomocą przesyłania dzienników z opóźnionym odzyskiwaniem

Wprowadzenie

Transaction Log Shipping to bardzo dobrze znana technologia wykorzystywana w SQL Server do utrzymywania kopii działającej bazy danych w witrynie Disaster Recovery Site. Technologia zależy od trzech kluczowych zadań:zadania kopii zapasowej, zadania kopiowania i zadania przywracania. Podczas gdy zadanie kopii zapasowej działa na serwerze głównym, zadania kopiowania i przywracania działają na serwerze dodatkowym. Zasadniczo proces obejmuje okresowe kopie zapasowe dziennika transakcji do udziału, z którego zadanie kopiowania jest przenoszone na serwer pomocniczy; następnie zadanie przywracania stosuje kopie zapasowe dziennika na serwerze pomocniczym. Zanim to wszystko się zacznie, dodatkowa baza danych musi zostać zainicjowana pełną kopią zapasową z serwera głównego przywróconą z opcją NORECOVERY.

Firma Microsoft udostępnia zestaw procedur składowanych, których można użyć do kompleksowego skonfigurowania przesyłania dzienników, a także odpowiedników GUI, zaczynając od elementu właściwości każdej bazy danych, dla której możesz chcieć skonfigurować przesyłanie dzienników. Warto zauważyć, że Secondary Database można skonfigurować w trybie NORECOVERY lub w trybie STANDBY. W trybie NORECOVERY baza danych nigdy nie jest dostępna dla zapytań, ale w trybie STANDBY, dodatkowa baza danych może być sprawdzana, gdy nie jest wykonywana żadna operacja przywracania dziennika transakcji.

Konfigurowanie środowiska

Aby nabrać tempa, tworzymy dwie instancje SQL Server na AWS z identycznym obrazem Amazon EC2. Ta instancja Amazon EC2 działa pod kontrolą SQL Server 2017 RTM-CU5 w systemie Windows Server 2016. Następnie przywracamy kopię bazy danych WideWorldImporters przy użyciu zestawu kopii zapasowych pobranego z GitHub do pierwszej instancji, naszej podstawowej instancji. Używamy tego samego zestawu kopii zapasowych do tworzenia dwóch identycznych baz danych o nazwach BranchDB i CorporateDB.

Rys. 1 wersja serwera SQL

Rys. 2 BranchDB i CorporateDB w instancji podstawowej (pusta instancja dodatkowa)

Listing 1:Przywracanie przykładowej bazy danych 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

Mamy teraz dwie instancje, podstawową instancję hostującą dwie podstawowe bazy danych (BranchDB i CorporateDB oraz drugą instancję bez baz danych użytkowników. Kontynuujemy konfigurowanie przesyłania dziennika transakcji w obu bazach danych, ale różnicujemy je, stosując opóźnienie do konfiguracji przywracania pierwszą bazę danych. Przypomnij sobie, że bazy danych są w rzeczywistości identyczne pod względem zawartych w nich danych. Poniższa grafika przedstawia kluczowe opcje wybrane w konfiguracji przesyłania dziennika.

Rys. 3 ustawienia kopii zapasowej dla BranchDB

Rys. 4 Kopiuj ustawienia dla BranchDB

Rys. 5 Przywróć ustawienia dla BranchDB

Każde zadanie Log Shipping jest skonfigurowane do uruchamiania co pięć minut. Aby przetworzyć „Opóźnione przywracanie kopii zapasowych”, musimy użyć trybu przywracania w trybie gotowości w konfiguracji Log Shipping. Jest to logiczne, ponieważ ma drugorzędną bazę danych w trybie gotowości i wskazuje, że możemy wysyłać zapytania do pomocniczej bazy danych, gdy przywracanie dziennika transakcji nie jest w toku. Wartość określona w tej opcji (w tym przypadku 30 minut) daje nam dobre okno, podczas którego możemy generować raporty z drugorzędnej bazy danych, oprócz podstawowego wymagania tego artykułu, czyli możliwości odzyskania po błędzie użytkownika.

Powinniśmy również wspomnieć, że przywracanie kopii zapasowych dziennika transakcji faktycznie jest opóźnione. Jego sygnatura czasowa jest późniejsza niż wartość opóźnienia. Oznacza to, że wszystkie kopie zapasowe dziennika transakcji zostaną skopiowane na serwer pomocniczy, który jest oparty na harmonogramie i określonym w zadaniu kopiowania. W rzeczywistości zadanie przywracania będzie nadal działać zgodnie z harmonogramem, ale kopie zapasowe dziennika transakcji (nie starsze niż 30 minut) nie zostaną przywrócone. Zasadniczo baza danych BranchDB w stanie gotowości jest 30 minut za podstawową bazą danych BranchDB. Aby zademonstrować to opóźnienie, w następnej sekcji stworzymy tabelę w obu bazach danych i stworzymy zadanie, które wstawia rekord co minutę. Zbadamy tę tabelę w drugorzędnych bazach danych.

Ustawienia bazy danych CorporateDB są takie same jak na rysunkach. 3 do 5, z wyjątkiem zadania przywracania, które NIE jest ustawione na opóźnienie tworzenia kopii zapasowych dziennika transakcji.

Rys. 6 Przywróć ustawienia dla CorporateDB

Weryfikacja konfiguracji

Po zakończeniu konfiguracji możemy sprawdzić, czy konfiguracja jest w porządku i rozpocząć obserwację jej pracy. Raport dotyczący wysyłki dziennika transakcji pokazuje nam, że Branch DB rzeczywiście opóźnia CorporateDB pod względem przywracania:

Rys. 7a Raport wysyłki dziennika transakcji na serwerze głównym

Rys. 7b Raport wysyłki dziennika transakcji na serwerze pomocniczym

Dodatkowo zauważysz poniższy komunikat w historii zadań przywracania dla BranchDB:

Rys. 8 przywracania pominiętych dzienników transakcji na serwerze pomocniczym

Możemy przejść dalej z tą weryfikacją, tworząc tabelę i używając zadania do zapełniania tej tabeli wierszami co minutę. Zadanie to prosty sposób na symulację tego, co aplikacja może robić z tabelą użytkowników. To może nam pokazać, że to opóźnienie jest zdecydowanie widoczne w danych użytkownika.

Listing 2 – Utwórz tabelę śledzenia dziennika

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)

Listing 3 – Utwórz zadanie w celu wypełnienia tabeli śledzenia dziennika

/* ==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

Gdy wysyłamy zapytanie do tabeli odpowiednio do podstawowych baz danych, możemy potwierdzić (za pomocą kolumny RecordTime), że wiersze są zgodne w BranchDB i CorporateDB. Kiedy badamy tabelę w drugorzędnych bazach danych, w ten sam sposób widzimy wyraźnie, że mamy 30-minutową przerwę między bazą danych BranchDB a bazą danych korporacji.

Listing 4 – Odpytywanie tabeli śledzenia dziennika

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

Rys. 9 tabel śledzenia dzienników pasuje do podstawowych baz danych

Rys. 10 tabel śledzenia dzienników ma około 30-minutową przerwę w drugorzędnych bazach danych

Przywracanie po błędzie użytkownika

Porozmawiajmy teraz o kluczowej korzyści tego opóźnienia. W scenariuszu, w którym użytkownik przypadkowo upuszcza tabelę, możemy szybko odzyskać dane z pomocniczej bazy danych, o ile nie upłynął okres opóźnienia. W tym przykładzie usuwamy tabelę Sales.Orderlines w OBU bazach danych i sprawdzamy, czy tabela nie istnieje już w OBU bazach danych.

Listing 5 – Porzucanie tabeli linii zamówień

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

Rys. 11 Dropping Table Sales.Orderlines

Kiedy szukamy tabeli na serwerze pomocniczym, stwierdzamy, że tabela jest nadal dostępna w OBU bazach danych. Tak więc w przypadku CorporateDB mamy mniej niż pięć minut na odzyskanie danych. (ryc. 12). Ale po wykonaniu kolejnego przywracania Cycle, tracimy tabelę w bazie danych Corporate DB. Aby odzyskać tę tabelę, musimy wykonać odzyskiwanie do określonego momentu przy użyciu pełnej kopii zapasowej w osobnym środowisku, a następnie wyodrębnić tę konkretną tabelę. Zgodzisz się, że zajmie to trochę czasu. W przypadku tabeli Linie zamówień BranchDB mamy trochę więcej czasu i możemy odzyskać tabelę za pomocą pojedynczej instrukcji SQL przez połączony serwer (patrz Listing 6).

Rys. Odliczanie 12 minut:tabela istnieje w obu drugorzędnych bazach danych

Rys. 13 dodatkowych 25 minut na odzyskanie tabeli BranchDB

Listing 6 – Odzyskaj tabelę linii zamówień

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

Rys. 14 Odzyskaj tabelę BranchDB Sales.Orderlines

Następnie weryfikujemy serwer główny (bazę danych BranchDB), czy tabela została przywrócona.

Rys. 15 Odzyskaj tabelę BranchDB Sales.Orderlines

Wniosek

SQL Server zapewnia wiele sposobów odzyskiwania danych po utracie danych z różnych przyczyn źródłowych – awarii dysku, uszkodzenia, błędu użytkownika itp. Odzyskiwanie do określonego momentu z kopii zapasowych jest prawdopodobnie najbardziej znaną z tych metod. W przypadku niektórych prostych przypadków błędu użytkownika lub podobnych przypadków, w których jeden lub dwa obiekty są tracone, dobrym rozwiązaniem jest użycie funkcji przesyłania dziennika transakcji z opóźnionym odzyskiwaniem. Należy jednak zauważyć, że dodatkowa baza danych, skonfigurowana wyłącznie na potrzeby DR, musi być wybrana dla niższych wartości RPO.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uszeregować wiersze w partycji w SQL?

  2. Wizualizacja danych w Microsoft Power BI

  3. Rozwiązania wyzwań generatora serii liczb – Część 3

  4. Tworzenie serwera połączonego ODBC bez konfigurowania źródła danych

  5. SQL, jak używać SELECT