Configuración y solución de problemas del parámetro SubscriptionStreams del Agente de distribución en SQL Server

Versión original del producto: SQL Server (todas las versiones admitidas)
Número de KB original: 953199

En este artículo se proporciona más información sobre el parámetro SubscriptionStreams, los procedimientos recomendados al usar este parámetro y la solución de problemas asociada.

Introducción

El parámetro SubscriptionStreams se puede usar para controlar el número de conexiones. En una replicación transaccional en Microsoft SQL Server, puede usar el parámetro para habilitar varias conexiones que el Agente de distribución usa para aplicar lotes de cambios en paralelo a un suscriptor. Esta operación mejora considerablemente el rendimiento de la replicación. Al mismo tiempo, el Agente de distribución todavía puede mantener muchas de las mismas características transaccionales que cuando el Agente de distribución usa una única conexión para aplicar los cambios. Si una de las conexiones no se puede ejecutar o confirmar, todas las conexiones anularán el lote actual y el agente usará una única secuencia para reintentar los lotes con errores. Antes de que se complete esta fase de reintento, puede haber incoherencias transaccionales temporales en el suscriptor. Una vez que los lotes con errores se confirman correctamente, el suscriptor vuelve a un estado de coherencia transaccional.

Cuando se especifica un valor de 2 o superior para el parámetro SubscriptionStreams, el orden en el que se reciben las transacciones en el suscriptor puede diferir del orden en que se realizaron en el publicador. Si este comportamiento provoca infracciones de restricciones durante la sincronización, debe usar la NOT FOR REPLICATION opción para deshabilitar la aplicación de restricciones durante la sincronización. Para obtener más información, vea Comportamiento del control de desencadenadores y restricciones en la sincronización.

Factores que se deben tener en cuenta antes de habilitar SubscriptionStreams

SubscriptionStreams principalmente se encarga de la latencia del distribuidor al suscriptor, por lo que antes de decidir ir a SubscriptionStreams, asegúrese de que realmente se está ejecutando en la latencia del distribuidor al suscriptor. Puede usar tokens de seguimiento en el Monitor de replicación o Monitor de rendimiento contadores como SQLServer:Replication Dist.>Dist:Delivery Latency para tener una idea del nivel de latencia.

La latencia del distribuidor al suscriptor puede deberse a muchas razones, como, entre otras, las siguientes:

  • Bloqueo en el distribuidor o suscriptor
  • Cualquier cuello de botella, ya sea en el distribuidor o suscriptor, como unidades de disco lentas, ancho de banda de red lento y estadísticas obsoletas
  • Transacciones masivas procedentes del publicador
  • La tasa de transacciones entrantes del publicador es demasiado alta
  • Desencadenadores o índices innecesarios en la base de datos suscrita

El administrador de bases de datos (DBA) debe realizar una llamada y probar si SubscriptionStreams va a ayudarles o no. Por ejemplo, en caso de bloqueo en el suscriptor, aumentar el número de conexiones simultáneas no ayudará, pero podría empeorar la situación. Mientras que en situaciones como la tasa de transacciones entrantes del publicador es demasiado alta y cree que un único subproceso para el Agente de distribución no puede hacer frente a la carga entrante, puede considerar la posibilidad de aumentar el valor del parámetro SubscriptionStreams a >=2. También puede ayudar en situaciones de red lenta y de disco lenta. Idealmente, el valor máximo de este parámetro es 64, pero el valor recomendado (o un buen valor por el que empezar) es igual al número de procesadores físicos en el destino (suscriptor).

Configuración del parámetro SubscriptionStreams

