建立和套用初始快照集

適用於:SQL ServerAzure SQL 受控執行個體

本主題說明如何使用 SQL Server Management Studio、Transact-SQL 或 Replication Management Objects (RMO),在 SQL Server 中建立及套用初始快照集。 使用參數化篩選的合併式發行集需要一個兩段式快照集。 如需詳細資訊,請參閱 使用參數化篩選建立合併式發行集的快照集
快照集在發行集建立之後由「快照代理程式」產生。 它們可以:

  • 立即產生。 依預設,在「新增發行集精靈」中建立發行集後會立即產生合併式發行集的快照集。
  • 在排程時間產生。 在「新增發行集精靈」的 [快照集代理程式] 頁面上指定排程,或在使用預存程序或 Replication Management Objects (RMO) 時指定排程。
  • 手動。 在命令提示下或從 SQL Server Management Studio 執行「快照集代理程式」。 如需執行代理程式的詳細資訊,請參閱複寫代理程式可執行檔概念啟動及停止複寫代理程式 Replication Agent (SQL Server Management Studio)

針對合併式複寫,每次執行快照集代理程式都會產生快照集。 針對異動複寫,是否產生快照集是依照發行集屬性 immediate_sync的設定而定。 若屬性設定為 TRUE (使用新增發行集精靈的預設),每次執行快照集代理程式都會產生快照集,同時隨時可套用至訂閱者。 若屬性設定為 FALSE (使用 sp_addpublication時的預設),則只有在上次執行快照集代理程式後有加入新訂閱的情況下,才會產生快照集。訂閱者必須等待快照集代理程式完成,才能同步處理。

依預設,快照集產生後會儲存在「散發者」上的預設快照集資料夾中。 您也可以將快照集檔案儲存於抽取式媒體,例如卸除式磁碟機、CD-ROM 或預設快照集資料夾之外的位置。 此外,您可以壓縮檔案,使它們更易儲存和傳送,還可以在快照集套用至「訂閱者」端前後執行指令碼。 如需這些選項的詳細資訊,請參閱 Snapshot Options

若快照集是專為使用參數化篩選的合併式發行集而產生,該快照集會使用兩部份處理建立而成。 首先建立結構描述快照集,其中包含複寫指令碼和已發行物件的結構描述,但不包含資料。 接下來每個訂閱皆以快照集初始化,該快照集中包含從結構描述快照集複製而來的指令碼和結構描述,以及屬於訂閱分割的資料。 如需詳細資訊,請參閱 Snapshots for Merge Publications with Parameterized Filters

快照集在「發行者」端建立,並儲存於預設或替代的快照集位置之後,可以傳送「訂閱者」並進行套用。 初始同步處理期間,「散發代理程式」 (用於快照式或異動複寫) 或「合併代理程式」 (用於合併式複寫) 會傳送快照集,並將結構描述和資料檔套用至「訂閱者」端的訂閱資料庫。 依預設,如果您使用「新增訂閱精靈」,初始同步處理便會在建立訂閱之後立即進行。 此行為由精靈 [初始化訂閱] 頁面上的 [初始化時機] 選項控制。 快照集在訂閱初始化之後產生時,不會套用至「訂閱者」,除非訂閱已標示為要重新初始化。 如需詳細資訊,請參閱 重新初始化訂閱

「散發代理程式」或「合併代理程式」套用初始化快照集後,代理程式會傳播後續的更新以及其他資料修改。 快照集散發並套用至「訂閱者」後,只有等待初始快照集或新快照集的「訂閱者」會受影響。 該發行集的其他「訂閱者」(收到對已發行資料之插入、更新、刪除或其他修改的「訂閱者」) 均不受影響。

若要檢視或修改預設的快照資料夾位置,請參閱

預設快照集位置

在「設定散發精靈」的 [快照集資料夾] 頁面中指定預設快照集位置。 如需使用此精靈的詳細資訊,請參閱設定發行和散發。 如果您在未設定為「散發者」的伺服器上建立發行集,則請在「新增發行集精靈」的 [快照集資料夾] 頁面中指定預設快照集位置。 如需使用此精靈的詳細資訊,請參閱建立發行集

在 [散發者屬性 - <散發者>] 對話方塊的 [發行者] 頁面上,修改預設快照集位置。 如需詳細資訊,請參閱檢視及修改散發者和發行者屬性。 在 [發行集屬性 - <發行集>] 對話方塊中為每個發行集設定快照集資料夾。 如需詳細資訊,請參閱 View and Modify Publication Properties

