建立並套用初始快照

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

本文說明如何使用 SQL Server Management Studio、Transact-SQL 或複寫管理物件(RMO)在 SQL Server 中建立並套用初始快照。 使用參數化篩選的合併式發行集需要一個兩段式快照集。 如需詳細資訊,請參閱 使用參數化篩選建立合併式發行集的快照。
快照代理程式會在發行建立之後產生快照。 你可以產生快照:

對於合併複寫,快照集代理程式 每次執行都會產生快照。 對於交易式複寫,快照的產生取決於發行集屬性 immediate_sync 的設定。 若該屬性設定為 TRUE(使用新發佈精靈時的預設值),快照集代理程式 每次執行都會產生快照,並可隨時將快照套用給訂閱者。 若屬性設定為 FALSE(使用 sp_addpublication 時的預設),快照集代理程式 僅在自上次 快照集代理程式 執行後新增訂閱時產生快照;訂閱者必須等待快照集代理程式完成後才能同步。

預設情況下,快照集代理程式 會將產生的快照儲存在位於分發器的預設快照資料夾中。 你也可以將快照檔案儲存在可移除的媒體上,例如可移動磁碟、CD-ROM,或是預設快照資料夾以外的位置。 你也可以壓縮檔案,讓它們更容易儲存和傳輸,並在 快照集代理程式 對訂閱者套用快照前後執行腳本。 如需這些選項的詳細資訊,請參閱 Snapshot Options。

若快照是用於使用參數化過濾器的合併發佈,快照集代理程式 會透過兩部分流程建立快照。 首先,它建立一個結構快照,包含複製腳本和已發佈物件的結構,但不含資料。 每個訂閱會以一個快照初始化,該快照包含從結構快照複製的腳本與結構,以及屬於訂閱分割區的資料。 如需詳細資訊,請參閱 Snapshots for Merge Publications with Parameterized Filters。

當 快照集代理程式 在 Publisher 建立快照並將其儲存在預設或替代快照位置後,你可以將快照轉移給訂閱者並套用。 散發代理程式(用於快照或交易複製)或 合併代理程式(用於合併複寫)會在初始同步時傳輸快照,並將結構與資料檔案套用到訂閱者的訂閱資料庫。 預設情況下,若使用新訂閱精靈,初始同步會在建立訂閱後立即進行。 精靈的「初始化訂閱」頁面上的「初始化時」選項控制此行為。 當 快照集代理程式 在訂閱初始化後產生快照時,除非你將訂閱標記為需重新初始化,否則不會將這些快照套用至訂閱者。 如需詳細資訊,請參閱 重新初始化訂閱。

「散發代理程式」或「合併代理程式」套用初始快照後,代理程式會傳送後續更新及其他資料變更。 快照集散發並套用至「訂閱者」後,只有等待初始快照集或新快照集的「訂閱者」會受影響。 該出版物的其他訂閱者(已接收插入、更新、刪除或其他已發佈資料修改的訂閱者)則不受影響。

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

預設快照位置

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

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

修改預設快照集位置

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

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

    注意

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

  3. 選取 OK。

建立快照

預設情況下,若 SQL Server Agent 正在執行,快照集代理程式 會在您使用新發佈精靈建立發佈文件後立即產生快照。 預設情況下,散發代理程式(用於快照與交易複製)或 合併代理程式(用於合併訂閱)會對所有訂閱套用快照。 你也可以使用 SQL Server Management Studio 和 Replication Monitor 來產生快照。 如需啟動複寫監視器的詳細資訊,請參閱啟動複寫監視器。

使用 SQL Server Management Studio

  1. 在 Management Studio 中連線到發行者,然後展開伺服器節點。
  2. 展開 複寫 資料夾,然後展開 本機發佈 資料夾。
  3. 右鍵點擊你想建立快照的出版品,然後選擇「檢視 快照集代理程式 狀態」。
  4. 在檢視 快照集代理程式 狀態 - <發佈>對話框中,選擇開始。
    當快照集代理程式產生快照完成後,會顯示訊息,例如「[100%] 產生了 17 篇文章的快照。」

在複寫監視器中

  1. 在複寫監視器中,於左窗格展開一個發行者群組,然後展開一個發行者。
  2. 右鍵點擊你想產生快照的出版品,然後選擇 「產生快照」。
  3. 要查看 快照集代理程式 的狀態,請選擇 Agents 標籤。欲了解更多詳細資訊,請在網格中右鍵點擊 快照集代理程式,然後選擇「檢視詳細資料」。

