Konfigurieren und Behandeln von Problemen mit dem SubscriptionStreams-Parameter des Verteilungs-Agent in SQL Server

Ursprüngliche Produktversion: SQL Server (alle unterstützten Versionen)
Ursprüngliche KB-Nummer: 953199

Dieser Artikel enthält weitere Informationen zum Parameter SubscriptionStreams, zu bewährten Methoden bei der Verwendung dieses Parameters und zur zugehörigen Problembehandlung.

Einführung

Der -Parameter SubscriptionStreams kann verwendet werden, um die Anzahl der Verbindungen zu steuern. In einer Transaktionsreplikation in Microsoft SQL Server können Sie den Parameter verwenden, um mehrere Verbindungen zu aktivieren, die der Verteilungs-Agent verwendet, um Batches von Änderungen parallel auf einen Abonnenten anzuwenden. Dieser Vorgang verbessert den Replikationsdurchsatz erheblich. Gleichzeitig kann der Verteilungs-Agent weiterhin viele der gleichen Transaktionsmerkmale beibehalten, wie wenn der Verteilungs-Agent eine einzelne Verbindung verwendet, um die Änderungen anzuwenden. Wenn eine der Verbindungen nicht ausgeführt oder committet werden kann, brechen alle Verbindungen den aktuellen Batch ab, und der Agent verwendet einen einzelnen Stream, um die fehlerhaften Batches erneut zu versuchen. Bevor diese Wiederholungsphase abgeschlossen ist, können temporäre Transaktionsinkonsistenzen auf dem Abonnenten vorliegen. Nachdem die fehlerhaften Batches erfolgreich committet wurden, wird der Abonnent wieder in den Zustand der Transaktionskonsistenz versetzt.

Wenn Sie einen Wert von 2 oder höher für den Parameter SubscriptionStreamsangeben, kann sich die Reihenfolge, in der Transaktionen auf dem Abonnenten empfangen werden, von der Reihenfolge unterscheiden, in der sie auf dem Herausgeber vorgenommen wurden. Wenn dieses Verhalten während der Synchronisierung Einschränkungsverletzungen verursacht, sollten Sie die NOT FOR REPLICATION Option verwenden, um die Erzwingung von Einschränkungen während der Synchronisierung zu deaktivieren. Weitere Informationen finden Sie unter Steuern des Verhaltens von Triggern und Einschränkungen in der Synchronisierung.

Faktoren, die vor der Aktivierung von SubscriptionStreams zu berücksichtigen sind

SubscriptionStreams kümmert sich hauptsächlich um die Latenz zwischen Verteiler und Abonnent. Bevor Sie sich also für SubscriptionStreamsentscheiden, stellen Sie sicher, dass tatsächlich eine Latenz zwischen Verteiler und Abonnent besteht. Sie können entweder Ablaufverfolgungstoken im Replikationsmonitor oder Leistungsmonitor Indikatoren wie SQLServer:Replication Dist verwenden.>Dist:Delivery Latency, um eine Vorstellung von der Latenzebene zu erhalten.

Die Latenz zwischen Verteiler und Abonnent kann aus vielen Gründen verursacht werden, z. B. aus den folgenden Gründen:

  • Blockieren beim Verteiler oder Abonnenten
  • Jeder Engpass, entweder beim Verteiler oder Beim Abonnenten, z. B. langsame Datenträgerlaufwerke, langsame Netzwerkbandbreite und veraltete Statistiken
  • Massentransaktionen, die vom Verleger stammen
  • Rate der eingehenden Transaktionen vom Verleger ist zu hoch
  • Trigger oder unnötige Indizes in der abonnierten Datenbank