修改預設快照集位置

  1. 在 [散發者屬性 - <散發者>] 對話方塊的 [發行者] 頁面上,按一下您要變更其預設快照集位置之發行者的屬性按鈕 (...)。

  2. 在 [發行者屬性 - <發行者>] 對話方塊中,輸入 [預設快照集資料夾] 屬性的值。

    注意

    快照集代理程式必須有您指定之目錄的寫入權限,而散發代理程式或合併代理程式則必須有讀取權限。 如果使用提取訂閱,您必須指定一個共用目錄做為通用命名慣例 (UNC) 路徑,例如 \\computername\snapshot。 如需詳細資訊,請參閱保護快照集資料夾

  3. 選取 [確定]。

建立快照集

根據預設,如果 SQL Server Agent 正在執行,則在使用「新增發行集精靈」建立發行集之後,「快照集代理程式」會立即產生快照集。 隨後,「散發代理程式」(針對快照式複寫和異動複寫) 或「合併代理程式」(針對合併訂閱) 預設會為所有訂閱套用該快照集。 也可以使用 SQL Server Management Studio 和複寫監視器來產生快照集。 如需啟動複寫監視器的詳細資訊,請參閱啟動複寫監視器

使用 SQL Server Management Studio

  1. 連線到 Management Studio 中的發行者,然後展開伺服器節點。
  2. 展開 [複寫] 資料夾,然後展開 [本機發行集] 資料夾。
  3. 以滑鼠右鍵按一下您要為其建立快照集的發行集,然後按一下 [檢視快照集代理程式的狀態]
  4. 在 [檢視快照集代理程式的狀態 - <發行集>] 對話方塊中,按一下 [啟動]。
    快照集代理程式產生完快照集後,就會顯示一個訊息,例如「[100%] 已產生 17 個發行項的快照集」。

在複寫監視器中

  1. 在複寫監視器的左窗格中展開發行者群組,然後展開發行者。
  2. 以滑鼠右鍵按一下要產生快照集的發行集,然後按一下 [產生快照集]
  3. 若要檢視快照集代理程式的狀態,請按一下 [代理程式] 索引標籤。如需詳細資訊,請以滑鼠右鍵按一下方格中的「快照集代理程式」,然後按一下 [檢視詳細資料]

使用 TRANSACT-SQL

可以透過程式設計方式建立初始快照集,其方式是建立及執行快照集代理程式作業,或是從批次檔執行快照集代理程式的可執行檔。 在產生初始快照集之後,此快照集會在第一次同步處理訂閱時,傳送及套用到訂閱者。 如果您從命令提示字元或批次檔執行快照集代理程式,每當現有的快照集無效時,您將需要重新執行此代理程式。

重要

可能的話,會在執行階段提示使用者輸入安全性認證。 如果您必須將認證儲存在指令碼檔案中,則必須維護這個檔案的安全性,使他人無法在未獲授權的情況下擅自存取。

  1. 建立快照式、交易式或合併式發行集。 如需詳細資訊,請參閱建立發行集

  2. 執行 sp_addpublication_snapshot (Transact-SQL)。 指定 @publication 及下列參數:

    • @job_login ,它會指定散發者上的快照集代理程式執行時所用的 Windows 驗證認證。

    • @job_password,它是提供之 Windows 認證的密碼。

    • (選擇性) 如果代理程式在連接到發行者時將使用「SQL Server 驗證」,會將 @publisher_security_mode 設定為 0 的值。 在此情況下,您也必須針對 @publisher_login@publisher_password指定「SQL Server 驗證」登入資訊。

    • (選擇性) 快照集代理程式作業的同步排程。 如需詳細資訊,請參閱 Specify Synchronization Schedules

    重要

    當利用遠端散發者來設定發行者時,提供給所有參數的值 (包括 job_loginjob_password) 都會以純文字的方式傳給散發者。 您應該先加密「發行者」及其遠端「散發者」之間的連接,再執行這個預存程序。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)

  3. 將發行項加入至發行集。 如需詳細資訊,請參閱 定義發行項

  4. 在發行集資料庫的發行者端,執行 sp_startpublication_snapshot (Transact-SQL),並指定步驟 1 中的 @publication 值。

套用快照集

使用 SQL Server Management Studio

  1. 產生快照集後,將透過「散發代理程式」或「合併代理程式」對訂閱進行同步處理來套用該快照集:

    • 如果將代理程式設定為連續執行 (異動複寫的預設值),快照集會在產生後自動套用。
    • 如果將代理程式設定為按排程執行,則快照集將在該代理程式排程的下次執行時套用。
    • 如果將代理程式設定為視需要執行,則快照集將您在下次執行該代理程式時套用。

    如需有關同步處理訂閱的資訊,請參閱< Synchronize a Push Subscription >和< Synchronize a Pull Subscription資料夾中可用。

