Запрет одновременного редактирования файла | |
---|---|
lili Автор Сообщений: 472 Откуда: Сыктывкар Дата регистрации: 07.11.2005 |
Приветствую всех!
На СКЛ-сервере в БД есть таблица tblFiles для хранения файлов. Содержимое файлов хранится в поле content(varbinarymax). Для редактирования файла делаю так: Заполняю кусрос-адаптер для данной таблицы. lcFile=c:\tmp\<тут имя файла>, то есть размещаю локально. COPY MEMO tblFiles.content TO (lcFile) Открываю файл в нужном приложении (прописаном в ОС для данного вида файлов), редактирую, сохраняю файл в поле content через tableupdate(). Программа многопользовательская и логично возникла задача запретить одновременное редактирование файла несколькими пользователями. Какие тут могут быть решения? ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
PaulWist Сообщений: 14761 Дата регистрации: 01.04.2004 |
Способ первый (неправильный), наложить монопольную блокировку на строку хинтом xlock
При "начале редактирования"
Разбор Способ второй, идеологически правильный при условии, что к табличке будут обращаться исключительно через API программы - это Блокировка приложения ------------------ Есть многое на свете, друг Горацио... Что и не снилось нашим мудрецам. (В.Шекспир Гамлет) Исправлено 3 раз(а). Последнее : PaulWist, 10.04.24 15:04 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
lili Автор Сообщений: 472 Откуда: Сыктывкар Дата регистрации: 07.11.2005 |
Как-то все это "не очень" удобно для юзеров.
По-хорошему, юзеру должно быть видно, кто и во сколько занял файл на редактирование. ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
PaulWist Сообщений: 14761 Дата регистрации: 01.04.2004 |
Ну, ни кто не мешает в имя ресурса запихать "что-то полезное", например ID таблички и время начала блокировки Прилржения.
------------------ Есть многое на свете, друг Горацио... Что и не снилось нашим мудрецам. (В.Шекспир Гамлет) ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
of63 Сообщений: 26041 Откуда: Н.Новгород Дата регистрации: 13.02.2008 |
() Вот-вот, тоже также изначально сделал "блокировку" в проге - создаю флаг, что де "открыл для записи такой-то ID". Фмзически ничего не блокируется, то программа создания флага читает наличие уже созданного флага "заблокирован ID". Т.е. БД никогда не заблокирована "ковырятелями в носу", а только на момент физической записи в БД (короткий момент)
![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
Владимир Максимов Сообщений: 14154 Откуда: Москва Дата регистрации: 02.09.2000 |
Зависит от того, что именно вкладывается в понятие "одновременное". И вообще, сколько времени может продолжаться сам процесс "редактирования"?
1. Добавить служебные поля с информацией о "блокировке" 2. Блокировка средствами SQL 3. Оптимистическая стратегия обновления Что есть "достоинства", а что "недостатки" для каждого варианта - зависит от решаемой задачи. Т.е. от самого понятия "одновременно" применительно к процессу редактирования 1. Добавить служебные поля с информацией о "блокировке" Собственно, это "закат солнца вручную" ![]() - Кто заблокировал (код пользователя) - Когда заблокировал (дата/время) - Поля с дополнительной информацией, если необходимо. Например, из какой функции была выполнена блокировка Т.е. логика такая 1. Если все служебные поля - пустые, то запись не блокирована можно установить блокировку 2. Под "блокировкой" понимается факт заполнения служебных полей 3. Соответственно, "снятие блокировки" - это очистка служебных полей Достоинства/Недостатки - Наглядность и понятность для пользователя. Поля с информацией о блокировке можно отобразить на форме - Время блокировки - не ограничено. Дни/недели/месяцы - Для снятия блокировки надо дать специальную команду (очистить поля). Если по каким-то причинам команды не было, то блокировка будет висеть "вечно", даже если уже никто ничего не редактирует. Обычно эта проблема решается служебной утилитой по очистке полей 2. Блокировка средствами SQL это то, что Паша описал Достоинства/Недостатки - Простота реализации - В случае разрыва соединения блокировка снимается автоматически - Неочевидность и не наглядность для пользователя. Требует специальных усилий по "расшифровке" того, кто и когда заблокировал 3. Оптимистическая стратегия обновления Собственно, это вопрос из цикла: а оно действительно надо? Клиент-серверные приложения "по определению" работают в режиме оптимистической буферизации. Т.е. никто ничего не блокирует, но при записи делается проверка того факта, что за время внесения изменения пользователем кто-то другой уже успел внести изменения. И если это действительно так, то либо запрет сохранения с сообщением пользователю, либо запись поверх изменений другого пользователя Разумеется, поля varbinary(max) сравнить проблематично и обычно для подобных "сверок" используют поля типа TimeStamp. В MS SQL для этого есть специальный тип данных, но, в общем случае, это может быть и обычный счетчик. Каждый Update увеличивает значение счетчика на единицу. Если при попытке записать текущее значение TimeStamp отлично от значения, которое было при чтении, то запись была изменена другим пользователем Если требуется знать кто/когда внес последние изменения, то создают еще соответствующие поля с названиями вроде ModifedBy, ModifiedDateTime в которые записывают соответствующие значения при любой модификации. Наряду с обновлением поля TimeStamp Достоинства/Недостатки - Стандартный режим работы клиент-серверного приложения - Нельзя запретить вносить изменения разным пользователям "одновременно" - Кроме решения основной задачи имеем некий "лог" изменения. Видно кто и когда последний изменял запись. Правда, не ясно, что именно в записи было изменено, но это уже другой вопрос ------------------------ PS: Есть еще вариант "скрестить ежа с ужом" ![]() Т.е. блокировка средствами SQL через sp_getapplock, но дополнительно, в отдельной служебной таблице записывать все необходимую сопутствующую информацию кто/когда/зачем установил блокировку по этому ресурсу. Идентификатор записи в этой служебной таблице - имя ресурса Таблицу можно даже не очищать при снятии блокировки. Своеобразный "лог" того, кто и когда блокировал ресурс Исправлено 2 раз(а). Последнее : Владимир Максимов, 14.04.24 20:44 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
shumik73 Сообщений: 554 Откуда: Алматы Дата регистрации: 10.05.2006 |
Запрет на редактирование файла - раскрыл 2 темы:
1) Это хранение, выгрузку и загрузку файла 2) Блокировка при совместной работе пользователей При чем вторая тема главная С подобной проблемой сталкиваюсь когда в определенной таблице возникают конфликты, когда 1-ый пользователь открыл первым, 2-ой пользователь позже и оба параллельно выполняют редактирование . Но потом каждый думает что он единственный и вносит свои коррективы и сохраняет. По итогу в базу записывается та версия - кто записал последним. А для другого пользователя потом выявится сюрприз что его работа пропала даром. Чем больше пользователей -тем вероятность конфликтов увеличивается. Требуется внести правили совместной работы 1) Каждый кто открывает должен выполнить проверку - нет ли блокировки документа (в этой таблице, этой записи) 2) Если блокировки до него не было - то он должен заблокировать документ и приступить к редактированию 3) После редактирования - он сохраняет документ и должен снять блокировку 4) Если документ до него заблокирован - то необходимо получить информацию (кто, когда, с какого компа) и сообщить опоздавшему претенденту 5) Если документ заблокирован - то вывести его в режиме чтения Таким образом возникает ряд функций 1) Функция проверки на блокировку документа (зная таблицу и № записи) 2) Функция блокировки документа 3) Функция разблокировки документа 4) Запуск документа в режиме редактирования (+ доступ для этого пользователя) 5) Запуск документа в режиме чтения Но тут требуется 2 параметра: 1) Флаг блокировки FLAG_BLOCK Bit 2) Информация о блокирующем (кто, когда, с какого компа) NAME_BLOCK char(100) Самый простой и неправильный вариант решения - это добавить в таблицу только одно поле NAME_BLOCK - То есть чтобы понять есть ли сейчас блокировка SELECT COUNT(NAME_BLOCK) FROM Table1 WHERE LEN(NAME_BLOCK)>0 and ID=123 - Чтобы понять кто заблокировал SELECT NAME_BLOCK FROM Table1 WHERE ID=123 - Чтобы заблокировать UPDATE Table1 SET NAME_BLOCK='Юзер 1 Время ххххх' WHERE ID=123 - Чтобы снять блокировку UPDATE Table1 SET NAME_BLOCK=SPACE(0) WHERE ID=123 - Чтобы получить список всех заблокированных документов SELECT NAME_BLOCK FROM Table1 WHERE LEN(NAME_BLOCK)>0 Гениально работает! Просто и надежно! ![]() Одна проблема - как только пользователь отключается от базы данных - то такая блокировка остаётся навсегда, так как пользователь думает что он все сделал, а другие думаю что еще работает. Исправлено 1 раз(а). Последнее : shumik73, 17.04.24 22:38 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
shumik73 Сообщений: 554 Откуда: Алматы Дата регистрации: 10.05.2006 |
Так как таблица TABLE1 хранит данные, то она не готова к тому что пользователь может в любой момент отвалиться и не успеть снять блокировку
В SQL Server для этих целей существует динамическое представление sys.dm_tran_locks. Оно возвращает сведения об активных в данный момент в SQL Server ресурсах диспетчера блокировок.
Особенности этой таблицы в том что - она хранит только те блокировки, которые были сделаны пользователем в то время пока он был подключен к базе И пока он еще на связи - таблица действует и сообщает всем другим пользователям что этот 1=ый пользователь успел заблокировать. Стоит ему отключиться от базы - то все его блокировки исчезают. Можно в этом убедиться - если подключиться от разных пользователей и проверять эту таблицу Очень напоминает разницу между CREATE TABLE Table1 () и созданием курсора CREATE CURSOR Table1 () При просмотре можно понять сколько и каких блокировок сейчас действует Но есть маленькое неудобство - все что можно информативно внести: Описание ресурса в поле resource_description nvarchar(256) Как видно это поле и так перегружено данными 0:[Form1] ![]() В этом поле ресурсов - необходимо занести уникальную идентификацию того документа, с которым будут работать пользователи. То есть надо как-то обозначить таблицу и номер записи. В каком это будет формате - тут дело вкуса ![]() Далее вместо этого будет фигурировать - Form1 Ссылки: learn.microsoft.com infostart.ru Исправлено 1 раз(а). Последнее : shumik73, 17.04.24 23:39 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
shumik73 Сообщений: 554 Откуда: Алматы Дата регистрации: 10.05.2006 |
В этой таблице dm_tran_locks будут записываться блокировки. Теперь необходимо реализовать остальные функции: как определить есть ли блокировка на интересующий нас документ
Ссылка: learn.microsoft.com Теперь как решить задачу блокировки документа - точнее как в таблицу блокировок добавить информацию о блокируемом документе после этого можно приступать к редактированию документа
Ссылка learn.microsoft.com После того как внесены изменения и документ сохранен - необходимо убрать блокировку
Ссылка learn.microsoft.com Следует отметить что по умолчанию lock_owner = 'Transaction' и все команды где этот параметр пропущен или указан должны формироваться в следующем виде:
Если выбрать @LockOwner='Session' то проще Что касается контроля за блокировками то в инете можно на найти SQL-запросы которые помогут отследить кто и что блокирует Исправлено 1 раз(а). Последнее : shumik73, 17.04.24 23:46 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
of63 Сообщений: 26041 Откуда: Н.Новгород Дата регистрации: 13.02.2008 |
> Программа многопользовательская и логично возникла задача запретить одновременное редактирование файла несколькими пользователями.
Какие тут могут быть решения? Решение простое - надо (или не надо ?) показать пользователю, что когда он открыл "запись" (за ней стоит много записей в подчиненных таблица, возможно) на желаемый режим "редактирование", то дай ему понять, что эта же "запись" редактируется кем-то другим (красный баннер на экране, всякие сигналы...) если "секретность" не предполагает такой сигнализации (о уже блокировании), то внутренний флаг взведи в программе, что вот такая особая ситуация с записью Под словом "запись" это совсем не транзакция, а может, "семафор" - искусственная конструкция для блокирования чего либо... ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
shumik73 Сообщений: 554 Откуда: Алматы Дата регистрации: 10.05.2006 |
Можно поподробнее развернуть вот это "что-то полезное" ? Пусть 1 пользователь редактирует табличку с ID=100, то есть он блокирует и в ресурсе указывает 'Редактируется файл 100, 20 апреля 10 часов' Пользователь 2 тоже хочет редактировать туже табличку и тоже хочет заблокировать с своим ресурсом 'Редактируется файл 100, 20 апреля 11 часов' И sp_getapplock ему одобрит блокировку того же ID=100, так как имена ресурсов то у них разные. Поэтому в ресурс нужно включить идентификатор, который был бы один для всех и дату включать не надо И с этим согласен. Если пользователь 2 не сможет получить заблокировать (получить доступ) - то конечно он захочет узнать кто его опередил. Следовательно нужно зная имя ресурса - найти (имя, время, компьютер) другого пользователь №1 ? Эту полезную информацию нужно куда-то записать и найти? Допустим все это запишем как ресурс и его можно найти в таблицах и вьюхах (в зависимости от версии MSSQL): Например как выглядет "OBJ=2137;REC=2464" в
Так что записать ресурс легко, да вот найти его и тем более найти его автора прям задача ![]() ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
of63 Сообщений: 26041 Откуда: Н.Новгород Дата регистрации: 13.02.2008 |
Что за проблемма,
Т.е, блокируемое ... значение, выражения, похожее на "индекс" в фокс... () фривольно - чтобы заблокировать доступ к собственной жене, например, то нужно указать какие ее параметры... ) Исправлено 1 раз(а). Последнее : of63, 23.04.24 00:23 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
PaulWist Сообщений: 14761 Дата регистрации: 01.04.2004 |
Репро-код запусти.
вернёт блокировки приложения. Володя Максимов уже "разжевал" возможные варианты. ------------------ Есть многое на свете, друг Горацио... Что и не снилось нашим мудрецам. (В.Шекспир Гамлет) ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
shumik73 Сообщений: 554 Откуда: Алматы Дата регистрации: 10.05.2006 |
Как блокировать и разблокировать - тут проблем нет, так как для этого нужен уникальный ресурс!
1) ну хоть SYS(2007, имя блокирующей программы + ID блокируемой записи) 2) например ID таблички и время начала блокировки Прилржения. select * from sys.dm_tran_locks where resource_type = N'APPLICATION' вернёт блокировки приложения. А точнее список уникальных ресурсов которые в данный момент заблокированы. Вопрос то в том кто из пользователей это сделал? Если включить в ресурс IDuser=123 то ресурс уже не будет уникальным так как блокирующий знает, а пытающийся разблокировать нет и вся система блокировки не имеет смысла Об этом проблеме и речь:
Если не заблокировать доступ к жене - то как найти того кто провел транзакцию? ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
PaulWist Сообщений: 14761 Дата регистрации: 01.04.2004 |
Добавь в Resource имя и ID таблички, положи хоть в xml-формате. Второй знает к какой таблице и ID обращается, дальше написать resource_description like '%Test.id=2%' и распарсить полученную строку, всего делов-то. Или в чём трудность??
------------------ Есть многое на свете, друг Горацио... Что и не снилось нашим мудрецам. (В.Шекспир Гамлет) Исправлено 1 раз(а). Последнее : PaulWist, 23.04.24 11:18 ![]() |
Re: Запрет одновременного редактирования файла | |
---|---|
of63 Сообщений: 26041 Откуда: Н.Новгород Дата регистрации: 13.02.2008 |
() Мтк, обсуждение касается ПРОГРАММНО обустроенного ограничения доступа к какой-то табличке, или ко всей базе (набору табличек). Если доступ осуществляется только через программу, сделанную специально для доступа к этим табличкам, то можно сделать всё как угодно удобно доступно/недоступно, или, если к таблице "лазят" другими способами (например, фоксовые таблички можно открывать фоксовым же IDE, или "DBFread" каким-нибудь... ХЕКС-редактором/смотрителем.), тогда доступ осуществлять надо совсем по-другому, тем более узнавать "кто пытался открыть файл"... ![]() |
© 2000-2025 Fox Club  |