在可用性群組中設定兩個對等節點

自 SQL Server 2019(15.x)CU 13 起,屬於 SQL Server Always On 可用性群組的資料庫可以作為對等節點,參與點對點交易式複寫拓撲。 本文說明如何以兩個對等節點設定此案例——每個對等節點各自位於自己的可用性群組中。

此範例中的腳本使用 T-SQL 儲存程序。

角色與名稱

本節說明參與本文複製拓撲的各種元素的角色與名稱。

Peer1

  • Node1:第一個可用性群組的主副本
  • Node2:第一個可用性群組的次要副本
  • MyAG:第一個可用性群組的名稱
  • MyDBName: Peer1 資料庫。 待公布資料庫
  • Dist1:遠端分配器
  • P2P_MyDBName:發行名稱
  • MyAGListenerName: 可用性群組監聽器

Peer2

  • Node3:第二個可用性群組的主副本
  • Node4:第二個可用性群組的次要副本
  • MyAG2:第二個可用性群組的名稱
  • MyDBName:即將發布的資料庫
  • Dist2:遠端分發器
  • P2P_MyDBName:發行名稱
  • MyAG2ListenerName:可用性群組監聽者

先決條件

  • 四個 SQL Server 實例分別設置在不同的實體或虛擬伺服器上,以承載可用性群組。 兩個可用群組各自包含一個對等資料庫。

  • 兩個 SQL Server 實例來架設發行商資料庫。

  • 所有伺服器實例都需要支援的版本——企業版或開發者版。

  • 所有伺服器實例都需要支援的版本——SQL Server 2019 (15.x) CU13 或更新版本。

  • 所有實例間的網路連線與頻寬都必須足夠。

  • 在所有 SQL Server 實例上安裝 SQL Server 複寫。

    要確認是否有複製安裝於任何實例,請執行以下查詢:

    USE master;   
    GO   
    DECLARE @installed int;   
    EXEC @installed = sys.sp_MS_replication_installed;   
    SELECT @installed; 
    

    Note

    為避免分發資料庫出現單點故障,建議每個節點使用遠端分發器。

    在示範或測試環境中,你可以在單一實例上配置發行資料庫。

設定分發者與遠端發佈者(Peer1)

本節說明如何在可用性群組中設置第一個對等節點(Peer1)。

  1. 執行 sp_adddistributor 以配置 Dist1 的分配。 用 @password = 來指定遠端出版者用來連接發行商的密碼。 設定遠端散發者時,請在每個遠端發行者使用此密碼。

    USE master;  
    GO  
    EXEC sys.sp_adddistributor  
     @distributor = 'Dist1',  
     @password = '<Strong password for distributor>';  
    
  2. 在散發者端建立散發資料庫。

    USE master;
    GO  
    EXEC sys.sp_adddistributiondb  
     @database = 'distribution',  
     @security_mode = 1;  
    
  3. 設定 Node1 和 Node2 遠端發佈者。

    @security_mode 會決定複製代理如何連接到目前的主要節點。

    • 1 = Windows 驗證.
    • 0= SQL Server 認證。 需要 @login 和 @password。 指定的登入與密碼必須在每個次要副本中有效。

    Note

    若任何修改過的複製代理程式在非分發器電腦上運行,則使用 Windows 驗證 連接主主機時,副本主機間的通訊需使用 Kerberos 認證。 使用 SQL Server 登入連線到目前的主要主機不需要 Kerberos 認證。

    USE master;  
    GO  
    EXEC sys.sp_adddistpublisher  
     @publisher = 'Node1',  
     @distribution_db = 'distribution',  
     @working_directory = '\\MyReplShare\WorkingDir',  
     @security_mode = 1
    USE master;  
    GO  
    EXEC sys.sp_adddistpublisher  
     @publisher = 'Node2',  
     @distribution_db = 'distribution',  
     @working_directory = '\\MyReplShare\WorkingDir',  
     @security_mode = 1
    