使用 Transact-SQL

  1. 建立快照式、交易式或合併式發行集。 如需詳細資訊,請參閱建立發行集

  2. 將發行項加入至發行集。 如需詳細資訊,請參閱 定義發行項

  3. 從命令提示字元或批次檔中,執行 snapshot.exe 來啟動 複寫合併代理程式,並指定下列命令列引數:

    • -Publication
    • -Publisher
    • -Distributor
    • -PublisherDB
    • -ReplicationType

    無果您正在使用「SQL Server 驗證」,您也必須指定下列引數:

    • -DistributorLogin
    • -DistributorPassword
    • -DistributorSecurityMode = \@publisher_security_mode
    • -PublisherLogin
    • -PublisherPassword
    • -PublisherSecurityMode = \@publisher_security_mode

範例 (Transact-SQL)

此範例會示範如何建立交易式發行集,並針對新的發行集加入快照集代理程式作業 (使用 sqlcmd 指令碼變數)。 此範例也會啟動此作業。

-- To avoid storing the login and password in the script file, the values 
-- are passed into SQLCMD as scripting variables. For information about 
-- how to use scripting variables on the command line and in SQL Server
-- Management Studio, see the "Executing Replication Scripts" section in
-- the topic "Programming Replication Using System Stored Procedures".

DECLARE @publicationDB AS sysname;
DECLARE @publication AS sysname;
DECLARE @login AS sysname;
DECLARE @password AS sysname;
SET @publicationDB = N'AdventureWorks2022'; --publication database
SET @publication = N'AdvWorksCustomerTran'; -- transactional publication name
SET @login = $(Login);
SET @password = $(Password);

USE [AdventureWorks]

-- Enable transactional and snapshot replication on the publication database.
EXEC sp_replicationdboption 
  @dbname = @publicationDB, 
  @optname = N'publish',
  @value = N'true';

-- Execute sp_addlogreader_agent to create the agent job. 
EXEC sp_addlogreader_agent 
  @job_login = @login, 
  @job_password = @password,
  -- Explicitly specify the security mode used when connecting to the Publisher.
  @publisher_security_mode = 1;

-- Create new transactional publication, using the defaults. 
USE [AdventureWorks2022]
EXEC sp_addpublication 
  @publication = @publication, 
  @description = N'transactional publication';

-- Create a new snapshot job for the publication, using the defaults.
EXEC sp_addpublication_snapshot 
  @publication = @publication,
  @job_login = @login,
  @job_password = @password;

-- Start the Snapshot Agent job.
EXEC sp_startpublication_snapshot @publication = @publication;
GO

此範例會建立合併式發行集,並針對此發行集加入快照集代理程式作業 (使用 sqlcmd 變數)。 此範例也會啟動此作業。

-- To avoid storing the login and password in the script file, the value 
-- is passed into SQLCMD as a scripting variable. For information about 
-- how to use scripting variables on the command line and in SQL Server
-- Management Studio, see the "Executing Replication Scripts" section in
-- the topic "Programming Replication Using System Stored Procedures".

DECLARE @publicationDB AS sysname;
DECLARE @publication AS sysname;
DECLARE @login AS sysname;
DECLARE @password AS sysname;
SET @publicationDB = N'AdventureWorks2022'; 
SET @publication = N'AdvWorksSalesOrdersMerge'; 
SET @login = $(Login);
SET @password = $(Password);

-- Enable merge replication on the publication database.
USE master
EXEC sp_replicationdboption 
  @dbname = @publicationDB, 
  @optname=N'merge publish',
  @value = N'true';

-- Create new merge publication, using the defaults. 
USE [AdventureWorks]
EXEC sp_addmergepublication 
  @publication = @publication, 
  @description = N'Merge publication.';

-- Create a new snapshot job for the publication, using the defaults.
EXEC sp_addpublication_snapshot 
  @publication = @publication,
  @job_login = @login,
  @job_password = @password;

-- Start the Snapshot Agent job.
EXEC sp_startpublication_snapshot @publication = @publication;
GO

下列命令列引數會啟動快照集代理程式,以針對合併式發行集產生快照集。

注意

加入了分行符號,以提升可讀性。 在批次檔中,必須在單一行中撰寫命令。

  
REM -- Declare variables  
SET Publisher=%InstanceName%  
SET PublicationDB=AdventureWorks2022   
SET Publication=AdvWorksSalesOrdersMerge   
  
