Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Если у вас есть одна или несколько хранимых процедур, которые выполняются на издателе и влияют на опубликованные таблицы, рассмотрите возможность включения этих хранимых процедур в публикацию в качестве статей о выполнении хранимой процедуры. Определение процедуры (инструкции CREATE PROCEDURE) копируется Подписчику при инициализации подписки; когда процедура выполняется у Издателя, репликация выполняет соответствующую процедуру у Подписчика. Это может значительно повысить производительность в случаях, когда выполняются большие пакетные операции, так как выполняется только выполнение процедуры, обходя необходимость репликации отдельных изменений для каждой строки. Например, предположим, что в базе данных публикации создается следующая хранимая процедура:
CREATE PROC give_raise AS
UPDATE EMPLOYEES SET salary = salary * 1.10
Эта процедура дает каждому из 10 000 сотрудников вашей компании увеличение заработной платы на 10 процентов. При выполнении этой хранимой процедуры на издателе она обновляет зарплату для каждого сотрудника. Без репликации выполнения хранимой процедуры обновление будет отправлено подписчикам в виде большой многоэтапной транзакции:
BEGIN TRAN
UPDATE EMPLOYEES SET salary = salary * 1.10 WHERE PK = 'emp 1'
UPDATE EMPLOYEES SET salary = salary * 1.10 WHERE PK = 'emp 2'
Это повторяется на протяжении 10 000 обновлений.
При репликации выполнения хранимой процедуры репликация отправляет только команду для выполнения хранимой процедуры на подписчике, а не записи всех обновлений в базу данных распространителя, а затем отправляет их по сети подписчику:
EXEC give_raise
Это важно
Репликация хранимой процедуры не подходит для всех приложений. Если статья фильтруется по горизонтали таким образом, что на Издателе и Подписчике существуют разные наборы строк, выполнение одной и той же хранимой процедуры на обоих приводит к различным результатам. Аналогичным образом, если обновление основано на вложенном запросе другой нереплицированной таблицы, то при выполнении одной хранимой процедуры на издателе и подписчике возвращаются разные результаты.
Публикация выполнения хранимой процедуры
SQL Server Management Studio: Выполнение хранимой процедуры в транзакционной публикации (SQL Server Management Studio)
Репликация Transact-SQL программирования: выполните команду sp_addarticle (Transact-SQL) и укажите значение 'serializable proc exec' (рекомендуется) или 'proc exec' для параметра @type. Дополнительные сведения об определении статей см. в разделе "Определение статьи".
Изменение процедуры для подписчика
По умолчанию определение хранимой процедуры на издателе распространяется на каждого подписчика. Однако можно также изменить хранимую процедуру на подписчике. Это полезно, если вы хотите выполнить другую логику в компоненте "Издатель" и "Подписчик". Например, рассмотрим sp_big_delete хранимую процедуру на издателе с двумя функциями: она удаляет 1000 000 строк из реплицированной таблицы big_table1 и обновляет нереплицированную таблицу big_table2. Чтобы уменьшить спрос на сетевые ресурсы, следует выполнить удаление миллиона строк в виде хранимой процедуры, опубликовав sp_big_delete. На подписчике можно изменить sp_big_delete, чтобы удалить только 1 миллион строк и не выполнить последующее обновление в big_table2.
Замечание
По умолчанию, все изменения, внесённые с помощью ALTER PROCEDURE у Издателя, передаются Подписчику. Чтобы предотвратить это, отключите распространение изменений схемы перед выполнением ALTER PROCEDURE. Сведения об изменениях схемы см. в разделе "Внесение изменений схемы" в базах данных публикации.
Типы статей о выполнении хранимых процедур
Существует два разных способа публикации выполнения хранимой процедуры: статьи о выполнении сериализуемой процедуры и статье о выполнении процедуры.
Параметр сериализации рекомендуется, так как он реплицирует выполнение процедуры, только если процедура выполняется в контексте сериализуемой транзакции. Если хранимая процедура выполняется вне сериализуемой транзакции, изменения данных в опубликованных таблицах реплицируются в виде ряда инструкций DML. Это поведение способствует тому, чтобы данные на подписчике были согласованы с данными на издателе. Это особенно полезно для пакетных операций, таких как большие операции очистки.
При использовании параметра выполнения процедуры можно реплицировать выполнение для всех подписчиков независимо от того, были ли отдельные инструкции в хранимой процедуре успешными. Кроме того, поскольку изменения, внесенные хранимой процедурой, могут происходить в нескольких транзакциях, данные на подписчиках могут не совпадать с данными на издателе. Для решения этих проблем требуется, чтобы подписчики были настроены для только чтения, и вы использовали уровень изоляции выше, чем чтение без фиксации. При использовании режима "чтение без фиксации" изменения данных в опубликованных таблицах реплицируются в виде ряда инструкций DML.
В следующем примере показано, почему рекомендуется настроить репликацию процедур в качестве статей процедур с возможностью сериализации.
BEGIN TRANSACTION T1
SELECT @var = max(col1) FROM tableA
UPDATE tableA SET col2 = <value>
WHERE col1 = @var
BEGIN TRANSACTION T2
INSERT tableA VALUES <values>
COMMIT TRANSACTION T2
В предыдущем примере предполагается, что оператор SELECT в транзакции T1 выполняется перед INSERT в транзакции T2.
Если процедура не выполняется в сериализуемой транзакции (с уровнем изоляции, установленным для SERIALIZABLE), транзакция T2 будет разрешена вставлять новую строку в диапазон инструкции SELECT в T1, и она зафиксируется до T1. Это также означает, что оно будет применяться у подписчика до T1. Когда T1 применяется на подписчике, SELECT потенциально может вернуть иное значение, чем у издателя, и это может привести к результату, отличному от UPDATE.
Если процедура выполняется в сериализуемой транзакции, транзакции T2 не будет разрешено вставлять в диапазон, охватываемый инструкцией SELECT в рамках T2. Он будет заблокирован до тех пор, пока T1 не зафиксирует те же результаты у подписчика.
Блокировки будут храниться дольше при выполнении процедуры в сериализуемой транзакции и могут привести к снижению параллелизма.
Параметр XACT_ABORT
При репликации выполнения хранимой процедуры параметр сеанса, выполняющего хранимую процедуру, должен указывать XACT_ABORT ON. Если для XACT_ABORT задано значение OFF и при выполнении процедуры у Издателя возникает ошибка, то та же ошибка возникнет у Подписчика, что приведет к сбою агента распространения. Указание XACT_ABORT ON гарантирует, что все ошибки, возникшие во время выполнения в Publisher, вызывают откат всего выполнения, избегая сбоя агент распространения. Дополнительные сведения о настройке XACT_ABORTсм. в разделе SET XACT_ABORT (Transact-SQL).
Если требуется параметр XACT_ABORT OFF, укажите параметр -SkipErrors для агент распространения. Это позволяет агенту продолжать применять изменения на подписчике, даже если возникла ошибка.