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

Zarządzanie replikacją MS SQL

Replikacja to jedna z najstarszych technologii na MS SQL Server, uwielbiana przez każdego administratora baz danych. Jest to świetna i niezawodna technologia przybliżania danych użytkownikom, zwłaszcza w przypadku raportowania rozproszonego. Dzięki temu dostępność bazy danych wzrasta w wielu serwerach SQL i regionach.

Replikacja została wprowadzona w SQL 2005. Czy możesz uwierzyć, że jest tak stara? Chociaż regularnie wprowadzane są nowsze zarządzane platformy SQL w chmurze, wierzę, że replikacja SQL pozostanie tutaj. Gdyby to był robak lub owad, pomyślałbym o nim jako o karaluchu. Trudno zmiażdżyć!

Jeśli należysz do małej populacji administratorów, którzy nigdy nie zarządzali bazą danych, istnieje oficjalna dokumentacja firmy Microsoft na ten temat. Pamiętaj jednak, że jest to dość długie, wyczerpujące i pozbawi Cię trochę czasu wolnego od wakacyjnych lub planowanych seriali telewizyjnych. Ponadto Codingsight oferuje przewodnik po instalacji i konfiguracji replikacji bazy danych SQL Server.

Ale zanim zabrudzisz ręce technicznymi rzeczami i wiem, że też jesteś chętny, ważne jest, aby to zaplanować.

Wymóg replikacji może ulec zmianie w odniesieniu do lokalizacji podczas wdrażania na serwerach SQL działających w chmurze. Ale kiedy replikacja SQL działa jak dobrze naoliwiona maszyna i replikuje dane produkcyjne, musisz zaplanować, jak nią zarządzać.

W tym poście podzielę się kilkoma wskazówkami i skryptami T-SQL, których możesz użyć, gdy musisz sprawdzić, czy wiele zadań agenta SQL jest tworzonych po skonfigurowaniu replikacji.

Monitoruj agenty replikacji

Podczas konfigurowania i konfigurowania replikacji SQL tworzy również zestaw autonomicznych funkcji i zadań agenta SQL, znanych jako agenci replikacji. Ich celem jest wykonywanie zadań związanych z przesuwaniem stołów, zwanych także artykułami , w konfiguracji replikacji od wydawcy do subskrybentów . Agenty replikacji można uruchamiać z wiersza poleceń i przez aplikacje korzystające z obiektów zarządzania replikacją (RMO).

Agenty replikacji SQL Server mogą być monitorowane i administrowane za pomocą Monitora replikacji i SQL Server Management Studio.

Podstawowym problemem administratora bazy danych/administratora replikacji jest upewnienie się, że wszystkie zadania replikacji agentów SQL są uruchomione. Jeśli zadanie agenta replikacji nie powiedzie się, subskrybent może nie otrzymać danych. Dlatego baza danych dystrybucji może się rozrosnąć z powodu nagromadzonych wierszy, które nie zostaną przeniesione do bazy danych subskrybentów.

Aby ustawić alert o niepowodzeniu zadania agenta replikacji, można utworzyć inne zadanie agenta. Sprawdzi niepowodzenia zadań i wyśle ​​wiadomość e-mail do zespołu dba, jeśli wykryje problemy.

Sprawdź nieudane zadania agenta replikacji

Użyj poniższego skryptu:

declare @time time 
set @time = dateadd(n,-30,getdate()) 
declare @date date 
set @date = convert(date,getdate()) 
declare @publisher varchar(100) 
set @publisher = @@SERVERNAME
SELECT LEFT(name,50) as [JobName], run_date AS [RunDate], run_time AS [RunTime], LEFT([message],50) AS [Message] 
FROM 
(select distinct b.name,a.run_date, run_time, message 
from msdb..sysjobhistory a inner join msdb..sysjobs b on a.job_id = b.job_id where b.name like 'servername here%' and run_status <> 1 and message like '%error%' 
and convert(date,convert(varchar,a.run_date ))= convert(date,getutcdate()) replace(convert(varchar(8),dateadd(n,-30,getutcdate())),':','') ) a 

Utwórz alert e-mail, aby powiadomić o niepowodzeniu pracy

Zastosuj następujący skrypt:

exec msdb.dbo.sp_send_dbmail 
@profile_name = 'DBA Alerts', 
@recipients = 'your dba team email here', 
@subject = '[Database name] Replication Jobs Failure', 
@query = 'SELECT LEFT(name,50) as [JobName], run_date AS [RunDate], run_time AS [RunTime], LEFT([message],50) AS [Message] 
FROM 
(select distinct b.name, a.run_date, a.run_time, message 
from msdb.dbo.sysjobhistory a inner join msdb.dbo.sysjobs b on a.job_id = b.job_id 
where b.name like ''servername here %'' and 
convert(date,convert(varchar,a.run_date)) = convert(date,getutcdate()) ) a 
', 
@attach_query_result_as_file = 0 ; 

Monitoruj tabelę zawierającą zreplikowane polecenia

Aby monitorować msrepl_commands tabeli, możesz użyć jeszcze jednego skryptu podanego poniżej. Zwróć uwagę, że ten stół powinien rosnąć za duży i za szybko. W takim przypadku zadania agenta replikacji mogą się nie powieść lub może wystąpić problem z konfiguracją replikacji.

Skrypt wygląda następująco:

use distribution 
SELECT Getdate() AS CaptureTime, LEFT(Object_name(t.object_id),20) AS TableName, st.row_count 
FROM sys.dm_db_partition_stats st WITH (nolock) 
INNER JOIN sys.tables t WITH (nolock) ON st.object_id = t.object_id INNER JOIN sys.schemas s WITH (nolock) ON t.schema_id = s.schema_id WHERE index_id < 2 AND Object_name(t.object_id) 
IN ('MSsubscriptions', 'MSdistribution_history', 'MSrepl_commands', 'MSrepl_transactions') 
ORDER BY st.row_count DESC

msrepl_commands trend wzrostu tabeli daje również wskazówkę, jak zdrowe jest opóźnienie replikacji. Istnieje wiele czynników wpływu. Jeśli Twoje środowisko znajduje się w chmurze, wybór regionu może mieć duży wpływ na opóźnienia replikacji.

Csporządź prosty raport na temat replikacji i wyślij go e-mailem

Możesz użyć następującego skryptu:

Declare @Publisher sysname, @PublisherDB sysname 
-- Set Publisher server and database name 
Set @Publisher = 'publication server name'; 
Set @PublisherDB = 'publishing database name'; 
-- Refresh replication monitor data 
USE [distribution] 
Exec sys.sp_replmonitorrefreshjob @iterations = 1; 
With MaxXact (ServerName, PublisherDBID, XactSeqNo) 
As (Select S.name, DA.publisher_database_id, max(H.xact_seqno) From dbo.MSdistribution_history H with(nolock) 
Inner Join dbo.MSdistribution_agents DA with(nolock) On DA.id = H.agent_id 
Inner Join master.sys.servers S with(nolock) On S.server_id = DA.subscriber_id 
Where DA.publisher_db = @PublisherDB 
Group By S.name, DA.publisher_database_id), OldestXact (ServerName, OldestEntryTime) 
As (Select MX.ServerName, Min(entry_time) 
From dbo.msrepl_transactions T with(nolock) 
Inner Join MaxXact MX On MX.XactSeqNo < T.xact_seqno And 
MX.PublisherDBID = T.publisher_database_id 
Group By MX.ServerName) 
Select [Replication Status] = Case MD.status 
When 1 Then 'Started' 
When 2 Then 'Succeeded' 
When 3 Then 'In progress' 
When 4 Then 'Idle' 
When 5 Then 'Retrying' 
When 6 Then 'Failed' 
End, 
Subscriber = SubString(MD.agent_name, Len(MD.publisher) + 
Len(MD.publisher_db) + Len(MD.publication) + 4, 
Charindex('-', MD.agent_name, 
Len(MD.publisher) + Len(MD.publisher_db) + 
Len(MD.publication) + 5) - 
(Len(MD.publisher) + 
Len(MD.publisher_db) + Len(MD.publication) + 4)), 
[Subscriber DB] = A.subscriber_db, 
[Publisher DB] = MD.publisher_db, 
Publisher = MD.publisher, 
[Current Latency (sec)] = MD.cur_latency,
[Current Latency (hh:mm:ss)] = Right('00' + Cast(MD.cur_latency/3600 As varchar), 2) + 
':' + Right('00' + 
Cast((MD.cur_latency%3600)/60 As varchar), 2) + 
':' + Right('00' + 
Cast(MD.cur_latency%60 As varchar), 2), 
[Latency Threshold (min)] = Cast(T.value As Int), 
[Agent Last Stopped (sec)] = DateDiff(hour, agentstoptime, getdate()) - 1, 
[Agent Last Sync] = MD.last_distsync, 
[Last Entry TimeStamp] = OX.OldestEntryTime 
From dbo.MSreplication_monitordata MD with(nolock) 
Inner Join dbo.MSdistribution_agents A with(nolock) On A.id = MD.agent_id Inner Join dbo.MSpublicationthresholds T with(nolock) On T.publication_id = MD.publication_id And T.metric_id = 2 -- Latency 
Inner Join OldestXact OX On OX.ServerName = SubString(MD.agent_name, Len(MD.publisher) + Len(MD.publisher_db) + 
Len(MD.publication) + 4, 
Charindex('-', MD.agent_name, 
Len(MD.publisher) + Len(MD.publisher_db) + 
Len(MD.publication) + 5) - 
(Len(MD.publisher) + 
Len(MD.publisher_db) + Len(MD.publication) + 4)) 
Where MD.publisher = @Publisher 
And MD.publisher_db = @PublisherDB 
And MD.publication_type = 0 -- 0 = Transactional publication And MD.agent_type = 3; -- 3 = distribution agent 
IF (@@ROWCOUNT > 500) 
BEGIN 
-- send alerts here.. 500 rows of undistributed transactions , should be higher. run this on remote distributor 
EXEC msdb.dbo.sp_send_dbmail 
@profile_name = 'DBA Alert', 
@recipients = 'your dba team email here', 
@body = 'This is replication latency alert. Check undistributed transactions query.', 
@subject = 'Replication Latency Alert' ; 
PRINT 'Alert here!' --since email is not yet working 
END