SubscriptionStreamses uno de esos parámetros que no están visibles en Agente de distribución Perfil en el Monitor de replicación. Puede especificar un valor para este parámetro de agente mediante @subscriptionstreamssp_addsubscription (Transact-SQL) o agregar este parámetro a la sección de comandos de trabajo del agente de distribución mediante el procedimiento siguiente:

  1. Abra El Monitor de replicación, expanda Mi publicador y seleccione la publicación en la ventana del panel izquierdo. En la ventana del panel derecho, en la sección Todas las suscripciones , verá la lista de todos los suscriptores de esta publicación.

  2. Haga clic con el botón derecho en el suscriptor que desea habilitar el parámetro SubscriptionStreams y seleccione Ver detalles. Aparecerá una nueva ventana con los detalles de la sesión de Agente de distribución.

  3. En esta nueva ventana, seleccione Acción en la barra de menús de la parte superior y seleccione Agente de distribución Propiedades del trabajo. Se abrirá la ventana Propiedades del trabajo de la Agente de distribución.

  4. Seleccione Pasos en la ventana del panel izquierdo y, a continuación, seleccione Ejecutar agente en la ventana del panel derecho y, a continuación, seleccione Editar. Aparecerá una nueva ventana.

  5. Desplácese hasta el final de la sección de comandos (el lado derecho) y anexe este parámetro -SubscriptionStreams 6.

  6. Guarde la configuración y reinicie el trabajo de Agente de distribución. Se requiere un reinicio de Agente de distribución para implementar los cambios.

Nota:

En el ejemplo anterior, SubscriptionStreams se establece en 6, lo que significa que estamos buscando seis conexiones paralelas para Agente de distribución en el suscriptor. Puede establecer este número según el entorno y las pruebas.

Determinar el número de secuencias

Es posible que observe mejoras de rendimiento mediante el parámetro SubscriptionStreams. Si hay una mejora, la mejora puede ser nominal. Es difícil determinar qué tipo de mejora de rendimiento proporcionará cada subsistema de disco en el mercado mediante SubscriptionStreams. Por lo tanto, se recomienda preparar un entorno de prueba que simule el entorno de producción. Puede probar escenarios que usan SubscriptionStreams mediante varios valores de configuración y un escenario que no usa SubscriptionStreams.

Se recomienda realizar pruebas de carga en la publicación y la suscripción para determinar las mejoras de rendimiento que puede obtener mediante SubscriptionStreams. Debe realizar las pruebas de línea base de rendimiento para comprender el rendimiento esperado del subsistema de disco. Antes de realizar cada prueba, aplique muchos cambios para crear una carga en el publicador. Al crear la carga, asegúrese de que no se ejecute Agente de distribución. Cuando la replicación tenga suficiente latencia, ejecute el Agente de distribución para probar el rendimiento de las siguientes configuraciones:

  • No use el parámetro SubscriptionStreams.
  • Establezca el valor de SubscriptionStreams para que sea igual al número de procesadores en el servidor. Por ejemplo, si el servidor tiene ocho procesadores, establezca el valor de SubscriptionStreams en 8.
  • Especifique valores diferentes para SubscriptionStreams obtener la configuración óptima.

Al realizar la prueba, puede supervisar los siguientes contadores de rendimiento de la Agente de distribución:

  • Dist: Cmds entregados por segundo
  • Dist: Latencia de entrega

Comportamiento de la Agente de distribución después de especificar el parámetro SubscriptionStreams

El Agente de distribución mantiene el número de sesiones o conexiones que especifique en SubscriptionStreams. El Agente de distribución usa estas sesiones para aplicar cambios en el suscriptor.

Sin embargo, después de especificar SubscriptionStreams y de que el Agente de distribución se ejecute durante algún tiempo, el Agente de distribución puede cambiar a usar solo una sesión para aplicar los cambios al suscriptor.

Motivos para que el Agente de distribución cambie a usar solo una sesión