在原始發佈者(Node1)上設定發佈者

  1. 設定遠端發行原始發佈者(Node1)。 為 sp_adddistributor 指定與您在散發者執行 @password 以設定散發時所使用的相同值。

    EXEC sys.sp_adddistributor  
    @distributor = 'Dist1',  
    @password = '<Password used when running sp_adddistributor on distributor server>' 
    
  2. 啟用資料庫進行複寫。

    USE master;  
    GO  
    EXEC sys.sp_replicationdboption  
     @dbname = 'MyDBName',  
     @optname = 'publish',  
     @value = 'true';  
    

將次要複本主機配置為複寫發佈者(Node2)

在第一個可用性群組的每個次要副本主機(Node2)上,設定散發。 請為 sp_adddistributor 指定與您在散發者端執行 @password 以設定散發時所使用的相同值。

EXEC sys.sp_adddistributor  
   @distributor = 'Dist1',  
   @password = '<Password used when running sp_adddistributor on distributor server>' 

將資料庫設為可用性群組的一部分,並建立監聽器(Peer1)

  1. 在預定的主要副本上,建立可用群組,資料庫作為成員資料庫。

  2. 為可用性群組建立一個 DNS 監聽器。 複製代理會利用監聽器連接到目前的主要副本。 以下範例會產生一個名為 MyAGListenerName的監聽器。

    ALTER AVAILABILITY GROUP 'MyAG'
    ADD LISTENER 'MyAGListenerName' (WITH IP (('<ip address>', '<subnet mask>') [, PORT = <listener_port>]));   
    

    Note

    在前述文字中,方括號內[ ... ]的資訊為可選。 用它來指定非預設值的 TCP 埠。 不要包含括號。

將原始發佈者重新導向至 AG 接聽器名稱(Peer1)

在 Peer1 的散發者上,將原始發行者重新導向至 AG 接聽程式名稱。

USE distribution;   
GO   
EXEC sys.sp_redirect_publisher    
@original_publisher = 'Node1',   
@publisher_db = 'MyDBName',   
@redirected_publisher = 'MyAGListenerName,<port>';   

Note

在前面的指令碼中,,<port> 是可選的。 只有在使用非預設埠時才需要。 不要包含角括號 <>。

在原始發佈者 Node1 上建立點對點發佈(Peer1)

以下腳本建立 Peer1 的發佈。

EXEC master..sp_replicationdboption  @dbname=  'MyDBName'   
        ,@optname=  'publish'   
        ,@value=  'true'  
GO
DECLARE @publisher_security_mode smallint = 1
EXEC [MyDBName].dbo.sp_addlogreader_agent @publisher_security_mode = @publisher_security_mode
GO
DECLARE @allow_dts nvarchar(5) = N'false'
DECLARE @allow_pull nvarchar(5) = N'true'
DECLARE @allow_push nvarchar(5) = N'true'
DECLARE @description nvarchar(255) = N'Peer-to-Peer publication of database MyDBName from Node1'
DECLARE @enabled_for_p2p nvarchar(5) = N'true'
DECLARE @independent_agent nvarchar(5) = N'true'
DECLARE @p2p_conflictdetection nvarchar(5) = N'true'
DECLARE @p2p_originator_id int = 100
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @repl_freq nvarchar(10) = N'continuous'
DECLARE @restricted nvarchar(10) = N'false'
DECLARE @status nvarchar(8) = N'active'
DECLARE @sync_method nvarchar(40) = N'NATIVE'
EXEC [MyDBName].dbo.sp_addpublication @allow_dts = @allow_dts, @allow_pull = @allow_pull, @allow_push = @allow_push, @description = @description, @enabled_for_p2p = @enabled_for_p2p, @independent_agent = @independent_agent, @p2p_conflictdetection = @p2p_conflictdetection, @p2p_originator_id = @p2p_originator_id, @publication = @publication, @repl_freq = @repl_freq, @restricted = @restricted, @status = @status, @sync_method = @sync_method
GO
DECLARE @article nvarchar(256) = N'tbl0'
DECLARE @description nvarchar(255) = N'Article for dbo.tbl0'
DECLARE @destination_table nvarchar(256) = N'tbl0'
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @source_object nvarchar(256) = N'tbl0'
DECLARE @source_owner nvarchar(256) = N'dbo'
DECLARE @type nvarchar(256) = N'logbased'
EXEC [MyDBName].dbo.sp_addarticle @article = @article, @description = @description, @destination_table = @destination_table, @publication = @publication, @source_object = @source_object, @source_owner = @source_owner, @type = @type
GO
DECLARE @article nvarchar(256) = N'tbl1'
DECLARE @description nvarchar(255) = N'Article for dbo.tbl1'
DECLARE @destination_table nvarchar(256) = N'tbl1'
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @source_object nvarchar(256) = N'tbl1'
DECLARE @source_owner nvarchar(256) = N'dbo'
DECLARE @type nvarchar(256) = N'logbased'
EXEC [MyDBName].dbo.sp_addarticle @article = @article, @description = @description, @destination_table = @destination_table, @publication = @publication, @source_object = @source_object, 
@source_owner = @source_owner, @type = @type
GO

