Указание способа распространения изменений для статей транзакций

Репликация транзакций позволяет указывать, как изменения данных распространяются от издателя к подписчикам. Для каждой опубликованной таблицы можно указать один из четырех способов, которым каждая операция (INSERT, UPDATE или DELETE) должна распространяться на подписчик:

  • Укажите, что репликации транзакций следует создать сценарий и затем вызвать хранимую процедуру для распространения изменений на подписчики (по умолчанию).

  • Укажите, что изменение должно распространяться с помощью инструкции INSERT, UPDATE или DELETE (по умолчанию для подписчиков, отличных от SQL Server).

  • Укажите, что должна использоваться пользовательская хранимая процедура.

  • Укажите, что данное действие не должно выполняться на любом подписчике. Транзакции этого типа не реплицируются.

По умолчанию репликация транзакций распространяет изменения на подписчики при помощи набора хранимых процедур, установленных на каждом подписчике. Операции вставки, обновления или удаления в таблице издателя преобразовываются в вызовы хранимой процедуры на подписчике. Хранимая процедура принимает параметры, которые соответствуют столбцам в таблице, допуская изменение этих столбцов в подписчике.

Задание метода распространения изменений данных в транзакционные статьи

Стандартные и пользовательские хранимые процедуры

Три процедуры, создаваемые репликацией по умолчанию для каждой статьи таблицы:

  • sp_MSins_<имя_таблицы>, обрабатывающая операции вставки.

  • sp_MSupd_<имя_таблицы>, обрабатывающая операции обновления.

  • sp_MSdel_<имя_таблицы>, обрабатывающая операции удаления.

<имя_таблицы> в процедуре зависит от того, как статья была добавлена в публикацию, и содержит ли база данных подписки таблицу другого владельца с одинаковым именем.

Любая из этих процедур может заменяться пользовательской процедурой, указываемой при добавлении статьи в публикацию. Пользовательские процедуры применимы, если приложению требуется пользовательская логика, такая как вставка данных в проверочную таблицу при обновлении строки в подписчике. Дополнительные сведения об указываемых пользовательских хранимых процедурах см. в справочных разделах, перечисленных выше.

Если указываются стандартные или пользовательские процедуры репликации, указывается также синтаксис вызова для каждой процедуры (при использовании процедур по умолчанию репликация выбирает умолчания). Синтаксис вызова определяет структуру параметров, предоставляемых процедуре, а также количество сведений, посылаемых подписчику с каждым изменением данных. Дополнительные сведения см. в подразделе «Синтаксис вызова для хранимых процедур» этого раздела.

Аспекты использования пользовательских хранимых процедур

При использовании пользовательских хранимых процедур примите во внимание следующие соображения:

  • В хранимой процедуре необходимо поддерживать логику; Microsoft не поддерживает пользовательскую логику.

  • Во избежание конфликтов с транзакциями, используемыми репликацией, явные транзакции не должны применяться в пользовательских процедурах.

  • Схема в подписчике, как правило, идентична схеме в издателе, однако при использовании фильтрации столбцов схема в подписчике может быть подмножеством схемы издателя. Однако при необходимости преобразования схемы при перемещении данных так, чтобы схема на подписчике не являлась подмножеством схемы на издателе, рекомендованным решением являются службы SQL Server 2008 Integration Services (SSIS) (SSIS). Дополнительные сведения см. в разделе Службы SQL Server Integration Services.

  • При внесении изменений схемы в опубликованную таблицу пользовательские процедуры должны быть созданы заново. Дополнительные сведения см. в разделе Повторное создание пользовательских процедур транзакций для отражения изменений схем.

  • При использовании значений больше 1 для параметра -SubscriptionStreams агента распространителя убедитесь, что обновления столбцов первичного ключа выполнены успешно. Например:

    update ... set pk = 2 where pk = 1 -- update 1
    update ... set pk = 3 where pk = 2 -- update 2
    

    Если агент распространителя использует больше одного соединения, то эти два обновления могут реплицироваться через другие соединения. Если обновление 1 применяется первым, то проблем не существует; если первым применяется обновление 2, возвращается сообщение «0 строк затронуто», т. к. обновление 1 еще не произошло. Данная ситуация в процедурах по умолчанию вызывает ошибку, если не существует строк, затронутых при обновлении:

    if @@rowcount = 0
        if @@microsoftversion>0x07320000
            exec sys.sp_MSreplraiserror 20598
    

    Возникновение ошибки заставляет агент распространителя повторить обновления через одно соединение, которые завершатся успешно. Пользовательские хранимые процедуры должны содержать похожую логику.

Синтаксис вызова для хранимых процедур

Существует пять вариантов синтаксиса, который применяется для вызова процедур, используемых репликацией транзакций:

  • Синтаксис функции CALL. Может использоваться для вставок, обновлений и удалений. По умолчанию репликация использует этот синтаксис для вставок и удалений.

  • Синтаксис функции SCALL. Может применяться только для обновлений. По умолчанию репликация использует этот синтаксис для обновлений.

  • Синтаксис функции MCALL. Может применяться только для обновлений.

  • Синтаксис функции XCALL. Может использоваться для обновлений и удалений.

  • VCALL. Применяется для обновляемых подписок. Только для внутреннего использования.

