Название: [Решено] Совет от опытных программистов БД. Отправлено: Exproment от Январь 12, 2012, 15:25 Имеется БД Oracle необходимо реализовать общий доступ с нескольких приложений с возможностью редактирования записей для каждого. При этом нельзя использовать технологию Мьютексов, т.е. нельзя блокировать данные, т.к. один пользователь может их зарезервировать на долгое время.
Например: два юзера одновременно редактируют запись, после чего нажимают сохранить - и тот кто получил права первый - сохранит, а второму должно выводится сообщение мол запись была редактирована. Как лучше организовать такую работу? имеется несколько идей, но мало опыта в программировании баз данных, потому могу не понимать некоторые концепции. Очень нужен совет именно по правильной организации. Заранее благодарен. Естественно задача должна быть выполнима средствами Qt))) Название: Re: Совет от опытных программистов БД. Отправлено: Пантер от Январь 12, 2012, 15:30 А на стороне самой БД нет такой возможности?
Название: Re: Совет от опытных программистов БД. Отправлено: Exproment от Январь 12, 2012, 15:38 Честно - понятия не имею.. именно с Oracle работаю вообще в первые... вот сейчас литературу сижу читаю по ней)
Название: Re: Совет от опытных программистов БД. Отправлено: Пантер от Январь 12, 2012, 15:48 Я давно уже с БД не работал, но вот решение в лоб:
1. В начале редактирования загружаем данные. 2. При сохранении сначала загружаем данные и сравниваем с сохраненными. 3. Если они равны, сохраняем. Если не равны, выдаем ошибку. Но тут косяк может быть такой, что между п.2 и п.3 кто-то может сохранить данные. Название: Re: Совет от опытных программистов БД. Отправлено: Bepec от Январь 12, 2012, 15:54 QReadWriteLock обеспечивает блокировку, разрешающую совместный доступ для чтения.
http://doc.crossplatform.ru/qt/4.4.3/qreadwritelock.html Помоему, как я понял проблему, вот вам и решение. Блокировка только на запись ставится в момент записи данных. При этом данные в этот же момент можно будет читать. Название: Re: Совет от опытных программистов БД. Отправлено: Пантер от Январь 12, 2012, 15:59 QReadWriteLock обеспечивает блокировку, разрешающую совместный доступ для чтения. Это не то совершенно.http://doc.crossplatform.ru/qt/4.4.3/qreadwritelock.html Помоему, как я понял проблему, вот вам и решение. Блокировка только на запись ставится в момент записи данных. При этом данные в этот же момент можно будет читать. Название: Re: Совет от опытных программистов БД. Отправлено: QuAzI от Январь 12, 2012, 16:00 И получить любимый косяк 1С v7.7 - залочку базы каким-то одним перцем, в то время как кто-то другой из полусотни активных юзверей пытается внести аналогичную запись.
Не знаю, как в Оракле, а толи в PG, толи в MySQL можно было сделать INSERT и при ошибке проверки записи на уникальность (тобишь нужен ключ гарантирующий что запись уникальна) создавать новую запись. Одной транзакцией. Что как бы гарантирует ;) . Жаль синтаксис не помню. Странно будет, если "ынтырпрайзная" СУБД такого не умеет. А вот оно и гуглится быстро даже http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html И можно ещё погуглить INSERT IF NOT EXISTS , возможно найдёте там ключ к решению задачи А вот даже по MySQL insert on update ссылочкам на сравнении с ораклей вывалило http://psoug.org/reference/merge.html Код: MERGE <hint> INTO <table_name> Название: Re: Совет от опытных программистов БД. Отправлено: Exproment от Январь 12, 2012, 16:37 Всем спасибо огромное, каждый вариант подробно изучу... Сделаю - обязательно отпишусь каким способом, в пока если появятся еще какие идеи - буду благодарен)
Название: Re: Совет от опытных программистов БД. Отправлено: asvil от Январь 12, 2012, 17:44 Иногда меня мучает вопрос: что дешевле, научить-таки пользователей сиквелу, или тратить тонны денег на тонны графических оболочек.
Вот раз у вас деньги на оракл нашлись, что нету денег теперь на какой-нибудь оракл формс, в котором все из коробки работает? Да по теме, в постгри сиквеле есть конструкция select ... for insert, update. Поищите возможно оракл реализует расширенный сиквел для блокировки на уровне строк, таблиц. Название: Re: Совет от опытных программистов БД. Отправлено: andrew.k от Январь 12, 2012, 21:42 Разве это не есть механизм транзакций, который должна сама СУБД поддерживать?
Название: Re: Совет от опытных программистов БД. Отправлено: MoPDoBoPoT от Январь 12, 2012, 21:52 Конкретно такое поведение можно сделать с помощью "временных меток". Добавляем столбец "временная метка", где будет храниться время последнего обновления данных для данной записи. При начитывании данных для обновления запоминаем эту самую метку, а перед непосредственным обновлением данных проверяем текущее значение временной метки: запрашиваем данные и лочим запись одновременно через SELECT FOR UPDATE (для синхронизации). Соответственно, если запрошенная временная метка "свежее" запомненной, то не обновляем данные. Стоит также отметить, что лочить и обновлять запись надо в одной транзакции, иначе от лока не будет толку. Также проверку метки можно в виде хранимой функции сделать с параметрами: сущность/таблица, метка.
НО, по-моему, такое поведение не логично, когда пользователь провёл некоторую работу по изменению данных, а при сохранении получить от ворот поворот. Лучше для обновления лочить запись через SELECT FOR UPDATE NOWAIT. Параметр NOWAIT заставляет не ждать до тех пор, пока блокировка не снимется (вылет по ORA-00054). При вылете говорим пользователю, что запись нельзя редактировать, т.к. она уже в обработке. Название: Re: Совет от опытных программистов БД. Отправлено: trot от Январь 13, 2012, 08:40 В СУБД postgres есть команда LOCK TABLE, которая предназначена для организации монопольного использования таблицы.
Может быть, что-то есть подобное в ORACLE. Но это не решит вашу проблему. Этот вопрос актуален только для одной операцией - UPDATE, остальные операции решаются самой СУБД, например когда два пользователя одновременно удаляют одну запись, что при этом будет, я думаю не трудно догадаться. Для UPDATE вам надо организовать обратную связь, например, клиент отсылает на сервер сообщение, что началась операция редактирования такой-то записи, а сервер в свою очередь рассылает сообщения клиентам (необходимым), что такой-то пользователь начал операцию редактирования такой-то записи, ну а далее относительно этого строится логика приложения. Задача я бы сказал не из простых, варианты её решения накладывают отпечаток на всю архитектуру вашего приложения. Название: Re: Совет от опытных программистов БД. Отправлено: Akon от Январь 13, 2012, 15:27 Блокировки бывают двух типов: пессимистичные и оптимистичные.
Цитировать Например: два юзера одновременно редактируют запись, после чего нажимают сохранить - и тот кто получил права первый - сохранит, а второму должно выводится сообщение мол запись была редактирована. Это и есть суть оптимистичной блокировки. Оптимизм в надежде на то, что запись параллельно данные никто не изменяет.Название: Re: Совет от опытных программистов БД. Отправлено: Exproment от Январь 22, 2012, 19:42 Ах да кстати... ) Тема решена следующим образом: в Oracle можно навесить на таблицу или на каждую строку SCN(System Change Number) - код-время последнего изменения, еоторым управляет БД.
1) при создании таблицы Включаем его поддержку для каждой строки (ключ ROWDEPENDENCIES в CREATE TABLE) - в результате чего для каждой строки появится дополнительное поле ORA_ROWSCN, величиною в 6 байт. 2) При каждом изменении не забываем делать COMMIT(чтобы обновлялся журнал изменений и SCN менялся) 3) Затем отредактировав запись и выполняя UPDATE используем следующую структуру: Код
и если не одна строка не была обработана, запись была изменена. |