REM --Start the Snapshot Agent to generate the snapshot for AdvWorksSalesOrdersMerge.  
"C:\Program Files\Microsoft SQL Server\120\COM\SNAPSHOT.EXE" -Publication %Publication%   
-Publisher %Publisher% -Distributor %Publisher% -PublisherDB %PublicationDB%   
-ReplicationType 2 -OutputVerboseLevel 1 -DistributorSecurityMode 1  
  

使用 Replication Management Objects (RMO)

快照集代理程式會在發行集建立之後產生快照集。 您可以使用 Replication Management Objects (RMO) 和對複寫代理程式功能的直接 Managed 程式碼存取,以程式設計的方式產生這些快照集。 您使用的物件取決於複寫的類型而定。 您可以使用 SnapshotGenerationAgent 物件同步啟動快照集代理程式,或是使用代理程式作業以非同步方式啟動它。 在產生初始快照集之後,此快照集會在第一次同步處理訂閱時,傳送及套用到訂閱者。 每當現有的快照集不再包含有效且最新的資料時,您就需要重新執行此代理程式。 如需詳細資訊,請參閱維護發行集

重要

可能的話,會在執行階段提示使用者輸入安全性認證。 如果您必須儲存認證,請使用 Microsoft Windows .NET Framework 提供的密碼編譯服務

啟動快照集代理程式作業 (非同步) 來針對快照式或交易式發行集產生初始快照集

  1. 使用 ServerConnection 類別建立與發行者的連接。

  2. 建立 TransPublication 類別的執行個體。 設定發行集的 NameDatabaseName 屬性,並將 ConnectionContext 屬性設定為在步驟 1 中建立的連接。

  3. 呼叫 LoadProperties 方法以載入物件的剩餘屬性。 如果此方法傳回 false,則表示步驟 2 中的發行集屬性定義不正確,或者該發行集不存在。

  4. 如果 SnapshotAgentExists 的值是 false,請呼叫 CreateSnapshotAgent 來針對這個發行集建立快照集代理程式作業。

  5. 呼叫 StartSnapshotGenerationAgentJob 方法來啟動代理程式作業,以針對這個發行集產生快照集。

  6. (選擇性) 當 SnapshotAvailable 的值是 true時,表示快照集可供訂閱者使用。

執行快照集代理程式 (同步) 來針對快照式或交易式發行集產生初始快照集

  1. 建立 SnapshotGenerationAgent 類別的執行個體,並設定下列必要的屬性:

  2. 針對 Transactional 設定 SnapshotReplicationType的值。

  3. 呼叫 GenerateSnapshot 方法。

啟動快照集代理程式作業 (非同步) 來針對合併式發行集產生初始快照集

  1. 使用 ServerConnection 類別建立與發行者的連接。

  2. 建立 MergePublication 類別的執行個體。 設定發行集的 NameDatabaseName 屬性,並將 ConnectionContext 屬性設定為在步驟 1 中建立的連接。

  3. 呼叫 LoadProperties 方法以載入物件的剩餘屬性。 如果此方法傳回 false,則表示步驟 2 中的發行集屬性定義不正確,或者該發行集不存在。

  4. 如果 SnapshotAgentExists 的值是 false,請呼叫 CreateSnapshotAgent 來針對這個發行集建立快照集代理程式作業。

  5. 呼叫 StartSnapshotGenerationAgentJob 方法來啟動代理程式作業,以針對這個發行集產生快照集。

  6. (選擇性) 當 SnapshotAvailable 的值是 true時,表示快照集可供訂閱者使用。

執行快照集代理程式 (同步) 來針對合併式發行集產生初始快照集

  1. 建立 SnapshotGenerationAgent 類別的執行個體,並設定下列必要的屬性:

  2. Merge 設定 ReplicationType的值。

  3. 呼叫 GenerateSnapshot 方法。

範例 (RMO)

這個範例會同步執行快照集代理程式,以針對交易式發行集產生初始快照集。

// Set the Publisher, publication database, and publication names.
string publicationName = "AdvWorksProductTran";
string publicationDbName = "AdventureWorks2022";
string publisherName = publisherInstance;
string distributorName = publisherInstance;

SnapshotGenerationAgent agent;

try
{
    // Set the required properties for Snapshot Agent.
    agent = new SnapshotGenerationAgent();
    agent.Distributor = distributorName;
    agent.DistributorSecurityMode = SecurityMode.Integrated;
    agent.Publisher = publisherName;
    agent.PublisherSecurityMode = SecurityMode.Integrated;
    agent.Publication = publicationName;
    agent.PublisherDatabase = publicationDbName;
    agent.ReplicationType = ReplicationType.Transactional;

    // Start the agent synchronously.
    agent.GenerateSnapshot();

}
catch (Exception ex)
{
    // Implement custom application error handling here.
    throw new ApplicationException(String.Format(
        "A snapshot could not be generated for the {0} publication."
        , publicationName), ex);
}
' Set the Publisher, publication database, and publication names.
Dim publicationName As String = "AdvWorksProductTran"
Dim publicationDbName As String = "AdventureWorks2022"
Dim publisherName As String = publisherInstance
Dim distributorName As String = publisherInstance