Каждый метод отличается по количеству данных, распространяемых на подписчик. Например, SCALL передается в значениях только для столбцов, реально затронутых обновлением. Напротив, XCALL запрашивает все столбцы (независимо от того, затронуты ли они обновлением) и все старые значения данных каждого столбца. Во многих случаях синтаксис SCALL целесообразен для обновлений, но если приложению нужны все значения данных во время обновления, это позволяет указать синтаксис XCALL.

Синтаксис функции CALL

  • Хранимые процедуры INSERT
    Хранимым процедурам, обрабатывающим инструкции INSERT, передаются вставляемые значения для всех столбцов:

    c1, c2, c3,... cn
    
  • Хранимые процедуры UPDATE
    Хранимым процедурам, обрабатывающим инструкции UPDATE, передаются обновленные значения для всех столбцов, определенных в статье, за ними передаются исходные значения для столбцов первичного ключа (попыток определить, какие столбцы были изменены, не предпринимается):

    c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn
    
  • Хранимые процедуры DELETE
    Хранимым процедурам, обрабатывающим инструкции DELETE, передаются значения для всех столбцов первичного ключа:

    pkc1, pkc2, pkc3,... pkcn
    

Синтаксис функции SCALL

  • Хранимые процедуры UPDATE
    Хранимым процедурам, обрабатывающим инструкции UPDATE, передаются обновленные значения только для измененных столбцов, затем передаются исходные значения для столбцов первичного ключа, за которыми следует параметр битовой маски (binary(n)), указывающий на измененные столбцы. В следующем примере столбец 2 (c2) не был изменен:

    c1, , c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask
    

Синтаксис функции MCALL

  • Хранимые процедуры UPDATE
    Хранимым процедурам, обрабатывающим инструкции UPDATE, передаются обновленные значения для всех столбцов, определенных в статье, а также исходные значения для столбцов первичного ключа и параметр битовой маски (binary(n)), указывающий на измененные столбцы.

    c1, c2, c3,... cn, pkc1, pkc2, pkc3,... pkcn, bitmask
    

Синтаксис функции XCALL

  • Хранимые процедуры UPDATE
    Хранимым процедурам, обрабатывающим инструкции UPDATE, передаются исходные значения (образ до обработки) для всех столбцов, определенных в статье, а затем передаются обновленные значения (образ после обработки) для всех столбцов, определенных в статье:

    old-c1, old-c2, old-c3,... old-cn, c1, c2, c3,... cn,
    
  • Хранимые процедуры DELETE
    Хранимым процедурам, обрабатывающим инструкции DELETE, передаются исходные значения (образ до обработки) для всех столбцов, определенных в статье:

    old-c1, old-c2, old-c3,... old-cn
    
    ПримечаниеПримечание

    При использовании функции XCALL предполагается, что значения двоичного образа до обработки для столбцов text и image равны NULL.

Примеры

Следующие процедуры являются процедурами по умолчанию, созданными для Таблица Vendor (AdventureWorks) в примере базы данных Adventure Works.

--INSERT procedure using CALL syntax
create procedure [sp_MSins_PurchasingVendor] 
  @c1 int,@c2 nvarchar(15),@c3 nvarchar(50),@c4 tinyint,@c5 bit,@c6 bit,@c7 nvarchar(1024),@c8 datetime
as 
begin 
insert into [Purchasing].[Vendor]( 
 [VendorID]
,[AccountNumber]
,[Name]
,[CreditRating]
,[PreferredVendorStatus]
,[ActiveFlag]
,[PurchasingWebServiceURL]
,[ModifiedDate]
 )
values ( 
 @c1
,@c2
,@c3
,@c4
,@c5
,@c6
,@c7
,@c8
 ) 
end
go


--UPDATE procedure using SCALL syntax
create procedure [sp_MSupd_PurchasingVendor] 
 @c1 int = null,@c2 nvarchar(15) = null,@c3 nvarchar(50) = null,@c4 tinyint = null,@c5 bit = null,@c6 bit = null,@c7 nvarchar(1024) = null,@c8 datetime = null,@pkc1 int
,@bitmap binary(2)
as
begin
update [Purchasing].[Vendor] set 
 [AccountNumber] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [AccountNumber] end
,[Name] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Name] end
,[CreditRating] = case substring(@bitmap,1,1) & 8 when 8 then @c4 else [CreditRating] end
,[PreferredVendorStatus] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [PreferredVendorStatus] end
,[ActiveFlag] = case substring(@bitmap,1,1) & 32 when 32 then @c6 else [ActiveFlag] end
,[PurchasingWebServiceURL] = case substring(@bitmap,1,1) & 64 when 64 then @c7 else [PurchasingWebServiceURL] end
,[ModifiedDate] = case substring(@bitmap,1,1) & 128 when 128 then @c8 else [ModifiedDate] end
where [VendorID] = @pkc1
if @@rowcount = 0
    if @@microsoftversion>0x07320000
        exec sp_MSreplraiserror 20598
end
go


--DELETE procedure using CALL syntax
create procedure [sp_MSdel_PurchasingVendor] 
  @pkc1 int
as 
begin 
delete [Purchasing].[Vendor]
where [VendorID] = @pkc1
if @@rowcount = 0
    if @@microsoftversion>0x07320000
        exec sp_MSreplraiserror 20598
end 
go