讓點對點發佈與可用性群組(Peer1)相容

在原始發佈者(Node1)上,執行以下腳本使發佈與可用性群組相容:

USE MyDBName
GO
DECLARE @publication sysname = N'P2P_MyDBName' 
DECLARE @property sysname = N'redirected_publisher' 
DECLARE @value sysname = N'MyAGListenerName,<port>' 
EXEC MyDBName..sp_changepublication @publication = @publication, @property = @property, @value = @value 
GO 

Note

在前述指令碼中,,<port> 是可選的。 只有在使用非預設埠時才需要。

完成前述步驟後,可用群組即可參與點對點拓撲。 接下來的步驟是將一個獨立的可用性群組設定為點對點複寫拓撲中的第二個節點(Peer2)。

設定發行商與遠端發佈者(Peer2)

本節說明如何在不同可用性群組中設定第二個節點(Peer2)。

  1. 執行 sp_adddistributor 以設定 Dist2 的分配。 用 @password = 來指定遠端出版者用來連接發行商的密碼。 設定遠端散發者時,請在每個遠端發行者使用此密碼。

    USE master;  
    GO  
    EXEC sys.sp_adddistributor  
     @distributor = 'Dist2',  
     @password = '<Strong password for distributor>';  
    
  2. 在散發者端建立散發資料庫。

    USE master;
    GO  
    EXEC sys.sp_adddistributiondb  
     @database = 'distribution',  
     @security_mode = 1;  
    
  3. 設定 Node3 和 Node4 遠端發佈者。

    @security_mode 會決定複製代理如何連接到目前的主要節點。

    • 1 = Windows 驗證.
    • 0= SQL Server 認證。 需要 @login 和 @password。 指定的登入與密碼必須在每個次要副本中有效。

    Note

    若任何修改過的複製代理程式在非分發器電腦上運行,則使用 Windows 驗證 連接主主機時,副本主機間的通訊需使用 Kerberos 認證。 使用 SQL Server 登入連線到目前的主要主機不需要 Kerberos 認證。

    USE master;  
    GO  
    EXEC sys.sp_adddistpublisher  
     @publisher = 'Node3',  
     @distribution_db = 'distribution',  
     @working_directory = '\\MyReplShare\WorkingDir2',  
     @security_mode = 1
    USE master;  
    GO  
    EXEC sys.sp_adddistpublisher  
     @publisher = 'Node4',  
     @distribution_db = 'distribution',  
     @working_directory = '\\MyReplShare\WorkingDir2',  
     @security_mode = 1
    

設定發佈者(Peer2)

  1. 在(Node3)設定遠端分配。 請為 sp_adddistributor 指定與您在散發者端執行 @password 以設定散發時所使用的相同值。

    EXEC sys.sp_adddistributor  
    @distributor = 'Dist2',  
    @password = '<Password used when running sp_adddistributor on distributor server>' 
    
  2. 啟用資料庫進行複寫。

    USE master;  
    GO  
    EXEC sys.sp_replicationdboption  
     @dbname = 'MyDBName',  
     @optname = 'publish',  
     @value = 'true';  
    

將次要副本主機配置為複寫發佈者(Node4)

在每個次要複本主機(Node4)的第二個可用性群組,設定分散式。 請為 sp_adddistributor 指定與您在散發者上執行 @password 以設定散發時所使用的值相同的值。

