Текущий архив: 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.55 MB
Время: 0.042 c