Der Datenbankadministrator (DBA) muss einen Anruf entgegennehmen und testen, ob SubscriptionStreams er ihnen helfen wird oder nicht. Im Falle einer Blockierung auf dem Abonnenten hilft es beispielsweise nicht, die Anzahl der gleichzeitigen Verbindungen zu erhöhen, kann die Situation jedoch verschlimmern. Während in Situationen wie der Rate eingehender Transaktionen von Publisher zu hoch ist und Sie der Meinung sind, dass ein einzelner Thread für die Verteilungs-Agent die eingehende Last nicht bewältigen kann, können Sie erwägen, den Wert des Parameters SubscriptionStreams auf =2 zu >erhöhen. Dies kann auch bei langsamen Netzwerken und langsamen Datenträgern hilfreich sein. Im Idealfall ist der maximale Wert für diesen Parameter 64, aber der empfohlene Wert (oder ein guter Wert für den Anfang) entspricht der Anzahl der physischen Prozessoren am Ziel (Abonnent).

Konfigurieren des Parameters SubscriptionStreams

SubscriptionStreamsist einer dieser Parameter, der in Verteilungs-Agent Profile im Replikationsmonitor nicht sichtbar ist. Sie können einen Wert für diesen Agent-Parameter mithilfe @subscriptionstreams von sp_addsubscription (Transact-SQL) angeben oder diesen Parameter dem Befehlsabschnitt des Verteilungs-Agents hinzufügen, indem Sie das folgende Verfahren verwenden:

  1. Öffnen Sie den Replikationsmonitor, erweitern Sie Mein Verleger, und wählen Sie ihre Publikation im linken Fenster aus. Im rechten Bereichsfenster wird im Abschnitt Alle Abonnements die Liste aller Abonnenten dieser Veröffentlichung angezeigt.

  2. Klicken Sie mit der rechten Maustaste auf den Abonnenten, den Sie den Parameter SubscriptionStreams aktivieren möchten, und wählen Sie Details anzeigen aus. Ein neues Fenster mit den Verteilungs-Agent Sitzungsdetails wird angezeigt.

  3. Wählen Sie in diesem neuen Fenster oben in der Menüleiste Aktion aus, und wählen Sie Verteilungs-Agent Auftragseigenschaften aus. Dadurch wird das Fenster Auftragseigenschaften für die Verteilungs-Agent geöffnet.

  4. Wählen Sie im linken Bereichsfenster Schritte und dann im rechten Bereichsfenster Agent ausführen aus, und wählen Sie dann Bearbeiten aus. Ein neues Fenster wird angezeigt.

  5. Scrollen Sie zum Ende des Befehlsabschnitts (ganz rechts), und fügen Sie den Parameter -SubscriptionStreams 6 an.

  6. Speichern Sie die Einstellungen, und starten Sie den Verteilungs-Agent Auftrag neu. Ein Neustart von Verteilungs-Agent ist erforderlich, um die Änderungen zu implementieren.

Hinweis

Im obigen Beispiel ist auf 6 festgelegt, was bedeutet, SubscriptionStreams dass wir nach sechs parallelen Verbindungen für Verteilungs-Agent auf dem Abonnenten suchen. Sie können diese Zahl gemäß Ihrer Umgebung und Ihren Tests festlegen.

Bestimmen der Anzahl von Datenströmen

Sie können Leistungsverbesserungen feststellen, indem Sie den Parameter SubscriptionStreamsverwenden. Wenn es eine Verbesserung gibt, kann die Verbesserung nominal sein. Es ist schwierig zu bestimmen, welche Art von Leistungsverbesserung jedes Datenträgersubsystem auf dem Markt mit SubscriptionStreamsbietet. Daher wird empfohlen, eine Testumgebung vorzubereiten, die die Produktionsumgebung simuliert. Sie können Szenarien testen, die verwenden SubscriptionStreams , indem Sie verschiedene Konfigurationswerte und ein Szenario verwenden, das nicht verwendet SubscriptionStreams.

