| ||||||||||||||||
![]() | ||||||||||||||||
| ||||||||||||||||
![]() | ||||||||||||||||
| ||||||||||||||||
![]() |
How to: Репликация транзакций В статье собраны наиболее типичные вопросы, связанные с репликацией транзакций, а также анализируются наиболее часто возникающие ошибки и общие для репликации проблемы.
Как использовать DBCC OPENTRAN? Как определить какие команды ожидают загрузки? Как понять когда лучше использовать комбинацию sp_dropsubscription и sp_addsubscription вместо комбинации sp_dropsubscription и sp_droparticle, с последующим исполнением sp_addarticle и sp_addsubscription? Как определить какой подписчик еще не получил данные? Как правильно сделать резервную копию реплицируемой БД? Как ежедневно добавлять таблицы в БД и реплицировать их, без запуска агента создания снимка? Как динамически секционировать данные? Что происходит, когда при выполнении транзакции на издателе происходит ошибка, применяется ли она на подписчике? Как в репликации транзакций прочитать транзакции не в двоичном формате? Как реплицировать изменения командой Update? Когда я выполняю команду update, она разбивается на delete и insert на подписчике. Почему? Как реплицировать пользователей? Как предотвратить удаления, приходящие от подписчика? Сообщения об ошибках При создании подписчиков с немедленным обновлением, выдается ошибка "Login failed for 'sa' Почему? С чем связана эта ошибка: Could not find stored procedure 'sp_MSupd_Region'? Общие проблемы Я использую стандартную репликацию транзакций на промышленном сервере. Когда я тестирую ее работу, поле identity не работает. Почему? Какие изменения в схеме допустимы на издателе? Как использовать DBCC OPENTRAN? Вот мой метод использования DBCC OPENTRAN: Если log reader agent успевает обработать то, что находится в журнале транзакций, тогда LSN самой старой транзакции, которая еще не передана подписчику, будет такой: (0:0:0).
Если же он не успевает обработать все новые тиражируемые транзакции или он не запущен, то результат будет похож на следующий:
Если имеются открытые транзакции, в начале получаемого отчёта будет следующая информация:
Для того чтобы определить, какая выполняется команда T-SQL,
нужно воспользоваться командой dbcc inputbuffer (55), а затем
уже принимать решение нужно ли прерывать данный
процесс.
Результатом исполнения этого запроса будет список LSN, а для получения более детальной информации, можно воспользоваться программой LogExplorer. Как определить какие команды ожидают загрузки? Для того чтобы получить timestamp самой последней реплицируемой команды, нужно выполнить следующий запрос:
Что бы увидеть последнюю команду, нужно выполнить в контексте базы данных Distribution представленный ниже скрипт. В качестве параметра процедуры используйте значение, полученное из запроса выше:
Как понять когда лучше использовать комбинацию sp_dropsubscription и sp_addsubscription вместо комбинации sp_dropsubscription и sp_droparticle, с последующим исполнением sp_addarticle и sp_addsubscription? Второй вариант лучше использовать, когда производятся
изменения, которые могут быть легко внесены при репликации,
такие например как изменение типа данных одного или нескольких
полей. Как избавиться от ошибки "Violation of Primary Key constraint 'PK__@snapshot_seqnos__{UniqueNumber}'. Cannot insert duplicate key in object '#{UniqueNumber}' Необходимо установить последний сервисный пакет. Имеются отзывы, что и этого не достаточно, потому что тип параметра subscription_seqno - varbinary (16), а не varchar (16). Нужно заменить тип данных столбца на varbinary (16), и тогда все будет работать правильно. Как определить какой подписчик еще не получил данные? Подписчики, на которых количество ожидающих передачу команд велико:
Для того чтобы получить список таких подписчиков, нужно
полученный результат объединить с запросом к таблице
msdistribution_agents (поле Id).
Как правильно сделать резервную копию реплицируемой БД? Прочитайте в BOL статьи "Strategies for Backing Up and Restoring Transactional Replication" и "Backing Up and Restoring Replication Databases". Имеется возможность для стандартной репликации транзакций использовать опцию 'sync with backup'. При использовании этой опции, транзакции не попадают в базу дистрибуции пока они не будут включены в резервную копию реплицируемой БД (то есть не будет таких транзакций в msrepl_commands, которые не были бы уже помещены в резервную копию на издателе). Однако это ведет к снижению производительности (даже при использовании Log Shipping выполнение резервной копии может выполняться не чаще чем раз в минуту). Если Вы не используете эту опцию, после восстановления из резервной копии нужно будет игнорировать некоторые транзакции и ошибки, делая это вручную (используя параметр -SKIPERRORS). Что же касается восстановления резервных копий подписчика, это обычно не является настолько критичным. Они должны быть восстановлены на момент времени, предшествующий восстановлению дистрибутора, и затем уже команды будут тиражироваться агентом дистрибуции - подробности можно прочитать в BOL. Или в качестве альтернативы, Вы могли бы просто реинициализировать подписчиков. Как ежедневно добавлять таблицы в БД и реплицировать их, без запуска агента создания снимка? Да, это возможно, если предполагается что данные уже существует на подписчике. Для этого нужно использовать процедуру sp_addsubscription с параметром @sync_type = 'none' при добавлении подписки, и нужно вручную добавить на подписчике пользовательские хранимые процедуры (используя sp_scriptpublicationcustomprocs). Тогда не понадобится генерировать новый снимок.
Как динамически секционировать данные? Используйте подписку с трансформацией. В таких подписках
используются DTS пакеты для преобразования данных, и для
каждого из подписчиков может быть создан свой пакет. При
создании публикации убедитесь, что выбраны опции 'Show
Advanced Options' и 'Yes, Transform the Data'.
Что происходит, когда при выполнении транзакции на издателе происходит ошибка, применяется ли она на подписчике? Результат выполнения транзакции на издателе можно
отслеживать с помощью функции @@error, а затем при
необходимости делать откат транзакции, но транзакция все равно
применится на подписчике. Данная ситуация отлавливается, если
установить уровень изоляции транзакций
serializable. Как в репликации транзакций прочитать транзакции не в двоичном формате? Транзакции записываются в таблицу MSrepl_commands, чтобы их посмотреть, нужно запустить процедуру sp_browsereplcmds. В случае использования очереди, применяйте sp_replqueuemonitor для того чтобы прочитать данные из таблицы MSreplication_queue, и sp_browsereplcmds для того чтобы посмотреть команды в транзакции при разрешении конфликтов. Как реплицировать изменения командой Update? Когда я выполняю команду update, она разбивается на delete и insert на подписчике. Почему? Это случается при изменении поля, которое является частью уникального индекса. Используйте флаг 8207, чтобы команда update применялась как update на подписчике, но это действительно только для случаев, когда update - одна команда в транзакции. Как реплицировать пользователей? Пользователи и другие административные объекты не могут быть реплицированы, поскольку нельзя реплицировать системные таблицы. Если это необходимо, Вы можете:
Как предотвратить удаления, приходящие от подписчика? При настройке издателя это сделать довольно просто - нужно только в свойствах статьи изменить правило для этой команды на NONE. Если ваш издатель уже настроен, это вызовет реинициализацию всех подписчиков. Если это только временная мера, и Вы не хотите повторно инициализировать подписчиков, можно изменить хранимую процедуру, связанную с удалением данных на подписчиках, чтобы предотвратить удаление, хотя очевидно это приведет к потере синхронизации данных. При создании подписчиков с немедленным обновлением, выдается ошибка "Login failed for 'sa' Почему? При подключении к издателю, подписчики с немедленным обновлением используют удаленный вызов процедур (RPC). По умолчанию учетная запись для подключения таким образом - sa с пустым паролем, что часто становится причиной ошибок. Используйте процедуру sp_link_publication с параметром @security_mode = 2. Другие параметры этой процедуры описаны в BOL или по этой ссылке: MS article. С чем связана эта ошибка: Could not find stored procedure 'sp_MSupd_Region'? Если в процедуре sp_addsubscription Вы используете параметр @sync_type = None (или выбираете аналогичную опцию в мастере создания публикации), а в окне инициализации подписчиков выбираете 'no, the subscriber already has the schema and data' - Вы можете получить эту ошибку. Системные таблицы репликации будут созданы на подписчике в любом случае, но Вам придётся вручную создать хранимые процедуры на подписчике, если Вы использовали эту опцию. Иными словами, Вы можете получить эту ошибку при изменении записей на издателе. Используйте sp_scriptpublicationcustomprocs (предполагается, что у Вас установлен sp1) для создания скриптов этих процедур, и выполните эти скрипты на подписчике. Я использую стандартную репликацию транзакций на промышленном сервере. Когда я тестирую ее работу, поле identity не работает. Почему? Если при инициализации у Вас используется опция nosync, может получиться, что поле имеет атрибут Identity - Yes (not for replication), но значение identity не увеличивается в процессе репликации и DBCC CHECKIDENT не всегда работает для таких полей. Это может стать для Вас одной из причин, чтобы рассмотреть возможность использования обновляемых подписчиков с использованием очередей. Какие изменения в схеме допустимы на издателе?
Для тех действий, которые допустимы на издателе, но не реплицируются на подписчиков, можно использовать механизм On-Demand Script Execution (или посредством linked servers и т.д.). |
|
![]() | ||||||||||||||||
| ||||||||||||||||
![]() | ||||||||||||||||
|