レプリケーションは、MS SQL Serverで最も古いテクノロジの1つであり、すべてのデータベース管理者に愛されています。これは、特に分散レポートの場合に、データをユーザーに近づけるための優れた信頼性の高いテクノロジーです。そのおかげで、データベースの可用性は複数のSQLServerとリージョンにわたって向上します。
レプリケーションはSQL2005で導入されました。それが古いと信じられますか?クラウド上の新しいマネージドSQLプラットフォームは定期的に導入されていますが、SQLレプリケーションはここに残ると思います。虫や虫ならゴキブリだと思います。押しつぶすのは難しいです!
データベースを管理したことのない少数の管理者に属している場合は、このトピックに関するMicrosoftの公式ドキュメントがあります。ただし、それはかなり長く、包括的であり、休日や計画されている一気見テレビシリーズからの休暇を奪うことに注意してください。また、Codingsightは、SQLServerデータベースレプリケーションのセットアップおよび構成ガイドを提供しています。
しかし、技術的なことで手を汚す前に、そしてあなたも熱心であることを私は知っています。それを計画することが重要です。
クラウド上で実行されているSQLServerに展開する場合、レプリケーション要件は場所に関して変更される可能性があります。ただし、SQLレプリケーションが十分に機能するマシンのように実行され、本番データをレプリケートしたら、それをどのように管理するかを計画する必要があります。
この投稿では、レプリケーション構成後に多くのSQLエージェントジョブが作成されていることを確認する必要がある場合に使用できるヒントとT-SQLスクリプトをいくつか紹介します。
レプリケーションエージェントの監視
SQLレプリケーションを設定および構成すると、レプリケーションエージェントと呼ばれるスタンドアロン関数とSQLエージェントジョブのセットも作成されます。彼らの目標は、テーブルの移動に関連するタスクを実行することです。これは、記事とも呼ばれます。 、パブリッシャーからのレプリケーション構成 サブスクライバー/秒へ 。コマンドラインから、およびレプリケーション管理オブジェクト(RMO)を使用するアプリケーションによってレプリケーションエージェントを実行できます。
SQL Serverレプリケーションエージェントは、ReplicationMonitorおよびSQLServerManagementStudioを介して監視および管理できます。
データベース管理者/レプリケーション管理者の主な関心事は、すべてのSQLエージェントレプリケーションジョブが実行されていることを確認することです。レプリケーションエージェントジョブが失敗した場合、サブスクライバーはデータを受信しない可能性があります。したがって、サブスクライバーデータベースに移動しない累積行のために、ディストリビューションデータベースが巨大になる可能性があります。
レプリケーションエージェントジョブの失敗に対するアラートを設定するには、別のエージェントジョブを作成できます。ジョブの失敗をチェックし、問題が特定された場合はdbaチームにメールを送信します。
失敗したレプリケーションエージェントジョブを確認する
以下のスクリプトを使用してください:
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
ジョブの失敗を通知するメールアラートを作成する
次のスクリプトを適用します:
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 ;
複製されたコマンドを含むテーブルを監視する
msrepl_commandsを監視するには 表では、以下に提供されているもう1つのスクリプトを使用できます。このテーブルは大きくなりすぎ、速くなりすぎることに注意してください。その場合、レプリケーションエージェントジョブが失敗するか、レプリケーション構成に問題がある可能性があります。
スクリプトは次のとおりです。
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 テーブルの増加傾向は、レプリケーションの待機時間がどれほど健全であるかについてのヒントも提供します。影響には多くの要因があります。ご使用の環境がクラウド内にある場合、リージョンの選択がレプリケーションのレイテンシーに大きく影響する可能性があります。
C レプリケーションに関する簡単なレポートを作成し、メールで送信する
次のスクリプトを使用できます:
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
Q 記事リストを使用して、サブスクライバーの状態を確認します
トランザクションレプリケーションで作業している場合、これらの操作は非常に重要です。スクリプトは次のとおりです:
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
DBAチームのレポートサマリーを作成する
すべてのレプリケーション統計と配信済みおよび未配信のコマンドを組み合わせるために、すべてのレプリケーションの詳細を含むテーブルをディストリビューションデータベースに作成できます。
この表から、レポートの概要を作成してdbaチームに配布できます 。このテーブルは、標準のデータベース管理者の朝のヘルスチェックとは別に、毎日のレプリケーションヘルスチェックの一部として毎日更新できます。
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]
概要
上記で提供されたこれらのいくつかのT-SQLスクリプトが、レプリケーションエージェントの監視に役立つことを願っています。それらを注意深く監視することを強くお勧めします。そうしないと、加入者側のユーザーが、リアルタイムデータがない(近い)ことについて際限なく不平を言う可能性があります。
今後の記事では、データを世界中のあらゆる場所に複製するSQLテクノロジについて詳しく説明します。ハッピーモニタリング!