Psprawdź listę artykułów i sprawdź stan zdrowia subskrybentów

Jeśli pracujesz nad replikacją transakcji, te operacje są niezwykle ważne. Oto skrypt:

SELECT DISTINCT LEFT(srv.srvname,50) AS publication_server 
, LEFT(a.publisher_db, 50) AS publisher_db 
, LEFT(p.publication,25) AS publication_name
, LEFT(a.article, 50) AS [article] 
, LEFT(a.destination_object,50) AS destination_object 
, LEFT(ss.srvname,25) AS subscription_server 
, LEFT(s.subscriber_db,25) AS subscriber_db 
, LEFT(da.name,50) AS distribution_agent_job_name 
FROM distribution..MSArticles a 
JOIN distribution..MSpublications p ON a.publication_id = p.publication_id JOIN distribution..MSsubscriptions s ON p.publication_id = s.publication_id JOIN master..sysservers ss ON s.subscriber_id = ss.srvid 
JOIN master..sysservers srv ON srv.srvid = p.publisher_id 
JOIN distribution..MSdistribution_agents da ON da.publisher_id = p.publisher_id AND da.subscriber_id = s.subscriber_id 
ORDER BY 1,2,3 

Utwórz podsumowanie raportów dla zespołu DBA

Aby połączyć wszystkie statystyki replikacji oraz dostarczone i niedostarczone polecenia, można utworzyć tabelę w bazie danych dystrybucji zawierającą wszystkie szczegóły replikacji.

Z tej tabeli możesz utworzyć podsumowanie raportowania, które zostanie przekazane zespołowi dba . Ta tabela może być odświeżana codziennie w ramach codziennej kontroli kondycji replikacji, oprócz standardowej porannej kontroli kondycji administratora bazy danych.

