Поделиться через


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

Область применения: SQL Server Управляемый экземпляр SQL Azure

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Логику необходимо поддерживать в хранимой процедуре; Корпорация Майкрософт не предоставляет поддержку пользовательской логики.

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

  • Схема в подписчике, как правило, идентична схеме в издателе, однако при использовании фильтрации столбцов схема в подписчике может быть подмножеством схемы издателя. Однако если необходимо преобразовать схему по мере перемещения данных, поэтому схема на подписчике не является подмножеством схемы на издателе, служба SQL Server 2019 Integration Services (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 Table примера базы данных 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