Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.30;
Скачать: CL | DM;

Вниз

Обновлении данных в многопользовательских программах   Найти похожие ветки 

 
Vovovanych ©   (2004-05-11 08:58) [0]

Уважаемы Мастера! Вопрос об обновлении данных при многопользовательском использовании базы данных Interbase: имеется таблица, с которой очень активно работает десяток пользователей (добавляют, редактируют и удаляют записи). Как сделать (без повторного переоткрытия таблицы) чтобы у каждого пользователя была постоянно самая свежая и актуальная информация? Как считывать из базы именно добавленные или обновленные данные?


 
Anatoly Podgoretsky ©   (2004-05-11 09:04) [1]

Без переоткрытия?
Добавить timestamp


 
Sergey13 ©   (2004-05-11 09:29) [2]

2Vovovanych ©   (11.05.04 08:58)  
ИМХО, твои мечты из серии - "Миссия невыполнима".


 
Nikolay M. ©   (2004-05-11 09:38) [3]

Если трехзвенка, то все изменения идут через application-server, который рассылает изменения всем клиентам-подписантам.
То, что это будут тормоза, глюки и вообще скорее всего не нужно, говорить не буду - и так понятно.


 
stud ©   (2004-05-11 10:18) [4]

если пользователи активно работают с базой то большая часть времени будет уходить на обновление данных а нужно ли это?


 
Locker   (2004-05-11 11:36) [5]

2 Vovovanych
Творите, выдумывайте, пробуйте... Решения задачи есть.
Вариант 1. Использование в каждой записи поля "Время последнего обновления". И выборка по этому полю. (Никогда не пробовал - может, и есть смысл, но, при большом количестве таблиц в проекте, будут тормоза с перебором таблиц).
Вариант 2. Использование таблицы синхронизации, в которую, при каждом изменении в других таблицах, вносится имя измененной таблицы и ключ записи. Кроме этого нужно автоинкрементное поле - для того, чтобы знать, с какой записи читать новые данные о синхрониации. И еще - таймер.

2 Sergey13
Не умеете сами - не мешайте другим...

2 stud

Сколько времени нужно на выборку одной записи из таблицы с миллионом записей? Посчитайте - и поймете, что синхронизация - это лучше, чем ручное обновление всей таблицы: быстрее, незаметнее и траффик низкий.

2 Nikolay M.
Объясните, почему это не нужно?


 
Курдль ©   (2004-05-11 11:42) [6]


> Locker   (11.05.04 11:36) [5]

Примените к себе свой же совет, который адресовали Sergey13
Автору не интересно знать, когда-что было обновлено, а надо рассылать Event-ы клиентам, как только что-то обновилось. Этим занимаются и вправду тяжеловесные, и чаще всего не оправдывающие себя Application-серверы, либо некоторые DB-серверы. Главное для него - определить, насколько это нужно пользователям. Лично я, не зная бизнесс-процессов, за решение не возьмусь.


 
Desdechado ©   (2004-05-11 11:48) [7]

2 Locker
вот пользователь редактирует запись, а ему автоматически раз - и обновили ее. вот матюки будут...

и что, для каждой записи свой запрос на проверку обновления? для выборки из 200 строк - 200 запросов? тормоза обеспечены, особенно если это с интервалом в 1 мин делать.

а про миллион загнул - никто на клиенте с таким количеством не работает


 
Sergey13 ©   (2004-05-11 11:48) [8]

2Locker   (11.05.04 11:36) [5]
А вы братец - хам. Именно потому что знаю как это делается и говорю, что при поставленых условиях задача невыполнима. Выполнима, но с большими затратами при других условиях. Но в любом случае проблема надумана и реализовывать ее не стОит. Никому это не надо. Достаточно одной кнопки "Обновить".
А твои советы - ну от Locker-а чего еще ждать. 8-)


 
div ©   (2004-05-11 11:53) [9]

(ИМХО) использовать на всех клиентах транзакции no_rec_version. Однако я уверен что при этом возникнут проблемы с блокировками записей. Видимо нужно использовать в транзакции параметр wait. Что касается Event"ов - то если работа действительно интенсивная, и при каждом изменении/удалении производить обновление - то думаю что как минимум половина пользователей только и будут делать что ждать обновления данных. Поэтому думаю стоит зделать обновление либо "вручную", либо по таймеру (например раз в минуту, это зависит от объемов).


 
Erik ©   (2004-05-11 12:28) [10]