El Agente de distribución puede cambiar a usar solo una sesión por muchos motivos. Las razones más comunes son las siguientes:

  • Cuando el Agente de distribución está aplicando cambios, una de las sesiones genera un error.

    Por ejemplo, el Agente de distribución inserta una fila en una tabla secundaria mediante una sesión. Si esto ocurre antes de que el Agente de distribución inserte la fila correspondiente en la tabla primaria mediante otra sesión, una infracción de restricción de clave externa genera un mensaje de error.

  • El subproceso del monitor de bloqueo detecta el bloqueo. El bloqueo puede producirse por una de las siguientes razones:

    • El Agente de distribución realiza una INSERT operación y en UPDATE una tabla en el suscriptor mediante sesiones diferentes. Si la tabla contiene un índice único no agrupado, puede producirse un bloqueo entre las dos sesiones cuando el Agente de distribución actualiza las claves de índice de la tabla.

    • En el suscriptor, el Agente de distribución ejecuta instrucciones del Lenguaje de manipulación de datos (DML) en varias tablas. Si se define una vista indizada en estas tablas, el bloqueo entre las dos sesiones puede producirse cuando la vista indizada actualiza las claves de índice compartidas.

    • El Agente de distribución ejecuta una instrucción DML en una tabla del suscriptor mediante una sesión. Los desencadenadores DML se definen en esta tabla. Los desencadenadores DML ejecutan instrucciones DML en otra tabla que se está actualizando mediante otra sesión. En esta situación, puede producirse el bloqueo entre las dos sesiones.

Se recomienda encarecidamente no usar los siguientes objetos de base de datos en la base de datos del suscriptor:

  • Restricciones de clave externa
  • Índices no clúster únicos
  • Vistas indizadas
  • Desencadenadores DML que pueden provocar bloqueos entre sesiones

Cómo determinar si el Agente de distribución ha cambiado a usar solo una sesión

Para ello, use uno de los métodos siguientes:

Nota:

Aunque puede confirmar que el Agente de distribución no ha cambiado al uso de una sesión mediante el método 1, debe usar el Método 2 o el Método 3 para confirmar que el Agente de distribución ha cambiado a mediante una sesión.

  • Método 1

    Consulte la vista de administración dinámica (DMV) sys.dm_exec_sessions para las sesiones de conexión a la base de datos de suscripciones. Si solo ve una sesión de conexión, es posible que el Agente de distribución haya cambiado a mediante una sesión. Si ve más de una sesión de conexión, el Agente de distribución sigue usando el número especificado de sesiones.

    Para confirmar que el Agente de distribución ha cambiado a usar una sesión, use el método 2 o el método 3.

  • Método 2

    Consulte la columna comments de la tabla msdistribution_history en la base de datos de distribución. Si el resultado de la consulta contiene la entrada siguiente, el Agente de distribución ha cambiado a mediante una sesión:

    El proceso no pudo completar el último lote en modo de streaming múltiple, se ha restablecido al modo de conexión única y está reintentar la operación.

  • Método 3

    Examine el archivo de salida del Agente de distribución. El Agente de distribución ha cambiado a usar solo una sesión si el archivo de salida contiene el mismo mensaje de error que el Método 2.

    El siguiente archivo de salida es un ejemplo:

    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.
    