EXEC sys.sp_adddistributor  
   @distributor = 'Dist2',  
   @password = '<Password used when running sp_adddistributor on distributor server>' 

讓資料庫成為可用性群組的一部分,並建立監聽器(Peer2)

  1. 在預定的主要副本上,建立可用群組,資料庫作為成員資料庫。

  2. 為可用性群組建立一個 DNS 監聽器。 複製代理會利用監聽器連接到目前的主要副本。 以下範例會產生一個名為 MyAG2ListenerName的監聽器。

    ALTER AVAILABILITY GROUP 'MyAG2'
    ADD LISTENER 'MyAG2ListenerName' (WITH IP (('<ip address>', '<subnet mask>') [, PORT = <listener_port>]));   
    

    Note

    在前述文字中,方括號內[ ... ]的資訊為可選。 用它來指定非預設值的 TCP 埠。 不要包含括號。

將原始發佈者重新導向至 AG 接聽器名稱(Peer2)

在 Peer2 的散發者上,將原始發行者重新導向至 AG 接聽程式名稱。

USE distribution;   
GO   
EXEC sys.sp_redirect_publisher    
@original_publisher = 'Node3',   
@publisher_db = 'MyDBName',   
@redirected_publisher = 'MyAG2ListenerName,<port>';   

Note

在前面的指令碼中,,<port> 是選用的。 只有在使用非預設埠時才需要。 不要包含角括號 <>。

建立點對點發佈(Peer2)

下列指令碼會為 Peer2 建立發佈項目。

在 Node3 上,執行以下指令建立點對點發佈。

EXEC master..sp_replicationdboption  @dbname=  'MyDBName'   
        ,@optname=  'publish'   
        ,@value=  'true'  
GO
DECLARE @publisher_security_mode smallint = 1
EXEC [MyDBName].dbo.sp_addlogreader_agent @publisher_security_mode = @publisher_security_mode
GO

-- Make sure that the value for @p2p_originator_id is different from Peer1.
DECLARE @allow_dts nvarchar(5) = N'false'
DECLARE @allow_pull nvarchar(5) = N'true'
DECLARE @allow_push nvarchar(5) = N'true'
DECLARE @description nvarchar(255) = N'Peer-to-Peer publication of database MyDBName from Node3'
DECLARE @enabled_for_p2p nvarchar(5) = N'true'
DECLARE @independent_agent nvarchar(5) = N'true'
DECLARE @p2p_conflictdetection nvarchar(5) = N'true'
DECLARE @p2p_originator_id int = 1
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @repl_freq nvarchar(10) = N'continuous'
DECLARE @restricted nvarchar(10) = N'false'
DECLARE @status nvarchar(8) = N'active'
DECLARE @sync_method nvarchar(40) = N'NATIVE'
EXEC [MyDBName].dbo.sp_addpublication @allow_dts = @allow_dts, @allow_pull = @allow_pull, @allow_push = @allow_push, @description = @description, @enabled_for_p2p = @enabled_for_p2p, @independent_agent = @independent_agent, @p2p_conflictdetection = @p2p_conflictdetection, @p2p_originator_id = @p2p_originator_id, @publication = @publication, @repl_freq = @repl_freq, @restricted = @restricted, @status = @status, @sync_method = @sync_method
GO
DECLARE @article nvarchar(256) = N'tbl0'
DECLARE @description nvarchar(255) = N'Article for dbo.tbl0'
DECLARE @destination_table nvarchar(256) = N'tbl0'
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @source_object nvarchar(256) = N'tbl0'
DECLARE @source_owner nvarchar(256) = N'dbo'
DECLARE @type nvarchar(256) = N'logbased'
EXEC [MyDBName].dbo.sp_addarticle @article = @article, @description = @description, @destination_table = @destination_table, @publication = @publication, @source_object = @source_object, @source_owner = @source_owner, @type = @type
GO

DECLARE @article nvarchar(256) = N'tbl1'
DECLARE @description nvarchar(255) = N'Article for dbo.tbl1'
DECLARE @destination_table nvarchar(256) = N'tbl1'
DECLARE @publication nvarchar(256) = N'P2P_MyDBName'
DECLARE @source_object nvarchar(256) = N'tbl1'
DECLARE @source_owner nvarchar(256) = N'dbo'
DECLARE @type nvarchar(256) = N'logbased'
EXEC [MyDBName].dbo.sp_addarticle @article = @article, @description = @description, @destination_table = @destination_table, @publication = @publication, @source_object = @source_object, 
@source_owner = @source_owner, @type = @type
GO

