Форум FAQ О команде
Поиск по сайту:
 
Sybase
Sybase ASA  
Sybase ASE  
Sybase IQ  
Sybase PowerDesigner  
Sybase PowerBuilder  

Продукты
Наши продукты  
Продукты партнеров портала  

Сообщества
Alef community  

Меню
Регистрация  
Почта  

Вход

Рассылка
Рассылка 'РСУБД Sybase ASA 9 - мощность, легкость и надежность'
Почтовая рассылка
"Технологии обработки данных компании Sybase"


Статистика
Яндекс цитирования

Rambler's Top100
Находится в каталоге Апорт

Главная -> Статьи
Что не рекомендуется делать в реплицируемых базах

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

Использование autoincrеment полей в качестве первичных ключей

Самая частая ошибка. Autoincrement поля прекрасно работают в одиночной базе, но когда баз две и больше, первичные ключи на одинаковых таблицах обязательно пересекутся. Существует несколько решений данной ситуации:
1) Каждая удаленая база создает новые строки в жестко определенном диапазоне значений. Например база на первом складе при добавлении описания товаров дает им номера от 1 до 999999, база на втором складе - от 1000000 до 1999999, третий склад - 2000000..2999999 и так далее. Для задания таких диапазонов в ASA существует специальная опция Global_database_id
Данное решение будет работать до тех пор пока количество добавленных строк не выйдет из заранее заданого диапазона. И во вторых, скрипт типа 'select max(id) from list_of_goods' попытается создать запись не в своем диапазоне значений а в чужом. Резюме: требуется постоянный контроль DBA и очень-очень внимательное написание процедуры вставки новых строк в таблицу.
2) Использование UUID полей вместо числовых. Например:
CREATE TABLE mytab( pk uniqueidentifier primary key default newid(), c1 int )
Функция newid() всегда выдаст уникальный UUID (во всяком случае должна). Минусы решения - данная функция появилась только в ASA 8.0.2 и не существует в более ранних версиях. Бинарная природа UUID приносит некоторые трудности в работу с ними со стороны клиента.
3) Полный отказ от автоматически создаваемых первичных ключей. Использование в качестве PK, полей уникальных по смыслу. Например, для складского учета такими полями могут быть "код склада"+"код товара". Это решение является самым надежным со всех точек зрения, но требует вдумчивого подхода к созданию таблиц.

Триггер на after insert добавляет строки

Это, более похоже на ошибку внутри DbRemote чем на ошибку дизайна, однако данная проблема существует во всех версиях, от ASA7 и вплоть до ASA 9.0.1 Так что стоит упоминания.
Иллюстрация: Оператор добавляет в базу платеж от клиента в счет накладной. Триггер на таблице платежей, проверяет указаную накладную, обнаруживает что суммма платежа превышает сумму накладной. Исправляет добавленную оператором запись и добавляет свою запись на разницу суммы с пояснением "платеж непонятно за что". Оператор видит появившуюсья "лишнюю" запись и указыват причину превышения (например штраф за просроченый платеж). Как это выглядит с точки зрения базы?
--- от клиентской программы:
insert into Payments(PaymentDate, Amount, ForOrder) values (today(*), 530, 'AB-2571');
---- что делает триггер
-- select Amount into @Amount from Orders where OrderId=new_payment.ForOrder;
-- if new_payment.Amount > @Amount then
--    set @Diff = new_payment.Amount - @Amount;
--    insert into Payments(PaymentDate, Amount, Reason) values (today(*), @Diff, 'unknown')
--    update Payments set Amount = @Amount where PaymentId = new_payment.PaymentId;
-- end if;
----- Клиентская программа делает перезапрос сегодняшних платежей и получает две новых строки. Оператор исправляет вторую:
update Payments set Reason = 'Penalty' where PaymentId=:NewPaymentId;
----- и клиентская программа закрывает транзакцию
commit work;

Что происходит при репликации? В репликацию попадают только команды от клиентской программы. Предполагается что в базе получателе данных имеется аналогично работающие триггеры. Однако, в данной ситуации, реплицируемые команды
insert into Payments(PaymentDate, Amount, ForOrder) values (today(*), 530, 'AB-2571');
update Payments set Reason = 'Penalty' where PaymentId=:NewPaymentId;
commit work;

Будут обработаны как атомарная операция и триггер на вставку строки будет запущен после попытки апдейта. То есть база получатель не сможет обновить несуществующую в данный момент строку. Но строка все же будет создана. При этом никакой диагностики выдано нигде не будет.
Метод лечения такой ситуации очень простой - клиент должен скомандовать commit work после попытки вставки первой строки:
insert into Payments(PaymentDate, Amount, ForOrder) values (today(*), 530, 'AB-2571');
commit work;
update Payments set Reason = 'Penalty' where PaymentId=:NewPaymentId;
commit work;



Таблица справочник и таблица данных в разных подписках

Справочники обновляются намного реже чем таблицы данных и хочется вынести обновление справочников в отдельную подписку. Особенно если удаленые базы используют разные справочники (один склад хранит одежду, другой медикаменты, третий запчасти для автомобилей) Выглядит логичным чтобы сделать одну подписку для накладных, одну для типов тканей, третью для типов масел и тд. При этом, база в офисе фирмы должна иметь все типы справочников и копии всех складских данных. Однако, не существует возможности управлять порядком в котором сообщения по разным подпискам будут посланы/приняты. Всегда будет вероятность, что первым пойдет репликационное сообщение описывающее появление на складе новой одежды, а следом пойдет описание нового типа ткани. Если таблицы одежды и типов тканей связаны между собой через внешние ключи - база получатель не сможет получить запись о новом товаре (dbremote на базе получателе выдаст предупреждающее сообщение).
Методов лечения два:
1) Не делать жесткой связи таблицы данных и таблицы справочника через foreign key. Минусы этого решения ясно видны. В плюсах - более гибкое управление какая из баз какими справочниками пользуется.
2) Объеденить подписку "накладные" и "справочник тканей" в одну общую. Минус решения - все базы будут получать обновления всех справочников. Плюс - таблица данных будет всегда обновляться после обновления таблицы справочника как это и происходило в оригинальной базе.


Дата публикации: Monday 27 March 2006 19:36:20
Материал прочитан: 12832 раз(а)
[ Назад ]



Продвижение сайтов
Биржа ссылок

Copyright©2005 phpMS. Все права защищены.
hosted on pets-tree