sql >> データベース >  >> RDS >> Database

MSSQLレプリケーションの管理

    レプリケーションは、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テクノロジについて詳しく説明します。ハッピーモニタリング!


    1. ワークフローパターンを使用して任意のエンティティの状態を管理する

    2. 2020年の計画でデータベース監視を優先する必要がある4つの理由

    3. OracleのSIGN()関数

    4. 回避策:クラスター化された列ストアインデックスを持つテーブルではカーソルはサポートされていません