Russian Qt Forum
Ноябрь 22, 2024, 16:54 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Решено] Совет от опытных программистов БД.  (Прочитано 10819 раз)
Exproment
Гость
« : Январь 12, 2012, 15:25 »

Имеется БД Oracle необходимо реализовать общий доступ с нескольких приложений с возможностью редактирования записей для каждого. При этом нельзя использовать технологию Мьютексов, т.е. нельзя блокировать данные, т.к. один пользователь может их зарезервировать на долгое время.

Например: два юзера одновременно редактируют запись, после чего нажимают сохранить - и тот кто получил права первый - сохранит, а второму должно выводится сообщение мол запись была редактирована.

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

Естественно задача должна быть выполнима средствами Qt)))
« Последнее редактирование: Январь 22, 2012, 19:43 от Exproment » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Январь 12, 2012, 15:30 »

А на стороне самой БД нет такой возможности?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Exproment
Гость
« Ответ #2 : Январь 12, 2012, 15:38 »

Честно - понятия не имею.. именно с Oracle работаю вообще в первые... вот сейчас литературу сижу читаю по ней)
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Январь 12, 2012, 15:48 »

Я давно уже с БД не работал, но вот решение в лоб:
1. В начале редактирования загружаем данные.
2. При сохранении сначала загружаем данные и сравниваем с сохраненными.
3. Если они равны, сохраняем. Если не равны, выдаем ошибку.

Но тут косяк может быть такой, что между п.2 и п.3 кто-то может сохранить данные.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Bepec
Гость
« Ответ #4 : Январь 12, 2012, 15:54 »

QReadWriteLock обеспечивает блокировку, разрешающую совместный доступ для чтения.
http://doc.crossplatform.ru/qt/4.4.3/qreadwritelock.html

Помоему, как я понял проблему, вот вам и решение. Блокировка только на запись ставится в момент записи данных. При этом данные в этот же момент можно будет читать.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Январь 12, 2012, 15:59 »

QReadWriteLock обеспечивает блокировку, разрешающую совместный доступ для чтения.
http://doc.crossplatform.ru/qt/4.4.3/qreadwritelock.html

Помоему, как я понял проблему, вот вам и решение. Блокировка только на запись ставится в момент записи данных. При этом данные в этот же момент можно будет читать.
Это не то совершенно.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
QuAzI
Гость
« Ответ #6 : Январь 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>
USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
DELETE <where_clause>
WHEN NOT MATCHED THEN <insert_clause>
[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];
Я так думаю это подойдёт
« Последнее редактирование: Январь 12, 2012, 16:07 от QuAzI » Записан
Exproment
Гость
« Ответ #7 : Январь 12, 2012, 16:37 »

Всем спасибо огромное, каждый вариант подробно изучу... Сделаю - обязательно отпишусь каким способом, в пока если появятся еще какие идеи - буду благодарен)
Записан
asvil
Гость
« Ответ #8 : Январь 12, 2012, 17:44 »

Иногда меня мучает вопрос: что дешевле, научить-таки пользователей сиквелу, или тратить тонны денег на тонны графических оболочек.
Вот раз у вас деньги на оракл нашлись, что нету денег теперь на какой-нибудь оракл формс, в котором все из коробки работает?
Да по теме, в постгри сиквеле есть конструкция select ... for insert, update. Поищите возможно оракл реализует расширенный сиквел для блокировки на уровне строк, таблиц.
Записан
andrew.k
Гость
« Ответ #9 : Январь 12, 2012, 21:42 »

Разве это не есть механизм транзакций, который должна сама СУБД поддерживать?
Записан
MoPDoBoPoT
Гость
« Ответ #10 : Январь 12, 2012, 21:52 »

Конкретно такое поведение можно сделать с помощью "временных меток". Добавляем столбец "временная метка", где будет храниться время последнего обновления данных для данной записи. При начитывании данных для обновления запоминаем эту самую метку, а перед непосредственным обновлением данных проверяем текущее значение временной метки: запрашиваем данные и лочим запись одновременно через SELECT FOR UPDATE (для синхронизации). Соответственно, если запрошенная временная метка "свежее" запомненной, то не обновляем данные. Стоит также отметить, что лочить и обновлять запись надо в одной транзакции, иначе от лока не будет толку. Также проверку метки можно в виде хранимой функции сделать с параметрами: сущность/таблица, метка.

НО, по-моему, такое поведение не логично, когда пользователь провёл некоторую работу по изменению данных, а при сохранении получить от ворот поворот. Лучше для обновления лочить запись через SELECT FOR UPDATE NOWAIT. Параметр NOWAIT заставляет не ждать до тех пор, пока блокировка не снимется (вылет по ORA-00054). При вылете говорим пользователю, что запись нельзя редактировать, т.к. она уже в обработке.
Записан
trot
Гость
« Ответ #11 : Январь 13, 2012, 08:40 »

В СУБД postgres есть команда LOCK TABLE, которая предназначена для организации монопольного использования таблицы.
Может быть, что-то есть подобное в ORACLE. Но это не решит вашу проблему.  Этот вопрос актуален только для одной операцией - UPDATE, остальные операции решаются самой СУБД, например когда два пользователя одновременно удаляют одну запись, что при этом будет, я думаю не трудно догадаться. Для UPDATE вам надо организовать обратную связь, например, клиент отсылает на сервер сообщение, что началась операция редактирования такой-то записи, а сервер в свою очередь рассылает сообщения клиентам (необходимым), что такой-то пользователь начал операцию редактирования такой-то записи, ну а далее относительно этого строится логика приложения. Задача я бы сказал не из простых, варианты её решения накладывают отпечаток на всю архитектуру вашего приложения.
Записан
Akon
Гость
« Ответ #12 : Январь 13, 2012, 15:27 »

Блокировки бывают двух типов: пессимистичные и оптимистичные.
Цитировать
Например: два юзера одновременно редактируют запись, после чего нажимают сохранить - и тот кто получил права первый - сохранит, а второму должно выводится сообщение мол запись была редактирована.
Это и есть суть оптимистичной блокировки. Оптимизм в надежде на то, что запись параллельно данные никто не изменяет.
Записан
Exproment
Гость
« Ответ #13 : Январь 22, 2012, 19:42 »

Ах да кстати... ) Тема решена следующим образом: в Oracle можно навесить на таблицу или на каждую строку SCN(System Change Number) - код-время последнего изменения, еоторым управляет БД.

1) при создании таблицы Включаем его поддержку для каждой строки (ключ ROWDEPENDENCIES в CREATE TABLE) - в результате чего для каждой строки появится дополнительное поле ORA_ROWSCN, величиною в 6 байт.

2) При каждом изменении не забываем делать COMMIT(чтобы обновлялся журнал изменений и SCN менялся)

3) Затем отредактировав запись и выполняя UPDATE используем следующую структуру:

Код
SQL
UPDATE message_db
SET
...
...
WHERE mes_id = “Активное значение” AND ORA_ROWSCN = curOra


и если не одна строка не была обработана, запись была изменена.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.062 секунд. Запросов: 23.