Dim agent As SnapshotGenerationAgent

Try
    ' Set the required properties for Snapshot Agent.
    agent = New SnapshotGenerationAgent()
    agent.Distributor = distributorName
    agent.DistributorSecurityMode = SecurityMode.Integrated
    agent.Publisher = publisherName
    agent.PublisherSecurityMode = SecurityMode.Integrated
    agent.Publication = publicationName
    agent.PublisherDatabase = publicationDbName
    agent.ReplicationType = ReplicationType.Transactional

    ' Start the agent synchronously.
    agent.GenerateSnapshot()

Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
     "A snapshot could not be generated for the {0} publication." _
     , publicationName), ex)
End Try

這個範例會以非同步方式啟動代理程式作業,以針對交易式發行集產生初始快照集。

// Set the Publisher, publication database, and publication names.
string publicationName = "AdvWorksProductTran";
string publicationDbName = "AdventureWorks2022";
string publisherName = publisherInstance;

TransPublication publication;

// Create a connection to the Publisher using Windows Authentication.
ServerConnection conn;
conn = new ServerConnection(publisherName);

try
{
    // Connect to the Publisher.
    conn.Connect();

    // Set the required properties for an existing publication.
    publication = new TransPublication();
    publication.ConnectionContext = conn;
    publication.Name = publicationName;
    publication.DatabaseName = publicationDbName;

    if (publication.LoadProperties())
    {
        // Start the Snapshot Agent job for the publication.
        publication.StartSnapshotGenerationAgentJob();
    }
    else
    {
        throw new ApplicationException(String.Format(
            "The {0} publication does not exist.", publicationName));
    }
}
catch (Exception ex)
{
    // Implement custom application error handling here.
    throw new ApplicationException(String.Format(
        "A snapshot could not be generated for the {0} publication."
        , publicationName), ex);
}
finally
{
    conn.Disconnect();
}
' Set the Publisher, publication database, and publication names.
Dim publicationName As String = "AdvWorksProductTran"
Dim publicationDbName As String = "AdventureWorks2022"
Dim publisherName As String = publisherInstance

Dim publication As TransPublication

' Create a connection to the Publisher using Windows Authentication.
Dim conn As ServerConnection
conn = New ServerConnection(publisherName)

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Set the required properties for an existing publication.
    publication = New TransPublication()
    publication.ConnectionContext = conn
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName

    If publication.LoadProperties() Then
        ' Start the Snapshot Agent job for the publication.
        publication.StartSnapshotGenerationAgentJob()
    Else
        Throw New ApplicationException(String.Format( _
         "The {0} publication does not exist.", publicationName))
    End If
Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
     "A snapshot could not be generated for the {0} publication." _
     , publicationName), ex)
Finally
    conn.Disconnect()
End Try

套用初始快照集時封鎖

如果您有多個發行集,該發行集會將資料發行至訂閱者端的一個資料庫,同時套用初始快照集,您會發現一次只能有一個發行集套用其快照集。

檢閱 SQL 活動時,您可能會看到類似下列的等候資源:

APP: 18:16384:[snapshot_delivery_in_progress_Tr]:(9bcdaf92)
APP: 5:16384:[snapshot_delivery_in_progress_Er]:(3c3b7db9
)

查詢鎖定行為可能會顯示類似下列的資源:

APP 16384:[appname]:(fbe42d68) XAPP 16384:[snapshot_del]:(9bcdaf92) X

這是設計的行為。  其發生原因是使用應用程式鎖定來防止多個複寫代理程式同時將不同發行集的快照集套用至相同的訂閱者資料庫。  由於應用程式鎖定包含訂閱者資料庫的名稱,因此任何發行至相同訂閱者資料庫的發行集都會受到影響。  結果是一次只能將一個快照集插入訂閱者資料庫中。

在此情況下會使用獨佔鎖定,協助避免複寫代理程式彼此變成死結的可能性。

若要解決此問題,請為每個發行集指定不同的訂閱者資料庫。

另請參閱

建立發行集
建立提取訂閱
建立發送訂閱
指定同步處理排程
使用快照集初始化訂閱
複寫管理物件概念
複寫安全性最佳作法
Replication System Stored Procedures Concepts
以指令碼變數使用 sqlcmd