Es wird empfohlen, Auslastungstests für die Veröffentlichung und das Abonnement durchzuführen, um die Leistungsverbesserungen zu ermitteln, die Sie mithilfe von SubscriptionStreamserhalten können. Sie sollten die Leistungsbaselinetests durchführen, um den erwarteten Durchsatz des Datenträgersubsystems zu verstehen. Bevor Sie jeden Test ausführen, wenden Sie viele Änderungen an, um eine Last auf dem Verleger zu erstellen. Stellen Sie beim Erstellen des Ladevorgangs sicher, dass Verteilungs-Agent nicht ausgeführt wird. Wenn die Replikation über eine ausreichende Latenz verfügt, führen Sie die Verteilungs-Agent aus, um die Leistung für die folgenden Konfigurationen zu testen:

  • Verwenden Sie nicht den Parameter SubscriptionStreams.
  • Legen Sie den Wert von SubscriptionStreams so fest, dass er gleich der Anzahl der Prozessoren auf dem Server ist. Wenn der Server beispielsweise über acht Prozessoren verfügt, legen Sie den Wert von SubscriptionStreams auf 8 fest.
  • Geben Sie verschiedene Werte für SubscriptionStreams an, um die optimale Konfiguration zu erhalten.

Wenn Sie den Test ausführen, können Sie die folgenden Leistungsindikatoren des Verteilungs-Agent überwachen:

  • Dist: Gelieferte Cmds/s
  • Dist: Übermittlungslatenz

Verhalten des Verteilungs-Agent nach dem Angeben des Parameters SubscriptionStreams

Die Verteilungs-Agent behält die Anzahl der Sitzungen/Verbindungen bei, die Sie in SubscriptionStreamsangeben. Die Verteilungs-Agent verwendet diese Sitzungen, um Änderungen auf dem Abonnenten anzuwenden.

Nachdem Sie jedoch angegeben SubscriptionStreams haben und die Verteilungs-Agent für einige Zeit ausgeführt wird, kann die Verteilungs-Agent nur eine Sitzung verwenden, um Änderungen auf den Abonnenten anzuwenden.

Gründe für die Verteilungs-Agent, nur eine Sitzung zu verwenden

Die Verteilungs-Agent kann aus vielen Gründen nur eine Sitzung verwenden. Dies sind die häufigsten Gründe:

  • Wenn die Verteilungs-Agent Änderungen anwendet, löst eine der Sitzungen einen Fehler aus.

    Beispielsweise fügt der Verteilungs-Agent eine Zeile mithilfe einer Sitzung in eine untergeordnete Tabelle ein. Wenn dies geschieht, bevor die Verteilungs-Agent die entsprechende Zeile mithilfe einer anderen Sitzung in die übergeordnete Tabelle einfügt, löst eine Fremdschlüsseleinschränkungsverletzung eine Fehlermeldung aus.

  • Der blockierende Überwachungsthread erkennt eine Blockierung. Eine Blockierung kann aus einem der folgenden Gründe auftreten:

    • Die Verteilungs-Agent führt einen INSERT - und einen UPDATE -Vorgang für eine Tabelle auf dem Abonnenten mithilfe verschiedener Sitzungen aus. Wenn die Tabelle einen eindeutigen nicht gruppierten Index enthält, kann eine Blockierung zwischen den beiden Sitzungen auftreten, wenn die Verteilungs-Agent die Indexschlüssel der Tabelle aktualisiert.

    • Auf dem Abonnenten führt die Verteilungs-Agent DML-Anweisungen (Data Manipulation Language) für mehrere Tabellen aus. Wenn eine indizierte Sicht für diese Tabellen definiert ist, kann eine Blockierung zwischen den beiden Sitzungen auftreten, wenn die indizierte Sicht die freigegebenen Indexschlüssel aktualisiert.

    • Die Verteilungs-Agent führt eine DML-Anweisung für eine Tabelle auf dem Abonnenten mithilfe einer Sitzung aus. DML-Trigger werden in dieser Tabelle definiert. Die DML-Trigger führen DML-Anweisungen für eine andere Tabelle aus, die mithilfe einer anderen Sitzung aktualisiert wird. In dieser Situation kann es zu einer Blockierung zwischen den beiden Sitzungen kommen.

Es wird dringend empfohlen, die folgenden Datenbankobjekte nicht in der Abonnentendatenbank zu verwenden:

  • Fremdschlüsseleinschränkungen
  • Eindeutige nicht gruppierte Indizes
  • Indizierte Sichten
  • DML-Trigger, die eine Blockierung zwischen Sitzungen verursachen können