Чего за фигня, я сделал обновление и все работает. У меня AppServer смотрит нужно ли пользователю обновление, если нужно вызывает CallBack передавая имя таблицы на клиента. Клиент смотрит какие формы подписались на даное событие и вызывает их метод обновления. Правда необходимось в обновлении у меня возникает не часто.


 
Danilka ©   (2004-05-11 12:36) [11]

Как я люблю этот вопрос! :))

[10] Erik ©   (11.05.04 12:28)
Интересно, а как он узнает - нужно пользователю обновление или нет? Например, пользователь утром запустил приложение, открыл все формы какие есть и пошел кофу попить, а потом водки, и весь день АппСервер думает что пользователю нужно обновление?


 
Locker   (2004-05-11 12:44) [12]

2 Sergey13
Прежде чем обвинять кого-то в хамстве - найдите повод обвинять!

Задача: Есть список (таблица) клиентов - физических лиц. В таблице - 50000 записей. Добавляем нового клиента. Скажем, 100 новых клиентов в день.
Вопрос: Как другим пользователям узнать, что в БД добавлен новый клиент? Обновлять все 50000 записей (хм...)? Или только запросить из БД новую запись? И как это сделать? Что проще: по 1 результирующей строке в запросе обновления, или по 50000 строк в каждом "ручном обновлении" кнопкой?

2 Desdechado
>> вот пользователь редактирует запись, а ему автоматически раз - и обновили ее
Для таких случаев в Pascal"e есть условный оператор:
if (not DataSet.State in [dsEdit, dsInsert]) then
begin
 // обновление
end;


 
Nikolay M. ©   (2004-05-11 12:52) [13]


> 2 Nikolay M.
> Объясните, почему это не нужно?

Потому что по большому счету я согласен с [2].
Тема поднималась уже раз 100, наверное. Пока было предложено единственно правильное решение - обновлять запрос по нажатию юзером кнопки. Все остальное - от лукавого.

ПС
Кстати, тут прозвучали мысли о посылке апп-сервером клиентам сообщения, что нужно обновиться. Гораздо логичнее, имхо, рассылать собственно изменения, а не заставлять кучу юзеров ломиться рефрешить свои данные. Собственно, я об этом сказал еще в [3].


 
Mike Kouzmine ©   (2004-05-11 12:53) [14]

Locker   (11.05.04 12:44) [12] А зачем им это узнавать? Добавили и добавили, слава Аллаху!


 
Danilka ©   (2004-05-11 12:53) [15]

[12] Locker   (11.05.04 12:44)
Гы.
Ну давай возьмем твой надуманый пример. Конктретно вопрос.


> Как другим пользователям узнать, что в БД добавлен новый
> клиент?

А нафига? Нафига им узнавать что добавлен новый клиент?
Ну заполняю я, к примеру, счет-фактуру, выбираю клиента из списка клиентов, при этом на момент выбора клиента идет запрос к серверу.
Момент времени, при котором я открываю список клиентов, ищу того, который мне нужен и выбираю его в СФ очень короткий. Даже если за этот момент и появился новый клиент - он мне по-барабану.

> Обновлять все 50000 записей (хм...)?

Вообще, тянуть столько записей на клиента - грех.


 
Danilka ©   (2004-05-11 13:11) [16]

[12] Locker   (11.05.04 12:44)
И еще, вот тебе ненадуманный пример: запрос на 12 килобайт из доброго десятка таблиц и вьюх, возвращает как-раз сотню записей (в таблицах десятки и сотни тысяч записей), ну-ка куда и чего надо добавить, чтобы получить только обновленные записи?
И добавь-ка дорогой все эти обновленные данные в грид, и только тем пользователям, кому надо (если отвернулся от монитора, значит ему не надо).


 
Desdechado ©   (2004-05-11 13:23) [17]

[12] Locker
гы, ладно, внес изменения, запостил, но в БД не сохранил - что здесь, а?


 
VoVovanych ©   (2004-05-11 16:32) [18]