讓點對點發佈與可用性群組(Peer2)相容

在原始發佈者(Node3)上,執行以下腳本使出版品與可用性群組相容:

USE MyDBName
GO
DECLARE @publication sysname = N'P2P_MyDBName' 
DECLARE @property sysname = N'redirected_publisher' 
DECLARE @value sysname = N'MyAG2ListenerName,<port>' 
EXEC MyDBName..sp_changepublication @publication = @publication, @property = @property, @value = @value 
GO 

Note

在上述指令碼中,,<port> 是選用的。 只有在使用非預設埠時才需要。

從 Peer1 建立一個推送訂閱,連接到 Peer2 的可用性群組監聽器

要從 Peer1 建立推送訂閱到可用性群組監聽器 Peer2,請在 Node1 執行以下指令。

在 Node1 執行以下腳本。 此腳本假設 Node1 正在執行主要副本。

Important

以下腳本指定用戶的可用性群組監聽器名稱。

@subscriber = N'MyAGListenerName,<port>'

Note

在前述指令碼中,,<port> 是可選的。 只有在使用非預設埠時才需要。 不要包含角括號 <>。

EXEC [MyDBName].dbo.sp_addsubscription 
   @publication = N'P2P_MyDBName'
 , @subscriber = N'MyAG2Listener,<port>' 
 , @destination_db = N'MyDBName'
 , @subscription_type = N'push'
 , @sync_type = N'replication support only'
GO

EXEC [MyDBName].dbo.sp_addpushsubscription_agent 
   @publication = N'P2P_MyDBName'
 , @subscriber = N'MyAG2Listener,<port>' 
 , @subscriber_db = N'MyDBName'
 , @job_login = null 
 , @job_password = null
 , @subscriber_security_mode = 1
 , @frequency_type = 64
 , @frequency_interval = 1
 , @frequency_relative_interval = 1
 , @frequency_recurrence_factor = 0
 , @frequency_subday = 4
 , @frequency_subday_interval = 5
 , @active_start_time_of_day = 0
 , @active_end_time_of_day = 235959
 , @active_start_date = 0
 , @active_end_date = 0
 , @dts_package_location = N'Distributor'
GO

從 Peer2 建立推送訂閱至可用性群組接聽程式 (Peer1)

要從 Peer2 建立推送訂閱到可用性群組監聽器(Peer1),請在 Node3 執行以下指令。

Important

以下腳本指定用戶的可用性群組監聽器名稱。

@subscriber = N'MyAGListenerName,<port>'

Note

在前面的指令碼中,,<port> 是選用的。 只有在使用非預設埠時才需要。 不要包含角括號 <>。

EXEC [MyDBName].dbo.sp_addsubscription 
   @publication = N'P2P_MyDBName'
 , @subscriber = N'MyAGListenerName,<port>'
 , @destination_db = N'MyDBName'
 , @subscription_type = N'push'
 , @sync_type = N'replication support only'
GO

EXEC [MyDBName].dbo.sp_addpushsubscription_agent 
   @publication = N'P2P_MyDBName'
 , @subscriber = N'MyAGListenerName,<port>'
 , @subscriber_db = N'MyDBName'
 , @job_login = null
 , @job_password = null
 , @subscriber_security_mode = 1
 , @frequency_type = 64
 , @frequency_interval = 1
 , @frequency_relative_interval = 1
 , @frequency_recurrence_factor = 0
 , @frequency_subday = 4
 , @frequency_subday_interval = 5
 , @active_start_time_of_day = 0
 , @active_end_time_of_day = 235959
 , @active_start_date = 0
 , @active_end_date = 0
 , @dts_package_location = N'Distributor'
GO

配置連結伺服器

在每個次要副本主機上,確保資料庫出版物的推送訂閱者以連結伺服器形式出現。

EXEC sys.sp_addlinkedserver   
    @server = 'MySubscriber';