Ermitteln, ob die Verteilungs-Agent nur eine Sitzung verwendet hat

Verwenden Sie dazu eine der folgenden Methoden:

Hinweis

Obwohl Sie mit Methode 1 bestätigen können, dass die Verteilungs-Agent nicht zur Verwendung einer Sitzung gewechselt ist, müssen Sie Methode 2 oder Methode 3 verwenden, um zu bestätigen, dass die Verteilungs-Agent zu einer Einzigen Sitzung gewechselt ist.

  • Methode 1

    Fragen Sie die dynamische Verwaltungssicht (Dynamic Management View, DMV) sys.dm_exec_sessions für die Verbindungssitzungen mit der Abonnementdatenbank ab. Wenn nur eine Verbindungssitzung angezeigt wird, hat die Verteilungs-Agent möglicherweise zu einer Sitzung gewechselt. Wenn mehr als eine Verbindungssitzung angezeigt wird, verwendet der Verteilungs-Agent weiterhin die angegebene Anzahl von Sitzungen.

    Verwenden Sie Methode 2 oder Methode 3, um zu bestätigen, dass die Verteilungs-Agent zur Verwendung einer Sitzung gewechselt ist.

  • Methode 2

    Fragen Sie die Spalte comments der Tabelle ab, die in der Verteilungsdatenbank msdistribution_history. Wenn das Ergebnis der Abfrage den folgenden Eintrag enthält, hat die Verteilungs-Agent zu einer Sitzung gewechselt:

    Der Prozess konnte den letzten Batch im Multistreamingmodus nicht abschließen, er wurde auf den Einzelverbindungsmodus zurückgesetzt und versucht den Vorgang erneut.

  • Methode 3

    Untersuchen Sie die Ausgabedatei des Verteilungs-Agent. Die Verteilungs-Agent hat nur eine Sitzung verwendet, wenn die Ausgabedatei dieselbe Fehlermeldung wie Methode 2 enthält.

    Die folgende Ausgabedatei ist ein Beispiel:

    Date/Time 100 transaction(s) with 1181 command(s) were delivered. 
    Date/Time 100 transaction(s) with 2672 command(s) were delivered. 
    Date/Time Bucket 6 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 1 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 3 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 0 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 5 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 2 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 7 aborted the wait for Ready To Commit event, deadlock found between spid 117 and 114 
    Date/Time Bucket 4 aborted the wait for Ready To Commit event, due to thread shutdown event 
    ... 
    Date/Time Number of subscription streams has been reset from 8 to 1, state 4. 
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    Date/Time Disconnecting from Subscriber 
    SQLInstance 
    
    
    Date/Time Connecting to Subscriber 
    SQLInstance 
    
    Date/Time The process failed to complete last batch in multi-streaming mode, it has been reset to single connection mode and is retrying the operation. 
    Date/Time 21 transaction(s) with 390 command(s) were delivered.
    

