блокировка записи

Обсуждение вопросов по разработке программ в среде продуктов копорации "Progress Software"
new
Старожил
Сообщения: 32
Зарегистрирован: 28 мар 2002, 03:00

Сообщение new » 30 мар 2002, 18:55

Ситуация:
Пользователь 1 (u1) держит запись в EXCLUSIVE-LOCK, Пользователь 2 (u2) пытается проапдейтить её же. U2 весело наблюдает блокировку.
Ситуация усложняется тем что программа которой пользуется u1 корявая (т.е. висит месага ОК, u1 пьёт чай и думает что всё хорошо)
вопрос: что будет с u2 через полчаса? :smile:
Как можно обработать блокировку у u2 програмно.
ограничение задачи: поправить прогу с которой работает u1 - невозможно. :sad:

Да и по возможности извлечь максимум информации о том кто блокирует.
вот.

буду благодарен любой информации

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

re:блокировка записи

Сообщение dmi » 30 мар 2002, 22:17

Ситуация:
Пользователь 1 (u1) держит запись в EXCLUSIVE-LOCK, Пользователь 2 (u2) пытается проапдейтить её же. U2 весело наблюдает блокировку.
Ситуация усложняется тем что программа которой пользуется u1 корявая (т.е. висит месага ОК, u1 пьёт чай и думает что всё хорошо)
вопрос: что будет с u2 через полчаса? :smile:
Как можно обработать блокировку у u2 програмно.
ограничение задачи: поправить прогу с которой работает u1 - невозможно. :sad:

Да и по возможности извлечь максимум информации о том кто блокирует.
вот.

буду благодарен любой информации


Можно в критических местах лочить запись include-файлом.

{1} - таблица
{2} - блок, откуда надо LEAVE сделать.

/*lock.i */
w-recid = RECID({1}).
FIND {1} EXCLUSIVE-LOCK WHERE RECID({1}) = w-recid NO-WAIT NO-ERROR.
IF LOCKED {1} THEN DO:
MESSAGE "Record in use by another user." VIEW-AS ALERT-BOX.
LEAVE {2}.
END.

Чтобы узнать, кто залочил - используй VST
(Virtual System Table)
Там есть таблица _lock. Если не знаешь, что это такое - найдешь в knowledge base у Progress.

/dmi

Гость

re:блокировка записи

Сообщение Гость » 01 апр 2002, 08:26

Юзер, делающий попытку залочить запись и наблюдающий сообщение record is in use by another (или как оно там?) через некоторое время БУДЕТ ОТКЛЮЧЕН ОТ БАЗЫ :???: Пробовал просматривать таблицу блокировок через VST и пришел к выводу, что так можно узнать только КТО УДЕРЖИВАЕТ запись. Если пытаться искать неблокированную запись, то прога виснет (а точнее, поиск длится бесконечно). :mad: Версия 9.1С.

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 01 апр 2002, 08:30

Мессага выше - моя. Что-то не срослось на форуме :smile:

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

re:блокировка записи

Сообщение dmi » 01 апр 2002, 13:29

Юзер, делающий попытку залочить запись и наблюдающий сообщение record is in use by another (или как оно там?) через некоторое время БУДЕТ ОТКЛЮЧЕН ОТ БАЗЫ :


raise STOP это называется. Да.
Для решения такой ситуации - используй FIND
с NO-WAIT.
Иначе возникнет ситуация "гонок" (или как их там :wink:)

o По умолчанию это время - полчаса. Вот это было сюрьпризом.


-lkwtmo = 1800 sec, возможный минимум 60sec, для WebSpeed - 10sec.

Второй сюрьприз - это невозможность отпустить запись внутри транзакции :sad: Например, блокируем записи в цикле, очередную не смогли (занята). Первое, что приходит в голову - откатить субтранзакцию (весь цикл), подождать и повторить весь цикл заново. Так вот, откат не освобождает уже заблокированные в цикле записи.


Можно код посмотреть?
И как ты lock записей смотрел?

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


