Форум: "Базы";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
Внизтранзакции в распределенной БД Найти похожие ветки
← →
wardoc © (2006-06-25 02:27) [0]Доброго времени суток уважаемые.
У меня такая проблема: делаю я клиент-серверную БД, использую в качестве сервера БД Interbase, сама база данных распределена в локальной сети с использованием DCOM. Разумеется хочется, чтобы БД была с многопользовательским доступом. Поэтому использую ессно транзакции. При добавлении/изменении записей клиентским приложением все вроде бы обновляется в БД благополучно, но если тут же делаю попытку добавления/изменения записи этой же таблицы из второго экземпляра клиентского приложения, то возникает такое вот исключение: "Cannot perform this operation on a closed database", или что-то в этом роде. Хотя компоненты связи с БД открыты. Что я делаю не так?
← →
Ломброзо © (2006-06-25 12:16) [1]неправильная архитектура.
Сервер приложений должен управлять распределением нагрузки на СУБД, для чего обычно реализуется механизм, обеспечивающий кэширование и повторное использование соединений к БД (сonnection pooling). В случае применения компонентов ADO этот механизм встроен в библиотеки OLE DB, поэтому нет смысла открывать и держать соединение открытым в течение всего времени жизни процесса. Другими словами, правильный код для доступа к данным должен выглядеть примерно так:
procedure GetData();
var
cnn: TADOConnection;
rs : TADORecordset;
begin
try
cnn := TADOConnection.Create();
cnn.COnnectionString := "...";
cnn.Open();
rs := cnn.Execute("select * from ...");
finally
if (cnn <> nil) then
begin
cnn.CLose();
cnn.Free();
cnn := nil;
end;
end;
end;
То есть основной принцип такой: создать соединение - открыть - сделать запрос - сразу же закрыть.
В вашем случае, насколько я понял, ошибка состоит в том, что компонент-соединение у вас лежит на форме или в DataModule в единственном экземпляре. Представьте, что к вашему приложению одновременно обратились два клиента. Первый открыл соединение, и выбирает данные. Второй при попытке открыть соединение получит исключение с сообщением о том, что соединение уже открыто и используется. Для устранения этой ткзать коллизии нужно:
- Писать код так, как указано в примере выше;
- Использовать примитивы синхронизации (например, критические секциии) для обеспечения гарантии того, что два процесса или потока не смогут одновременно обращаться к общей переменной.
Ну и ещё, наверное, я бы на вашем месте отказался от DCOM и использовал бы COM+.
← →
ВЫЛфдгпшт (2006-06-26 14:22) [2]В Интербейзе есть такое понятие как Двухфазный коммит. Изменение данных на разных серверах в контексте одной общей транзакции.
Возможно использование этого механизма решит вашу проблему
← →
DSKalugin © (2006-06-26 14:27) [3]ВЫЛфдгпшт=DSKalugin
не той раскладкой свой ник написал :-)
Автоматический коннект, транзакцию и отсоединение реализовано в библиотеке dbExpress насколько я правильно понял
http://ibase.ru/devinfo/dbexpress.htm
← →
wardoc © (2006-06-27 15:26) [4]2Ломброзо:
Я не использую ADO, но все равно спасибо за совет закрывать соединение после обмена данными. Что касается того, что компонент-провайдер лежит в модуле данных в единственном экземпляре - да это так, но ведь настройки модуля данных таковы, что на каждого подключенного клиента в память загружается отдельный экземпляр модуля данных. Разве это не должно обеспечивать многопользовательский доступ, даже если компоненты открыты? COM+ обязательно попробую.
2DSKalugin:
За ссылку на инфу по dbExpress большое спасибо. Двухфазный коммит - изменение данных на разных серверах? Это клиент должен быть подключен к разным серверам одновременно что-ли?
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.049 c