USE [distribution] 
IF OBJECT_ID('Tempdb.dbo.#ReplStats') IS NOT NULL 
DROP TABLE #ReplStats 
CREATE TABLE [dbo].[#ReplStats] ( 
[DistributionAgentName] [nvarchar](100) NOT NULL 
,[DistributionAgentStartTime] [datetime] NOT NULL 
,[DistributionAgentRunningDurationInSeconds] [int] NOT NULL ,[IsAgentRunning] [bit] NULL 
,[ReplicationStatus] [varchar](14) NULL 
,[LastSynchronized] [datetime] NOT NULL 
,[Comments] [nvarchar](max) NOT NULL 
,[Publisher] [sysname] NOT NULL 
,[PublicationName] [sysname] NOT NULL 
,[PublisherDB] [sysname] NOT NULL 
,[Subscriber] [nvarchar](128) NULL 
,[SubscriberDB] [sysname] NULL 
,[SubscriptionType] [varchar](64) NULL 
,[DistributionDB] [sysname] NULL 
,[Article] [sysname] NOT NULL 
,[UndelivCmdsInDistDB] [int] NULL 
,[DelivCmdsInDistDB] [int] NULL 
,[CurrentSessionDeliveryRate] [float] NOT NULL 
,[CurrentSessionDeliveryLatency] [int] NOT NULL 
,[TotalTransactionsDeliveredInCurrentSession] [int] NOT NULL
,[TotalCommandsDeliveredInCurrentSession] [int] NOT NULL ,[AverageCommandsDeliveredInCurrentSession] [int] NOT NULL ,[DeliveryRate] [float] NOT NULL 
,[DeliveryLatency] [int] NOT NULL 
,[TotalCommandsDeliveredSinceSubscriptionSetup] [int] NOT NULL ,[SequenceNumber] [varbinary](16) NULL 
,[LastDistributerSync] [datetime] NULL 
,[Retention] [int] NULL 
,[WorstLatency] [int] NULL 
,[BestLatency] [int] NULL 
,[AverageLatency] [int] NULL 
,[CurrentLatency] [int] NULL 
) ON [PRIMARY] 
INSERT INTO #ReplStats 
SELECT da.[name] AS [DistributionAgentName] 
,dh.[start_time] AS [DistributionAgentStartTime] 
,dh.[duration] AS [DistributionAgentRunningDurationInSeconds] ,md.[isagentrunningnow] AS [IsAgentRunning] 
,CASE md.[status] 
WHEN 1 
THEN '1 - Started' 
WHEN 2 
THEN '2 - Succeeded' 
WHEN 3 
THEN '3 - InProgress' 
WHEN 4 
THEN '4 - Idle' 
WHEN 5 
THEN '5 - Retrying' 
WHEN 6 
THEN '6 - Failed' 
END AS [ReplicationStatus] 
,dh.[time] AS [LastSynchronized] 
,dh.[comments] AS [Comments] 
,md.[publisher] AS [Publisher] 
,da.[publication] AS [PublicationName] 
,da.[publisher_db] AS [PublisherDB] 
,CASE 
WHEN da.[anonymous_subid] IS NOT NULL 
THEN UPPER(da.[subscriber_name]) 
ELSE UPPER(s.[name]) 
END AS [Subscriber] 
,da.[subscriber_db] AS [SubscriberDB] 
,CASE da.[subscription_type] 
WHEN '0' 
THEN 'Push' 
WHEN '1' 
THEN 'Pull'
WHEN '2' 
THEN 'Anonymous' 
ELSE CAST(da.[subscription_type] AS [varchar](64)) 
END AS [SubscriptionType] 
,md.[distdb] AS [DistributionDB] 
,ma.[article] AS [Article] 
,ds.[UndelivCmdsInDistDB] 
,ds.[DelivCmdsInDistDB] 
,dh.[current_delivery_rate] AS [CurrentSessionDeliveryRate] ,dh.[current_delivery_latency] AS [CurrentSessionDeliveryLatency] ,dh.[delivered_transactions] AS 
[TotalTransactionsDeliveredInCurrentSession] 
,dh.[delivered_commands] AS [TotalCommandsDeliveredInCurrentSession] ,dh.[average_commands] AS [AverageCommandsDeliveredInCurrentSession] ,dh.[delivery_rate] AS [DeliveryRate] 
,dh.[delivery_latency] AS [DeliveryLatency] 
,dh.[total_delivered_commands] AS 
[TotalCommandsDeliveredSinceSubscriptionSetup] 
,dh.[xact_seqno] AS [SequenceNumber] 
,md.[last_distsync] AS [LastDistributerSync] 
,md.[retention] AS [Retention] 
,md.[worst_latency] AS [WorstLatency] 
,md.[best_latency] AS [BestLatency] 
,md.[avg_latency] AS [AverageLatency] 
,md.[cur_latency] AS [CurrentLatency] 
FROM [distribution]..[MSdistribution_status] ds 
INNER JOIN [distribution]..[MSdistribution_agents] da ON da.[id] = ds.[agent_id] 
INNER JOIN [distribution]..[MSArticles] ma ON ma.publisher_id = da.publisher_id 
AND ma.[article_id] = ds.[article_id] 
INNER JOIN [distribution]..[MSreplication_monitordata] md ON [md].[job_id] = da.[job_id] 
INNER JOIN [distribution]..[MSdistribution_history] dh ON [dh].[agent_id] = md.[agent_id] 
AND md.[agent_type] = 3 
INNER JOIN [master].[sys].[servers] s ON s.[server_id] = da.[subscriber_id] 
--Created WHEN your publication has the immediate_sync property set to true. This property dictates 
--whether snapshot is available all the time for new subscriptions to be initialized. 
--This affects the cleanup behavior of transactional replication. If this property is set to true, 
--the transactions will be retained for max retention period instead of it getting cleaned up 
--as soon as all the subscriptions got the change. 
WHERE da.[subscriber_db] <> 'virtual' 
AND da.[anonymous_subid] IS NULL
AND dh.[start_time] = ( 
SELECT TOP 1 start_time 
FROM [distribution]..[MSdistribution_history] a 
INNER JOIN [distribution]..[MSdistribution_agents] b ON a.[agent_id] = b.[id] 
AND b.[subscriber_db] <> 'virtual' 
WHERE [runstatus] <> 1 
ORDER BY [start_time] DESC 
) 
AND dh.[runstatus] <> 1 
SELECT 'Transactional Replication Summary' AS [Comments]; 
SELECT [DistributionAgentName] 
,[DistributionAgentStartTime] 
,[DistributionAgentRunningDurationInSeconds] 
,[IsAgentRunning] 
,[ReplicationStatus] 
,[LastSynchronized] 
,[Comments] 
,[Publisher] 
,[PublicationName] 
,[PublisherDB] 
,[Subscriber] 
,[SubscriberDB] 
,[SubscriptionType] 
,[DistributionDB] 
,SUM([UndelivCmdsInDistDB]) AS [UndelivCmdsInDistDB] 
,SUM([DelivCmdsInDistDB]) AS [DelivCmdsInDistDB] 
,[CurrentSessionDeliveryRate] 
,[CurrentSessionDeliveryLatency] 
,[TotalTransactionsDeliveredInCurrentSession] 
,[TotalCommandsDeliveredInCurrentSession] 
,[AverageCommandsDeliveredInCurrentSession] 
,[DeliveryRate] 
,[DeliveryLatency] 
,[TotalCommandsDeliveredSinceSubscriptionSetup] 
,[SequenceNumber] 
,[LastDistributerSync] 
,[Retention] 
,[WorstLatency] 
,[BestLatency] 
,[AverageLatency] 
,[CurrentLatency] 
FROM #ReplStats 
GROUP BY [DistributionAgentName] 
,[DistributionAgentStartTime] 
,[DistributionAgentRunningDurationInSeconds] 
,[IsAgentRunning]
,[ReplicationStatus] 
,[LastSynchronized] 
,[Comments] 
,[Publisher] 
,[PublicationName] 
,[PublisherDB] 
,[Subscriber] 
,[SubscriberDB] 
,[SubscriptionType] 
,[DistributionDB] 
,[CurrentSessionDeliveryRate] 
,[CurrentSessionDeliveryLatency] 
,[TotalTransactionsDeliveredInCurrentSession] 
,[TotalCommandsDeliveredInCurrentSession] 
,[AverageCommandsDeliveredInCurrentSession] 
,[DeliveryRate] 
,[DeliveryLatency] 
,[TotalCommandsDeliveredSinceSubscriptionSetup] 
,[SequenceNumber] 
,[LastDistributerSync] 
,[Retention] 
,[WorstLatency] 
,[BestLatency] 
,[AverageLatency] 
,[CurrentLatency] 
SELECT 'Transactional Replication Summary Details' AS [Comments]; 
SELECT [Publisher] 
,[PublicationName] 
,[PublisherDB] 
,[Article] 
,[Subscriber] 
,[SubscriberDB] 
,[SubscriptionType] 
,[DistributionDB] 
,SUM([UndelivCmdsInDistDB]) AS [UndelivCmdsInDistDB] ,SUM([DelivCmdsInDistDB]) AS [DelivCmdsInDistDB] 
FROM #ReplStats 
GROUP BY [Publisher] 
,[PublicationName] 
,[PublisherDB] 
,[Article] 
,[Subscriber] 
,[SubscriberDB] 
,[SubscriptionType] 
,[DistributionDB]

Podsumowanie

Mam nadzieję, że te kilka skryptów T-SQL podanych powyżej pomoże Ci w monitorowaniu Twoich agentów replikacji. Gorąco polecam uważne ich monitorowanie. W przeciwnym razie użytkownicy po stronie subskrybenta mogą w nieskończoność narzekać, że nie mają danych (bliskich) w czasie rzeczywistym.

W kolejnych artykułach zagłębię się w technologię SQL replikacji danych do dowolnej części globu. Miłego monitorowania!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sterownik ODBC Google BigQuery

  2. Zarabiaj pieniądze na niewykorzystanych rzeczach:model danych gospodarki współdzielenia

  3. Jak filtrowane indeksy mogą być potężniejszą funkcją?

  4. Filtrowane indeksy i dołączone kolumny

  5. SQL INSERT dla początkujących