Я не понял вот этого ^^^^^^^^^.
Пробовал просматривать таблицу блокировок через VST и пришел к выводу, что так можно узнать только КТО УДЕРЖИВАЕТ запись.


Верно. Давай код посмотрим, действительно?
Если пытаться искать неблокированную запись, то прога виснет (а точнее, поиск длится бесконечно). :mad: Версия 9.1С.


А как и что ты пытаешься искать?

ps:
Попробуй почитать:
Из Progress Software Technical Support Note # 5929

REFERENCES TO WRITTEN DOCUMENTATION:
====================================

PROGRESS Language Reference Manual - References to Block Statements
such as DO, FOR EACH, REPEAT.
Also Record Phrase and
COMPILE LISTING.

PROGRESS Programming Handbook - References to Transactions,
Record
Scope, Record-locking, Block
Properties and istrans.p.

/dmi

<font size=-1>[ Это Сообщение было отредактировано: dmi в 2002-04-01 17:31 ]</font>

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 03 апр 2002, 09:35

raise STOP это называется. Да.
Для решения такой ситуации - используй FIND
с NO-WAIT.
Иначе возникнет ситуация "гонок" (или как их там :wink:)

С этим-то понятно. Без этого пользователи нас загрызли бы давно :smile: За такие "ожидания".
-lkwtmo = 1800 sec, возможный минимум 60sec, для WebSpeed - 10sec.

Это тоже знаем. Еще когда начинали работать, попробовал поменять этот параметр. Опять же, обругали. Именно тогда я обнаружил, что выполняется этот raise stop :smile: Просто такое поведение было неожиданным :wink:

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 03 апр 2002, 13:55

По поводу снятия блокировок. Вот пример кода:

label-1:
DO TRANSACTION:
/* some actions here */
label-2:
DO TRANSACTION:
/* some actions here */
FOR EACH table1 EXCLUSIVE-LOCK:
/* some actions here */
END.
MESSAGE "After FOR" VIEW-AS ALERT-BOX.
UNDO label-2.
END.
MESSAGE "After subtransaction" VIEW-AS ALERT-BOX.
END.

Допустим, во внейшней транзакции с таблицей table1 ничего не делали (не меняли ее). Пишем в нее в субтранзакции (блокируя записи само собой). Потом откатываем субтранзакцию.
При висящем окошке второй мессаги смотрим промоном таблицу блокировок и видим, что записи table1 остались залочены. И таковыми останутся до завершения транзакции (но не субтранзакций). Это и в доке написано, просто очень мне не понравилось. И вот почему. В программе при создании документа сразу открывается транзакция. Юзер старается, вбивает данные. Пытается сохраниться (при этом блокируются, например, товарные карточки). Другой юзер делает то же самое, натыкается на невозможность заблокировать запись. Легко получаем dead lock, взаимную блокировку. Тут бы одному из них откатить СУБТРАНЗАКЦИЮ, до того места, где начинается сохранение документа, и при этом отпустить записи карточек. А сделать последнее НЕВОЗМОЖНО. Изначально один из юзеров был вынужден откатывать всю транзакцию, то есть жертвовать документом. Сейчас добавил таблицу с флагами, процедура предварительно делает там записи О ПРЕДПОЛАГАЕМЫХ блокировках. Dead lock обошли. Но ведь это извращение чистой воды :sad:

Гость

re:блокировка записи

Сообщение Гость » 03 апр 2002, 14:15

Ну и еще насчет невозможности посмотреть, заблокирована ли запись кем-нибудь.
Ввиду невозможности отпустить лок внутри транзакции хотелось бы иметь средство, позволяющее определить, держит кто-нибудь запись или нет, не блокируя ее самому. Функция LOCKED работает только после неудачного FIND, самому делать FIND...EXCLUSIVE-LOCK нельзя по условиям задачи :wink: Пробовал вот такое:

find first sign no-lock no-error.

find first _file where _file._file-name = "sign" no-lock no-error.

find first _lock where _lock._lock-recid = integer(recid(sign)) and _lock._lock-table = _file._file-num and _lock._lock-flag = "x" no-lock no-error.