使用 TRANSACT-SQL

你可以透過建立並執行 快照集代理程式 工作,或從批次檔執行 快照集代理程式 執行檔來以程式化方式建立初始快照。 產生初始快照之後,系統會在訂閱首次同步處理時,將該快照傳送到訂閱者並在該處套用。 如果你從命令提示字元或批次檔執行 快照集代理程式,當現有快照失效時,就必須重新執行該代理程式。

重要

可能的話,會在執行階段提示使用者輸入安全性認證。 如果您將認證儲存在指令碼檔案中,必須保護該檔案免於未經授權的存取。

  1. 建立快照式、交易式或合併式發行集。 如需更多資訊,請參閱建立出版項目。

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

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

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

    • (可選)若代理在連接Publisher時使用 SQL Server 認證,則 @publisher_security_mode 值為 0。 在此情況下,您也必須針對 @publisher_login 和 @publisher_password指定「SQL Server 驗證」登入資訊。

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

    重要

    當你用遠端分配器設定Publisher時,你提供的所有參數值,包括job_login和job_password,都會以純文字形式傳送給分配器。 在執行此儲存程序前,先加密 Publisher 與遠端發行商之間的連線。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)。

  3. 將文章新增至出版物。 如需詳細資訊,請參閱 定義發行項。

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

套用快照

使用 SQL Server Management Studio

快照產生後,將訂閱與 散發代理程式 或 合併代理程式 同步以套用:

  • 如果代理持續執行(交易複製的預設),它會在產生快照後自動套用快照。

  • 如果代理程式依排程執行,則會在下次執行時套用快照。

  • 如果代理程式是隨需執行,下次執行時就會套用該快照。

    如需更多有關同步訂閱的資訊,請參閱 Synchronize a Push Subscription 和 Synchronize a Pull Subscription。

使用 Transact-SQL

  1. 建立快照式、交易式或合併式發行集。 如需更多資訊,請參閱建立出版項目。

  2. 將文章新增至出版物。 如需詳細資訊,請參閱 定義發行項。

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

    • -出版品
    • -Publisher
    • -經銷商
    • -PublisherDB
    • -ReplicationType

    如果你使用 SQL Server 認證,也請指定以下參數:

    • -DistributorLogin
    • -DistributorPassword
    • -DistributorSecurityMode = 0
    • -PublisherLogin
    • -PublisherPassword
    • -PublisherSecurityMode = 0

範例 (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  
  

使用複寫管理物件 (RMO)

快照代理程式會在你建立發行集後產生快照。 你可以透過複製管理物件(RMO)並直接存取複製代理程式功能的管理程式碼,來產生這些快照。 您使用的物件取決於複寫的類型而定。 你可以用SnapshotGenerationAgent物件同步啟動 快照集代理程式,或用代理工作非同步啟動。 初始快照產生後,快照集代理程式 會將其傳送給訂閱者,並在訂閱首次同步時套用。 每當現有快照不再包含有效的最新資料時,您都需要重新執行代理程式。 如需詳細資訊,請參閱Maintain Publications。

重要

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

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

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

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

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

  4. 如果 SnapshotAgentExists 的值為 false,請呼叫 CreateSnapshotAgent 為此發行集建立快照代理程式作業。

  5. 呼叫 StartSnapshotGenerationAgentJob 方法以啟動為此發行產生快照的代理程式工作。

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

藉由執行快照代理程式(同步)來為快照式或交易式發行產生初始快照

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

  2. 針對 Transactional 設定 Snapshot 或 ReplicationType的值。

  3. 呼叫 GenerateSnapshot 方法。

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

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

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

  3. 呼叫 LoadProperties 方法以載入物件的剩餘屬性。 如果此方法傳回 false,則表示不是步驟 2 中的發行屬性定義錯誤,就是該發行項目不存在。

  4. 如果 SnapshotAgentExists 的值為 false,請呼叫 CreateSnapshotAgent 為此發行集建立快照代理程式作業。

  5. 呼叫 StartSnapshotGenerationAgentJob 方法以啟動為此發行產生快照的代理程式工作。

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

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

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

  2. 將 ReplicationType 設為 Merge。

  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

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

在此情況下會使用獨佔鎖,以避免複寫代理程式彼此發生死結的可能性。

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