Behandeln von Problemen bei einem Verteilungs-Agent, bei dem nur eine Sitzung verwendet wird

  1. Führen Sie die SQL Server Profiler auf dem Abonnenten aus, um das Berichtsereignis Blockierter Prozess und das Ausnahmeereignis zu erfassen. Diese Ereignisse zeichnen Blockierungen und Fehler auf, die auftreten, wenn die Verteilungs-Agent Änderungen anwendet.

    Hinweis

    Das Ausnahmeereignis kann durch jede Art von Fehler verursacht werden, die mit dem Problem verbunden sein können. Der Fehler kann beispielsweise durch eine Verletzung der Fremdschlüsseleinschränkung verursacht werden.

  2. Verwenden Sie eine der Methoden im Abschnitt How to determine whether the Verteilungs-Agent has switched to using only one session to monitor the Verteilungs-Agent.

  3. Wenn die Verteilungs-Agent zur Verwendung einer Sitzung gewechselt ist, beenden Sie die Ablaufverfolgung.

  4. Rufen Sie aus der Ausgabedatei des Verteilungs-Agent oder aus der Spalte start_time der Tabelle msdistribution_history den Zeitstempel des folgenden Eintrags ab:

    Der Prozess konnte den letzten Batch im Multistreamingmodus nicht abschließen, er wurde auf den Einzelverbindungsmodus zurückgesetzt und versucht den Vorgang erneut.

  5. Öffnen Sie die Ablaufverfolgungsdatei (.trc) auf dem Abonnenten. Suchen Sie ein blockierende Skript oder ein Ausnahmeereignis, dessen Zeitstempel dem in Schritt 4 abgerufenen Zeitstempel entspricht oder sich sehr nahe am Zeitstempel befindet.

  6. Wenn Sie eine Ausnahme bemerken, überprüfen Sie die Details der Ausnahme, um die Ursache zu ermitteln. Die Ausnahme kann beispielsweise durch eine Verletzung der Fremdschlüsseleinschränkung verursacht werden. Wenn ja, empfiehlt es sich, die Fremdschlüsseleinschränkung in der Abonnentendatenbank zu entfernen.

    Wenn Sie ein blockierende Skript bemerken, wird das Problem durch eine Blockierung verursacht. Im Folgenden finden Sie ein Beispiel für ein Blockierungsskript:

    <blocked-process-report monitorLoop="41589"> 
        <blocked-process> 
            <process id="process3a6d438" taskpriority="0" logused="24592" waitresource="KEY: 6:72057594375700480 (0100e420fa5a)" waittime="9937" ownerId="568644832" transactionname="user_transaction" lasttranstarted="2008-05-05T04:55:04.430" XDES="0xa5619e370" lockMode="X" schedulerid="11" kpid="6104" status="suspended" spid="58" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2008-05-05T04:55:04.553" lastbatchcompleted="2008-05-05T04:55:04.430" clientapp=<DistributionAgentProgram> hostname=<servername> hostpid="3980" loginname=<SQLAgentAcct>  isolationlevel="read committed (2)" xactid="568644832" currentdb="6" lockTimeout="4294967295" clientoption1="671090784" clientoption2="128056"> 
                <executionStack> 
                <frame line="5" stmtstart="642" stmtend="1600" sqlhandle="0x0300060057a14477a8c6dd00609a00000100000000000000"/> 
                </executionStack> 
                <inputbuf> 
                Proc [Database Id = 6 Object Id = 2000986455]
                </inputbuf> 
            </process> 
        </blocked-process> 
        <blocking-process> 
            <process status="sleeping" spid="68" sbid="0" ecid="0" priority="0" transcount="1" lastbatchstarted="2008-05-05T04:55:04.570" lastbatchcompleted="2008-05-05T04:55:05.103" clientapp=<DistributionAgentProgram> hostname=<servername> hostpid="3980" loginname=<SQLAgentAcct> isolationlevel="read committed (2)" xactid="568644998" currentdb="6" lockTimeout="4294967295" clientoption1="671090784" clientoption2="128056"> 
            <executionStack/> 
            <inputbuf> 
            Proc [Database Id = 6 Object Id = 1172459501]
            </inputbuf> 
            </process> 
        </blocking-process> 
    </blocked-process-report> 
    

    Das blockierende Skript zeichnet eine blockierte Sitzung und eine blockierende Sitzung auf. Die blockierte Sitzung beginnt mit dem Tag <blocked-process>. Die blockierende Sitzung beginnt mit dem Tag <blocking-process>.

  7. Suchen Sie die Object Id des -Objekts Proc in der blockierten Sitzung und in der blockierenden Sitzung.

    Im Beispielblockierungsskript ist 2000986455der Object Id von Proc in der blockierten Sitzung . Der Object Id von Proc in der blockierenden Sitzung ist 1172459501.

  8. Fragen Sie in der Abonnementdatenbank die Sicht sys.objects ab, indem Sie die Spalte object_id angeben, die den Objekt-IDs entspricht, die Sie in Schritt 7 abgerufen haben. In diesem Fall können Sie die Objektnamen bestimmen.

    Führen Sie beispielsweise die folgende Abfrage im Kontext der Abonnementdatenbank aus:

    USE <SubDBName> 
    GO 
    SELECT name FROM sys.objects 
    WHERE object_id = 1172459501 OR object_id = 2000986455 
    

    Hinweis

    • Der Platzhalter <SubDBName> stellt den Namen der Abonnementdatenbank dar.
    • In der Regel handelt es sich bei diesen Objekten um gespeicherte Prozeduren, die in der Replikation verwendet werden.
  9. Bestimmen Sie den Index oder die indizierte Sicht, die eine Blockierung verursacht. Gehen Sie dazu wie folgt vor:

    1. Suchen Sie im blockierenden Skript den Wert der Eigenschaft waitresource.

      Im Beispielblockierungsskript ist 72057594375700480der Wert von waitresource .

    2. Fragen Sie die Sicht sys.partitions ab, um die Objekt-ID und die Index-ID abzurufen, indem Sie die Spalte PARTITION_ID angeben, die dem Wert des entspricht, den waitresource Sie in Schritt 9a abgerufen haben.

      Führen Sie beispielsweise die folgende Abfrage aus:

      SELECT object_id, index_id FROM SYS.PARTITIONS WHERE PARTITION_ID=72057594375700480
      
    3. Fragen Sie in der Abonnementdatenbank die Sicht sys.indexes ab, um den Index mithilfe der Objekt-ID und der Index-ID zu ermitteln, die Sie in Schritt 9b abgerufen haben.

      Führen Sie beispielsweise die folgende Abfrage aus:

      USE <SubDBName> 
      GO 
      SELECT name, type_desc, is_unique FROM sys.indexes 
      WHERE object_id = <objID> and index_id = <idxID>
      

      Hinweis

      • Der Platzhalter <objID> stellt die Objekt-ID dar, die Sie in Schritt 9b abgerufen haben.
      • Der Platzhalter <idxID> stellt die Index-ID dar, die Sie in Schritt 9b abgerufen haben.
  10. Wenn die Blockierung durch eine indizierte Sicht verursacht wird, empfiehlt es sich, die indizierte Ansicht zu löschen. Wenn die Blockierung durch einen eindeutigen nicht gruppierten Index verursacht wird, empfiehlt es sich, den Index zu löschen und dann einen nicht eindeutigen Index neu zu erstellen.