Так вот, зря я писал, что последний FIND "бесконечный". Не бесконечный он, но!... На реальной работающей базе это заняло 3966 секунд!!! :eek: На локальной "пустышке" - около двух минут (и это при пустой таблице блокировок!), что тоже не сахар. В общем, тут VST не помогают :cry:
Вот, выплакался :roll:

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 03 апр 2002, 14:18

Похоже, "Анонимный" станет моим вторым ником... Как это там... "Сегодня с вами был я, SVR" :smile:

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

re:блокировка записи

Сообщение dmi » 03 апр 2002, 16:27

label-1:
DO TRANSACTION:
/* some actions here */
label-2:
DO TRANSACTION:
/* some actions here */
FOR EACH table1 EXCLUSIVE-LOCK:
/* some actions here */
END.
MESSAGE "After FOR" VIEW-AS ALERT-BOX.
UNDO label-2.
END.
MESSAGE "After subtransaction" VIEW-AS ALERT-BOX.
END.


У тебя тут получается три уровня транзакций,
ты здорово намудрил с ними. Зачем так сложно?
{} Line Blk
-- ---- ---
1 label-1:
2 1 DO TRANSACTION:
3 1 label-2:
4 2 DO TRANSACTION:
5 3 FOR EACH table1 EXCLUSIVE-LOCK:
6 3 UPDATE table1.xxx
7 2 END.
8 2 MESSAGE "After FOR" VIEW-AS ALERT-BOX.
9 2 UNDO label-2.
10 1 END.
11 1 MESSAGE "After subtransaction" VIEW-AS ALERT-BOX.
12 END.
13
14
04/03/2002 16:59:41 PROGRESS(R) Page 2

File Name Line Blk. Type Tran Blk. Label
-------------------- ---- --------- ---- --------------------------------
0 Procedure No
2 Do Yes label-1
4 Do Yes label-2
5 For Yes

Используй опцию LISTING оператора COMPILE, для просмотра кода.


Допустим, во внейшней транзакции с таблицей table1 ничего не делали (не меняли ее).


А зачем тогда транзакция там?

почему. В программе при создании документа сразу открывается транзакция. Юзер старается, вбивает данные.


Зачем так сложно писать? Не надо
растягивать транзакцию на время ввода пользователя. Загони данные в локальные переменные и при нажатии кнопки OK заноси в
базу. Пересечений с другими пользователями
станет на несколько порядков меньше.

Пытается сохраниться (при этом блокируются, например, товарные карточки). Другой юзер делает то же самое, натыкается на невозможность заблокировать запись. Легко получаем dead lock, взаимную блокировку. Тут бы одному из них откатить СУБТРАНЗАКЦИЮ, до того места, где начинается сохранение документа, и при этом отпустить записи карточек. А сделать последнее НЕВОЗМОЖНО. Изначально один из юзеров был вынужден откатывать всю транзакцию, то есть жертвовать документом. Сейчас добавил таблицу с флагами, процедура предварительно делает там записи О ПРЕДПОЛАГАЕМЫХ блокировках. Dead lock обошли. Но ведь это извращение чистой воды :sad:


Ты очень сложно построил процесс ввода документов. У вас есть исходники NS2000?
Если да - посмотри, как сделано там.
Если нет - возьми Progress Programming Handbook, найди главу 13.6 Managing Locks To Improve Concurrency.

Грубо говоря все сводится к таким вещам:

Each time you want to present data to the user for inspection and possible update, follow this
procedure:
1. Request and display the record with the NO–LOCK option.
2. Let the user manipulate the data until the user signals that they have finished (ON LEAVE
OF field, ON CHOOSE OF ok–button, or similar).
3. Request the same record again using the FIND CURRENT or GET CURRENT statement
with the EXCLUSIVE–LOCK option.
4. Use the CURRENT–CHANGED function to see if the original record has changed since
you first presented it to the user.
5. If the record is the same, commit the change.
6. If the record has changed, inform the user, display

Попробуй переработать логику сохранения.

/dmi

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

re:блокировка записи

Сообщение dmi » 03 апр 2002, 16:51

