Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
Рискну перебросить еще вопросик: Задача следующая: Надо для некоторой экранной формы(не грид) обеспечить доступ к единственной строке таблицы так, чтобы массив сканировался другими задачами без задержек, но другой юзер не смог бы скорректировать эту запись ( аналог RLock() в языках xBase ). Делаю так: declare c1 cursor SCROLL DYNAMIC for select aserty,z,m from a1 with(HOLDLOCK) for update open c1 declare @aserty int,@z char(10),@m numeric(18,0) -- Позиционирование в таблице, например так fetch next from c1 into @aserty,@z,@m while @aserty<>'680580' fetch next from c1 into @aserty,@z,@m -- Вышли на нужную запись --Далее отдаем в экранную форму и юзер минут 5 соображает что и как корректировать.При этом таблица сканируется и соседние записи корректируются но текущую запись через простой UPDATE не изменить, то есть вроде запись захвачена. Затем UPDATE a1 set z='proc1 ',m=66 WHERE CURRENT OF c1 Все хорошо, если в этот момент другой юзер таким же курсором не изменит эту же запись (за 2 минуты ) Тогда - облом, либо перечитай запись и сразу корректируй - это пройдет. Как же все-таки изобразить RLock() ? Можно ли определить, что эта запись уже кем-то прихвачена? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2002, 09:49 |
|
||
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
Возможно, Glory меня поправит, но тут я вижу 2 способа решения: 1. Введение поля типа TimeStamp и при сбросе своих измененных данных включать это поле в условие Where (аналог оптимистической буферизации). Т.е. если другой пользователь изменил запись пока ты ее редактировал, то неизбежно было изменено поле TimeStamp и после команды UPDATE ты получишь @@RowCount=0. Дальше делаешь выводы: писать поверх чужих изменений или обновить. 2. Этот вариант значительно хуже. Надо обернуть твою команду транзакцией. Чтобы не блокировалась вся страница, необходимо создать специальное служебное поле (тип и содержание значения не имеют). Код примерно следующий: BEGIN TRANSACTION OneColumnOneRecord UPDATE MyTable SET EditColumn=EditColumn WHERE RecordID=<код редактируемой записи> Далее берешь запись на редактирование SELECT * FROM MyTable WHERE RecordID=<код редактируемой записи> И после завершения редактирования снимаешь транзакцию, причем ROLLBACK или COMMIT совершенно не важно ROLLBACK TRANSACTION OneColumnOneRecord Этот способ плох именно наличием открытой транзакции в течении неопределенно долгого времени. Правда заблокировано только одно поле одной строки, но все-равно, подозреваю, что придется выставлять всем "грязный" уровень изоляции (READ UNCOMMITED), чтобы вообще можно было делать выборки пока кто-то редактирует одну запись. Что уже не есть хорошо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.04.2002, 16:00 |
|
||
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
2ВладимирМ П1. ИМХО не в тему! Я говорил о скроллируемом динамическом курсоре. При этом @@RowCount бессмысленен, Where некуда вставлять, TimeStamp (если есть) отслеживается сервером автоматом, либо через контрольные суммы. По п2. "Правда заблокировано только одно поле одной строки" - а что, уже есть FIELDLOCK ? Я-то думал что только от TABLOCK & PAGELOCK добрались до ROWLOCK Я хотел именно уйти от предлагаемой Вами схемы и в качестве решения наиболее близок мне курсор. В моем примере именно соблюдается выполнение ВСЕХ селектов при текущих (мб и неизвестных) установках уровня изоляции, и всех апдейтов, не затрагивающих данную запись. Так что курсор мне ПОЧТИ подходит. Однако различные клиенты (или коннекты) с таким курсором конкурируют за эту запись совершенно одинаково, вне зависимости от того, кто первым к ней обратился. Я хотел бы чтобы захват надежно удерживал запись, вне зависимости от типов других курсоров в иных приложениях, средств разработки и способах доступа к серверу (Fox/Delpi, ADO/ODBC...) Вопрос остается - как определить,что нужная запись уже кем-то прихвачена и как не дать другому ее изменять? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2002, 11:53 |
|
||
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
Ну уж если совсем в лоб, то: -- выбираем информацию для редактирования -- (по aserty нужен уникальный индекс) BEGIN TRAN select aserty,z,m from a1 with(UPDLOCK,ROWLOCK,HOLDLOCK) where aserty='680580' -- собственно изменяем и сразу завершаем транзакцию UPDATE a1 set z='proc1 ',m=66 where aserty='680580' COMMIT Минус - плохой UPDLOCK будет висеть все время пока открыта транзакция. Однако, он хоть не мешает читать. Есть вариант более эффективный при большой нагрузке, пару месяцев назад видел в конфе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2002, 13:34 |
|
||
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
2 Варяг Вы пытаетесь использовать подходы xBase в SQL, что несколько ненормально. Отсюда Ваше желание использовать курсор, который нужен совершенно для другого (честно говоря практически и не нужен, за редким исключением). Необходимо менять логику. В SQL в принципе нет механизмов "надёжного удержания записи". Но зато есть возможность реализовать нечто подобное. Вы совершенно напрасно с ходу отвергли П1, который предложил ВладимирМ. Задумайтесь всё-таки над ним. Вам выше предлагали способы блокировки записей, в принципе они рабочие(2000-й блокирует на уровне записи и 7-й по-моему тоже). Но не стоит ими пользоваться, это просто притягивание возможностей SQL под Ваши желания. Что касается Вашего вопроса Можно ли определить, что эта запись уже кем-то прихвачена? , то наверное нельзя, поскольку такого действия как "прихватывание записи" нет. Меняйте логику работы с БД. С приветом Сергей ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2002, 14:57 |
|
||
|
Захват единственной записи
|
|||
|---|---|---|---|
|
#18+
Я делал блокировку по такому алгоритму: 1) добавил поле в таблицу username varchar(25) default '' 2) когда вибираю данные (открываю накладную, делаю с помощью хранимой процедуры) проверяю если пустое поле то я один с ним работаю, присвоюю свой user_name(), если не пустое то с ней работает пользователь имя его в username, 3) когда выхожу из накладной, присваиваю username='' плюсы быстрота выполнения!!!!!, минусы во время работы с накладной пропала связь и накладная осталась заблокированой (ввел кнопочку "разблокиравать", эта кнопочка появляеться для людей которые имеют соответствующие права (роль на сервере unloc_nakladna_role)) сейчас думаю что надо было добавить поле userid int, вместо username, всеже есть разница 4 байта и 28, економия 14 байт ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.04.2002, 20:53 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32027894&tid=1823071]: |
0ms |
get settings: |
9ms |
get forum list: |
19ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
57ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
62ms |
get tp. blocked users: |
1ms |
| others: | 266ms |
| total: | 437ms |

| 0 / 0 |
