Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > InterBase: транзакции - read_commited


Автор: pavelv 13.4.2009, 08:43
Ситуация: 2 пользователя загрузили программу. Оба заходят как бы в одну таблицу и начинают добавлять записи. Всё проходит нормально, без косяков, но они не видят что добавил другой из них...а очень как хочется smile.  В принципе можно сделать, чтобы они это видели, если сделать рефреш запроса. Но в какой момент это делать? Да и вообще наверное это нужно делать на уровне БД, а не на уровне языка. В общем, что да как посоветуйте.
 А ещё иногда оба начинают редактить одну и туже запись и тут вообще аут начинается.... 

P.S> Использую понятно read_commited + rec_version + nowait.


Автор: Frees 13.4.2009, 12:42
в FireBird есть Post event позволяющий оповещать клиентов об изменениях
в IB наверно тоже есть

в тригере после обновления(вставки, удаления) пишеш  Post event 'UPDATE'

а в программе береш компонент IBEvents(он ловит эти сообщения из базы) и читаеш по нему хелп

Автор: Akella 13.4.2009, 13:29
Цитата(pavelv @  13.4.2009,  08:43 Найти цитируемый пост)
Оба заходят как бы в одну таблицу и начинают добавлять записи. Всё проходит нормально, без косяков, но они не видят что добавил другой из них...а очень как хочется 

После добавления нужно делать close/open smile

Добавлено через 3 минуты и 10 секунд
Цитата(pavelv @  13.4.2009,  08:43 Найти цитируемый пост)
А ещё иногда оба начинают редактить одну и туже запись и тут вообще аут начинается.... 

ну а как ты хотел smile
Постарайся сделать так, чтобы пишущие транзакции были как можно короче.

Автор: pavelv 14.4.2009, 08:08
с IbEvents понял, спасибо. Akella сделать пишушие транзакции как можно короче, это же не означает делать пост после каждого измененного поля? smile Просто конечно способ действенный, но думаю вы не это хотели сказать.
  А есть какая-нибудь возможность заблокировать на редактирование запись которая уже редактируется? Я конечно не имею ввиду случаи с использованием временной таблицы, куда постоянно будет стекать инфа о том какие таблицы и кем сейчас редактируются и далее при попытке редактирования просто брать её оттуда. Хочется что-нибудь покрасивее и на уровне компонентом чтоли.

Автор: Frees 14.4.2009, 08:15
Цитата(pavelv @  14.4.2009,  10:08 Найти цитируемый пост)
  А есть какая-нибудь возможность заблокировать на редактирование запись которая уже редактируется? Я конечно не имею ввиду случаи с использованием временной таблицы, куда постоянно будет стекать инфа о том какие таблицы и кем сейчас редактируются и далее при попытке редактирования просто брать её оттуда. Хочется что-нибудь покрасивее и на уровне компонентом чтоли.

http://www.ibase.ru/devinfo/pslock.htm

Автор: Akella 14.4.2009, 09:45
Цитата(pavelv @  14.4.2009,  08:08 Найти цитируемый пост)
Akella сделать пишушие транзакции как можно короче, это же не означает делать пост после каждого измененного поля? 

Нет. Нужно сделать примерно так:
Пользователь нажимает кнопку Редактировать.
Программа считывает в элементы управления все данные из записи. Но сама запись на редактирование не открывается, т.е. никакого update не происходит. Т.о. запись не блокируется.
Пользователь что-то меняет на форме.
Нажимает кнопку Cохранить. И вот здесь уже работает пишущая транзакция.

Т.е. пользователь может держать форму редактирования/добавления (без выполнения update table) достаточно долго. Т.о. пишущая транзакция работает _только_ в момент сохранения/добавления записи.

При этом требуется учитывать специфику работы пользователей и самого приложения. Проблема может быть в том, что запись нужно будет блокировать на время редактирования. В этом случае обрати пристальное внимание на сообщение уважаемого Frees`а  smile 

Автор: pavelv 14.4.2009, 11:38
Угу Akella 10x, но именно специфика не позволяет так работать. Frees тоже спасибо, линк полезный.
Возник один вопрос, вроде читал внимательно и проверил как работает - круто smile. 
 Но проблема вот в чем: два человека могут открыть одновременно одну группу записей, как бы попадающих под общую специфику.  Так вопрос:
1) можно сделать "for update with Lock" для всей группы записей при открывании формы. 
   +) Нет мозгопарства, один запрос.
   -) Двое уже не зайдут. А если и зайдут, то второй максимум что сможет это смотреть в режиме чтения и ничерта не поймёт при этом. Мало того второй может хочет поменять вовсе не ту запись которую редактирует первый.
2) можно сделать "for update with lock" только для конкретной записи при её изменении, но тогда у пользователя вынужденны будут исчезнуть остальные записи группы пока он не закончит редактирование. 
   +) Lock одной записи
    -) Всё исчезло неожиданно, пользователь в шоке, начинается паника в отделе и звонки во все инстанции включая президента.

Как бы так от минусов избавиться хитро? В идеалы бы как-нибудь открыть все записи, а при редактировании заблокировать текущую и после редактирования все измененные данные скинуть, предварительно завершив лок.

Автор: Frees 14.4.2009, 11:59
Цитата(pavelv @  14.4.2009,  13:38 Найти цитируемый пост)
но тогда у пользователя вынужденны будут исчезнуть остальные записи группы пока он не закончит редактирование. 

почему исчезнут, поясни чет я не пойму

Автор: pavelv 14.4.2009, 13:23
Изначально выборка ведется допустим: 
Код

 select * from table1 where bla-bla bla


Затем, чтобы залочить только одну запись(это второй случай), нужно видимо сделать так:
Код

 select * from table1 where bla-bla bla and ID=X FOR update with lock


Если при этом результат запроса было видно в ДБГрид, то их там больше не будет ибо запрос поменялся. 

Автор: Frees 15.4.2009, 13:35
Цитата(pavelv @  14.4.2009,  15:23 Найти цитируемый пост)
Затем, чтобы залочить только одну запись(это второй случай), нужно видимо сделать так:код Pascal/Delphi1: select * from table1 where bla-bla bla and ID=X FOR update with lockhighlightSyntax('delphi_YxOGQ0','delphi');Если при этом результат запроса было видно в ДБГрид, то их там больше не будет ибо запрос поменялся. 

для такого случая можно использовать еще один запрос(не Грида)

либо заблокировать в этом датасете если нет авто комита то 

Код

DataSet.Edit;
DataSet.Post;
//выполнится "пустой" update


заблокирует текущую запись, в FIBPlus вместо едит пост есть спец метод LockRecord. 
Компоненты доступа у тебя какие?


Автор: pavelv 16.4.2009, 05:04
Цитата
для такого случая можно использовать еще один запрос(не Грида)

Но в этом случае прийдется редактировать записи именно через него. Представь форму, сверху грид со всеми записями, а ниже параметры текущей записи доступные для редактирования. Возьму другой запрос, все поля для редактирования нужно переделывать для него. А там компоненты использованы: TDBEdit, TDB*.... Ну кароче датасурс во всех поменять прийдется. Сильно муторно думаю...

Компоненты доступа:
TibTable + DataSource  + IbUpdateSqlW
FireBird 2.0

Слушай гляну сейчас, если есть LockRecord то вообще никаких проблем получается

Автор: Frees 16.4.2009, 06:16
Цитата(pavelv @  16.4.2009,  07:04 Найти цитируемый пост)
Но в этом случае прийдется редактировать записи именно через него.

нет можно и через датасет грида редактировать если он в той же транзакции

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)