Beschreibung des blockierenden Überwachungsthreads

Die Verteilungs-Agent verwaltet einen blockierenden Überwachungsthread, der Blockierungen zwischen den Sitzungen erkennt. Wenn der blockierende Überwachungsthread eine Blockierung zwischen den Sitzungen erkennt, wechselt der Verteilungs-Agent zu einer Sitzung, um den aktuellen Batch von Befehlen erneut anzuwenden, den die Verteilungs-Agent zuvor nicht angewendet haben.

Weitere Informationen zum blockierenden Überwachungsthread finden Sie unter Blockieren des Monitorthreads.

Fortsetzen mehrerer Sitzungen durch die Verteilungs-Agent

Bevor die Verteilungs-Agent mehrere Sitzungen fortsetzen kann, muss der Verteilungs-Agent die gespeicherte Prozedur sp_MSget_repl_commands ausführen, um die Verteilungsdatenbank für die Befehle erneut abzufragen, die nicht auf den Abonnenten angewendet wurden. Anschließend muss der Verteilungs-Agent alle diese Befehle auf dem Abonnenten anwenden, bevor der Verteilungs-Agent mehrere Sitzungen fortsetzen kann. In einer latenten Replikationsumgebung kann der Verteilungs-Agent mehrere Sitzungen nicht fortsetzen, da der Verteilungs-Agent viele Befehle auf dem Abonnenten anwenden muss, bevor der Verteilungs-Agent mehrere Sitzungen fortsetzen kann.

Um den gesamten Prozess nachzuverfolgen, untersuchen Sie die Ausgabedatei des Verteilungs-Agent.