Тпру... Стойте, остановитесь. Не думал что мой вопрос вызовет такую бурю эмоций. Тем более разбирательств "хам-нехам" :) Я возможно не совсем корректно задал вопрос: возможно ли получить в УЖЕ ОТКРЫТЫЙ запрос запись, добавленную другим пользователем, тем более что необходимость в актуальных данных имеется (привести полностью постановку задачи не могу, долго и нудно)? Пробовал использовать FIBPlus (ОГРОМНОЕ СПАСИБО Сергею БУЗАДЖИ, обещаю купить лицензионку), там есть компонент FIBDataSet и у него метод Refresh, который автоматически после вставки или удаления обновляет именно ту запись, в которой произошли изменения (естественно не на всех машинах, а на той где эти изменения и произошли :)). Кто не знаком с FIBDataSet хочу пояснить что запрос на обновление выглядит примерно так: Select X From Y Where Z=:OLD_ID (ID ключевое поле таблицы). То есть при редактировании, точнее после редактирования, вызывается этот самый запрос, в котором параметру OLD_ID присваивается значение ID той самой отредактированной записи и соответственно обновляется только эта запись. Уф-ф-ф-ф... Надеюсь понятно объяснил. Так вот, я пробовал сделать так: приложение получало от сервера сообщение о том что добавлена или изменена запись, передавался ID записи, я пытался передать этот ID в запрос как OLD_ID (примерно так qryAAA.ParamByName("OLD_ID").As Integer:=ID) и вызвать Refresh... Безрезультатно :(  Получаю ошибку что-то типа "Параметр OLD_ID не существует". Как насчет такого варианта развития события?

2Sergey13 В данный момент у меня стоит кнопка "Обновить"... Многим не нравиться, да и не помогает: рефрешатся каждую минуту...

2Anatoly Podgoretsky: Часто читаю Ваши ответы и они помогают. Единственная проблема - краткие они очень :)... Если можно, разъясните несколько подробней. Разжевывать не надо, просто нарежьте :)))


 
Курдль ©   (2004-05-11 17:23) [19]

Боюсь, что никакие FIBDataSet-ы с обновлением одной записи Вам не поможет, т.к. он вернет ее только Вам же, а не всем юзерам.


 
Petr V. Abramov ©   (2004-05-11 18:52) [20]

> рефрешатся каждую минуту...
 Либо у них нету возможностей поиска
 Либо постановка задачи нехорошая
 Либо это действительно надо (1% вероятности). Тогда либо event`ы, либо AppServer какой-нить масти


 
AGin   (2004-05-11 19:23) [21]

2 VoVovanych Мне кажется, что в Вашем случае поможет несколько извращенное решение - использовать обычные GRID"ы (НЕ DBGRID"ы) для отображения информации (или другие контролы). Тогда от пользователя будет скрыта вся внутренняя работа программы по обновлению данных. А данные следует обновлять, как советовал А.Подгорецкий (и другие) - в каждую нужную таблицу добалять поле timestamp и раз в минуту просматривать ID отредактированных за эту минуту записей. При наличии таковых - обновлять информацию в GRID"ах ВРУЧНУЮ. Это, конечно, геморрой, но не очень большрй...:))


 
Anatoly Podgoretsky ©   (2004-05-11 19:45) [22]

VoVovanych ©   (11.05.04 16:32) [18]
Как считывать из базы именно добавленные или обновленные данные?

Anatoly Podgoretsky ©   (11.05.04 09:04) [1]
Добавить timestamp

Без временной метки это не возможно сделать, ты никак не отличишь обновленную от необновленной. Каждая запись в таблицу должна делаться с обновленной меткой, тогда в запросе можно будет указать TS>OldTS, вернутся все новые и обновленные


 
VoVovanych ©   (2004-05-11 21:58) [23]

2 Курдль: не совсем. Каждое запущенное приложение получает от сервера сообщение и запускает у себя процедуру обновления данных. Теоретически это задумывалось так :). Практически не получилось. Так и родился сабж...

2 Petr V. Abramov ©: Возможность поиска есть, причем настолько навороченная, что лучше уж по моему быть не может (просьба не изголятся по поводу навороченности, не тратьте время) :) Просто для оперативного решения вопросов необходимо видеть ВСЁ...

2 ВСЕМ: попытка №3. Отвлечемся от постановки задачи, кнопок принудительного обновления, timestampов, правильно-неправильно и т.д. Будем считать что мы знаем какие записи нужно обновить (добавить и т.д.). ЗАДАЧА: КАК В УЖЕ ОТКРЫТЫЙ ЗАПРОС ПОЛУЧИТЬ С СЕРВЕРА НОВЫЕ (ОБНОВЛЕННЫЕ) ДАННЫЕ? То ли лыжи у меня не едут, то ли одно из двух.


 
Polevi ©   (2004-05-11 23:02) [24]

запросить эти данные во временный датасет, ручкам пробежать по нему и обновить рабочий сет
еснно нужно ключевое поле для сопоставления записей


 
Petr V. Abramov ©   (2004-05-11 23:05) [25]

CachedUpdates = true
 отдельный запрос обновлений (пусть qrRefresh) по таймеру или по event`ам
 ручная перекачка записей из qrRefresh в основной
 возможно, еще геморрой с соблюдением сортировки


 
Курдль ©   (2004-05-11 23:20) [26]