Solución de problemas de un Agente de distribución que cambia a usar solo una sesión

  1. Ejecute el SQL Server Profiler en el suscriptor para capturar el evento de informe de proceso bloqueado y el evento Exception. Estos eventos registran el bloqueo y los errores que se producen cuando el Agente de distribución aplica cambios.

    Nota:

    El evento Exception puede deberse a cualquier tipo de error que pueda estar asociado al problema. Por ejemplo, el error puede deberse a una infracción de restricción de clave externa.

  2. Use uno de los métodos de la sección How to determinehether the Agente de distribución has switched to using only one session to monitor the Agente de distribución (Cómo determinar si el Agente de distribución ha cambiado a usar solo una sesión para supervisar el Agente de distribución).

  3. Si el Agente de distribución ha cambiado a usar una sesión, detenga el seguimiento.

  4. En el archivo de salida del Agente de distribución o de la columna start_time de la tabla msdistribution_history, obtenga la marca de tiempo de la entrada siguiente:

    El proceso no pudo completar el último lote en modo de streaming múltiple, se ha restablecido al modo de conexión única y está reintentar la operación.

  5. Abra el archivo de seguimiento (.trc) desde el suscriptor. Busque un script de bloqueo o un evento de excepción cuya marca de tiempo sea igual o muy cercana a la marca de tiempo que obtuvo en el paso 4.

  6. Si observa una excepción, examine los detalles de la excepción para determinar la causa. Por ejemplo, la excepción puede deberse a una infracción de restricción de clave externa. Si es así, se recomienda quitar la restricción de clave externa en la base de datos del suscriptor.

    Si observa un script de bloqueo, el problema se debe al bloqueo. A continuación se muestra un script de bloqueo de ejemplo:

    <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> 
    

    El script de bloqueo registra una sesión bloqueada y una sesión de bloqueo. La sesión bloqueada comienza desde la etiqueta <blocked-process>. La sesión de bloqueo comienza desde la etiqueta <blocking-process>.

  7. Busque el Object Id del objeto Proc en la sesión bloqueada y en la sesión de bloqueo.

    En el script de bloqueo de ejemplo, el Object Id de Proc en la sesión bloqueada es 2000986455. Proc en Object Id la sesión de bloqueo es 1172459501.

  8. En la base de datos de suscripciones, consulte la vista sys.objects especificando la columna object_id para que sea igual a los identificadores de objeto que obtuvo en el paso 7. Al hacerlo, puede determinar los nombres de objeto.

    Por ejemplo, ejecute la siguiente consulta en el contexto de la base de datos de suscripciones:

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

    Nota:

    • El marcador de posición <SubDBName> representa el nombre de la base de datos de suscripción.
    • Normalmente, estos objetos son procedimientos almacenados que se usan en la replicación.
  9. Determine el índice o la vista indizada que provoca el bloqueo. Para ello, siga estos pasos:

    1. En el script de bloqueo, busque el valor de la propiedad waitresource.

      En el script de bloqueo de ejemplo, el valor de waitresource es 72057594375700480.

    2. Consulte la vista sys.partitions para obtener el identificador de objeto y el identificador de índice especificando que la columna PARTITION_ID sea igual al valor del que obtuvo en el waitresource paso 9a.

      Por ejemplo, ejecute la consulta siguiente:

      SELECT object_id, index_id FROM SYS.PARTITIONS WHERE PARTITION_ID=72057594375700480
      
    3. En la base de datos de suscripciones, consulte la vista sys.indexes para determinar el índice mediante el identificador de objeto y el identificador de índice que obtuvo en el paso 9b.

      Por ejemplo, ejecute la consulta siguiente:

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

      Nota:

      • El marcador de posición <objID> representa el identificador de objeto que obtuvo en el paso 9b.
      • El marcador de posición <idxID> representa el identificador de índice que obtuvo en el paso 9b.
  10. Si el bloqueo se debe a una vista indizada, se recomienda quitar la vista indizada. Si el bloqueo se debe a un índice único no clúster, se recomienda quitar el índice y, a continuación, volver a crear un índice no único.

Descripción del subproceso del monitor de bloqueo

El Agente de distribución mantiene un subproceso de monitor de bloqueo que detecta el bloqueo entre las sesiones. Si el subproceso del monitor de bloqueo detecta el bloqueo entre las sesiones, el Agente de distribución cambia a usar una sesión para volver a aplicar el lote actual de comandos que el Agente de distribución no pudo aplicar anteriormente.

Para obtener más información sobre el subproceso de supervisión de bloqueo, consulte Bloquear subproceso de monitor.

Cómo el Agente de distribución reanuda varias sesiones

Antes de que el Agente de distribución pueda reanudar varias sesiones, el Agente de distribución debe ejecutar el procedimiento sp_MSget_repl_commands almacenado para volver a consultar la base de datos de distribución de los comandos que no se han aplicado en el suscriptor. A continuación, el Agente de distribución debe aplicar todos estos comandos en el suscriptor para que el Agente de distribución pueda reanudar varias sesiones. En un entorno de replicación latente, el Agente de distribución no puede reanudar varias sesiones porque el Agente de distribución debe aplicar muchos comandos en el suscriptor antes de que el Agente de distribución pueda reanudar varias sesiones.

Para realizar un seguimiento de todo el proceso, examine el archivo de salida del Agente de distribución.