![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
транзакции в распределенной БД [D7, IB6.x]
wardoc © (2006-06-25 02:27:00)Доброго времени суток уважаемые.
У меня такая проблема: делаю я клиент-серверную БД, использую в качестве сервера БД Interbase, сама база данных распределена в локальной сети с использованием DCOM. Разумеется хочется, чтобы БД была с многопользовательским доступом. Поэтому использую ессно транзакции. При добавлении/изменении записей клиентским приложением все вроде бы обновляется в БД благополучно, но если тут же делаю попытку добавления/изменения записи этой же таблицы из второго экземпляра клиентского приложения, то возникает такое вот исключение: 'Cannot perform this operation on a closed database', или что-то в этом роде. Хотя компоненты связи с БД открыты. Что я делаю не так?
wardoc (2006-06-27 15:26:00) [1]2Ломброзо:
Я не использую ADO, но все равно спасибо за совет закрывать соединение после обмена данными. Что касается того, что компонент-провайдер лежит в модуле данных в единственном экземпляре - да это так, но ведь настройки модуля данных таковы, что на каждого подключенного клиента в память загружается отдельный экземпляр модуля данных. Разве это не должно обеспечивать многопользовательский доступ, даже если компоненты открыты? COM+ обязательно попробую.
2DSKalugin:
За ссылку на инфу по dbExpress большое спасибо. Двухфазный коммит - изменение данных на разных серверах? Это клиент должен быть подключен к разным серверам одновременно что-ли?
DSKalugin (2006-06-26 14:27:00) [2]ВЫЛфдгпшт=DSKalugin
не той раскладкой свой ник написал :-)
Автоматический коннект, транзакцию и отсоединение реализовано в библиотеке dbExpress насколько я правильно понял
http://ibase.ru/devinfo/dbexpress.htm
ВЫЛфдгпшт (2006-06-26 14:22:00) [3]В Интербейзе есть такое понятие как Двухфазный коммит. Изменение данных на разных серверах в контексте одной общей транзакции.
Возможно использование этого механизма решит вашу проблему
Ломброзо (2006-06-25 12:16:00) [4]неправильная архитектура.
Сервер приложений должен управлять распределением нагрузки на СУБД, для чего обычно реализуется механизм, обеспечивающий кэширование и повторное использование соединений к БД (с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+.