> VoVovanych ©   (11.05.04 21:58) [23]
> (добавить и т.д.). ЗАДАЧА: КАК В УЖЕ ОТКРЫТЫЙ ЗАПРОС ПОЛУЧИТЬ
> С СЕРВЕРА НОВЫЕ (ОБНОВЛЕННЫЕ) ДАННЫЕ? То ли лыжи у меня
> не едут, то ли одно из двух.

Вы достаточно тертый калач, но ленитесь! Для себя бы я чё-нить придумал (пока что просто таких ТЗ не попадалось) а для Вас - тоже лень :)
Ну есть идея (в предсонном бреду) создать журнал логов на значимые таблицы и "вести" в нем по триггерам изменения значимых полей. Отдельным запросом порлучать свежие данные, обрабатывать на клиенте по принципу "это у нас уже есть, а это, ты глянь,  - изменилось!". А потом насильственно записывать в набор данных обработанные изменения.
И далее - давайте по понятиям! Что есть "ОТКРЫТЫЙ ЗАПРОС"? Видимо "ПОЛУЧЕННЫЙ НАБОР ДАННЫХ"?


 
Polevi ©   (2004-05-11 23:27) [27]

> [26] Курдль ©   (11.05.04 23:20)
скорее всего открытый запрос у него квери в гриде отображается и он не хочет целиком перезапрашивать его, имеет смысл в принципе если большая выборка и реализован эффективный механизм уведомлений об изменениях, хотя это не просто.. много холостых данных и проблема с редактированием, о чем уже говорилось
хотя при желании можно конечно сделать, проблему холостых данных можно решить через подписку на события об изменениях и отписываться в случае если юзер не работает с программой..
мое имхо лучше без этого обойтись


 
Курдль ©   (2004-05-11 23:34) [28]

Да просто может не следует комплексоваться на избранной структуре? Ведь решений может быть немеряно! Уже 100 раз говорили об application server. Да взять какой-нить апач на сервер, забульбенить логику на сервлетах Java, а юзерам - апплеты через браузер (заодно проблема вэб-доступа сразу решится, а то ее в ТЗ всегда как "перспективную фитчу" прописывают :)


 
Polevi ©   (2004-05-11 23:39) [29]

да с app-server тоже не фонтан
проблема в том что нефиг качать данные туда-сюда когда их никто не ждет


 
Курдль ©   (2004-05-11 23:44) [30]


> проблема в том что нефиг качать данные туда-сюда когда их
> никто не ждет

Если он так упорно настаивает на том, что надо, значит кто-то ждет. Другое дело, что вряд ли следует привязываться к стандартным принципам работы с БД. Например, через сокеты транслировать все обновления "бегущей строкой" от сервака к клиентам (как сделки на бирже) а там уж каждый клиент по наборам данных раскладывает...


 
SteelAxe   (2004-05-12 04:04) [31]

2VoVovanych ©   (11.05.04 21:58) [23]CachedUpdates = true
1.Получаешь с сервака набор, открываешь(запуск программы).
2.редактируешь датасет в соответствии с AppEvents.
3.Если ТЕКУЩИЙ клиент редактирует запись, то ВЫВОДИШЬ ЗАПИСЬ В   ОТДЕЛЬНОЕ ОКОШКО и пусть он там её себе редактирует. При сохранении этой записи отсылаешь ОТДЕЛЬНЫЙ запрос-сохранение на сервер И В СВОЙ ОТКРЫТЫЙ ДАТАСЕТ со значениями, считанными с ЭТОГО ОКОШКА.
4.В конце работы закрываешь датасет без сохранения сделанных изменений.
Здесь кратко, но, думаю, понятно. Надеюсь подойдёт.


 
VoVovanych ©   (2004-05-13 07:14) [32]

Спасибо всем кто ответил. Вариантов предложена куча, есть над чем подумать. Еще раз спасибо.



Страницы: 1 вся ветка

Текущий архив: 2004.05.30;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.024 c
1-1084735371
Chlavik
2004-05-16 23:22
2004.05.30
TGraphicControl и его отрисовка за пределами его :)


1-1084361905
Ilya53
2004-05-12 15:38
2004.05.30
ActiveX DLL и Delphi


14-1084363364
WondeRu
2004-05-12 16:02
2004.05.30
Delphi 8. Где OpenGL, DirectX и т.п.?


7-1082821306
Aplay
2004-04-24 19:41
2004.05.30
Узнать о DivX


3-1083711368
Dark Man
2004-05-05 02:56
2004.05.30
Работа с SQL Server 2000 из под Delphi 5