Функция LOCKED работает только после неудачного FIND, самому делать FIND...EXCLUSIVE-LOCK нельзя по условиям задачи :wink: Пробовал вот такое:


Почему?

Подсоединился к базе на сервере, двумя клиентами.
В одном сделал:
--------
DO TRANSACTION:
FIND FIRST mainxref.pcode EXCLUSIVE-LOCK.
MESSAGE "locked" VIEW-AS ALERT-BOX.
END.
--------

Во втором:
---------
FIND FIRST mainxref.pcode EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
IF LOCKED mainxref.pcode THEN DO:
FIND FIRST mainxref.pcode NO-LOCK.
FIND FIRST mainxref._lock WHERE _lock-recid = integer(RECID(mainxref.pcode)) NO-LOCK NO-ERROR.
IF AVAIL mainxref._lock THEN
MESSAGE "record is locked by:" _lock._lock-name VIEW-AS ALERT-BOX.
END.
---------

Все быстро и моментально. 9.1C
Ты много лишних условий написал в find [?]

/dmi

van
Модератор
Сообщения: 407
Зарегистрирован: 12 июл 2001, 03:00

re:блокировка записи

Сообщение van » 03 апр 2002, 17:07

> Ты очень сложно построил процесс ввода
> документов. У вас есть исходники NS2000?
> Если да - посмотри, как сделано там.

:smile:) вот именно "там" это и сделано. svr наоборот пытается распутать этот клубок.
все дело в том, что заказчик наворотил сложные логистические схемы (хотя, сделали все по учебникам торговли), а исполнитель многое реализовал "в лоб", практически не задумываясь о последствиях (субд мол хорошая - все вытянет). теперь идет героическое преодоление.
оказывается, в этом и состоит 70% таинства внедрения.
причем, насколько показывает опыт и наших соседей по другим кис - у них такая же песня.
у меня тут афоризм родился: в программистов надо переучивать бывших саперов - вот это будут кадры :smile:

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 04 апр 2002, 06:51

У тебя тут получается три уровня транзакций,
ты здорово намудрил с ними. Зачем так сложно?

Так было изначально написано. Ввод новых данных производится непосредственно в рабочие таблицы, а не в переменные и не во временные таблицы. Отсюда и транзакции.
А зачем тогда транзакция там?

Я не зря написал /* some actions here */. Под этим подразумевалось изменение других таблиц. То есть без этой внешней транзакции никак.
Не надо растягивать транзакцию на время ввода пользователя.

Я бы рад... Но вся идеология программирования для этой системы (NS2000) изначально завязана вот на такое использование транзакций.

Аватара пользователя
svr
Старожил
Сообщения: 68
Зарегистрирован: 13 июл 2001, 03:00

re:блокировка записи

Сообщение svr » 04 апр 2002, 06:59

Почему?

FIND...EXCLUSIVE-LOCK не хотелось использовать именно потому, что потом этот лок не отпустить. Я же говорил.
Все быстро и моментально. 9.1C

Разница между твоим и моим кодом в том, что когда ты ищешь в _lock, ты уже знаешь, что запись заблокирована другим и соответственно информация об этом ГАРАНТИРОВАННО есть в _lock. А я пытался по результатам поиска в _lock понять, держит кто-нибудь запись или нет. Без попытки блокировки.

FD

Проверка блокировки

Сообщение FD » 19 июл 2002, 11:04

Зачем вы так изголяетесь, чтобы проверить, захвачена запись или нет?
Почему так не написать:

IF NOT CAN-FIND(record WHERE expression SHARE-LOCK NO-WAIT) THEN
MESSAGE "Record is locked" VIEW-AS ALERT-BOX.

Это кусок из Progress 4GL Reference Help про CAN-FIND:

SHARE-LOCK

Specifies that CAN-FIND determines whether the record can be SHARE-LOCKed. If you use this option without the NO-WAIT option, and if the record is EXCLUSIVE-LOCKed, CAN-FIND waits until that lock is released before returning. If you use SHARE-LOCK with the NO-WAIT option, then CAN-FIND returns a FALSE value immediately if the record is EXCLUSIVE-LOCKed.