Модераторы: LSD
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизировать доступ к таблице из нескольких, приложений 
:(
    Опции темы
Royan
Дата 2.2.2009, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 1
Всего: 15



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

Трудность в том, что в один и тот же момент времени два процесса могут прочесть ID (SELECT не синхронизируется транзакциями), а следующим шагом попытаться провести INSERT, в результате чего один из процессов свалится с ORA-00001: unique constraint (XXX) violated Вопрос есть ли возможность в Oracle преодолеть сию проблему? Может как-то грамотно засинхронизировать SELECT?



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Zloxa
Дата 2.2.2009, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(Royan @  2.2.2009,  14:17 Найти цитируемый пост)
Может как-то грамотно засинхронизировать SELECT

Общего рецепта нет. Есть лишь частные.
Сериализовать доступ по чтению можно лишь блокировками. Блокировки оракл устанавливает лишь при операции записи.
Надо придумать чтото чтобы это чтото кудато записывать перед чтением, либо использовать dbms_lock дабы не плодить сущего без надобного.

Из контекста я понял что у тебя что то вроде insert into tab(id) select nvl(max(id),0)+1 from tab;
Рецепт - Lock table tab in exclusive mode перед выполнением этой операции.

Это сообщение отредактировал(а) Zloxa - 2.2.2009, 14:43


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Deniel_li
Дата 2.2.2009, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 6.12.2007

Репутация: нет
Всего: 1



если правильно понял, то проблема в этом 

ORA-00001: unique constraint (XXX) violated

а почему бы вместо чтения Id из таблицы не воспользоваться последовательностями? 

тем более, если по условию с таблицей активно работают.... 

Это сообщение отредактировал(а) Deniel_li - 2.2.2009, 17:08
PM MAIL   Вверх
Royan
  Дата 3.2.2009, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 1
Всего: 15



Поясню проблему. У меня код работает буквально так

Код

SELECT xxx FROM t_foo WHERE id=100;


Далее код на java

if(SELECT чего то нашел, то есть запись существует) {
Код

UPDATE t_foo SET xxx='999' WHERE id=100;
 
} else {
Код

INSERT INTO t_foo (id, xxx) VALUES (100, '999');
 
}

Я так понял этот подход совковый и надо в таких случаях использовать MERGE. Вопрос к знатокам, а MERGE блокирует табличку на время своего выполнения?



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Zloxa
Дата 3.2.2009, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(Royan @  3.2.2009,  12:35 Найти цитируемый пост)
MERGE блокирует табличку на время своего выполнения

По чтению - нет.
Но ситуацию разрулит.

Первому селекту можно добавить for update. Это будет гарантироватЬ, что если запись есть, то она никуда не денется.

Можно заменить конструкцию на:
Код

begin
  INSERT INTO t_foo (id, xxx) VALUES (100, '999');
exception 
  when dup_val_on_index
    then UPDATE t_foo SET xxx='999' WHERE id=100;
end

Но, соответственно, запись может потеряться, если произойдет фиксация удаления между инсертом и аптдейтом


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
DimW
Дата 3.2.2009, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 23
Всего: 44



Цитата(Royan @  3.2.2009,  12:35 Найти цитируемый пост)
а MERGE блокирует табличку на время своего выполнения?

 оракле не предусмотрен механизм блокирования таблицы при модификации данных. блокируется всегда только модифицируемая строка/строки в независимости от их количества.

MERGE всего лишь гарантирует выполнение одним оператором insert-a или update-a.

Цитата(Royan @  2.2.2009,  14:17 Найти цитируемый пост)
одновременно читают и пишут несколько приложений

не забываем что даный механизм должен быть реализован для всех приложений ибо от ORA-00001 не отвертеться. 

PM MAIL ICQ   Вверх
DimW
Дата 4.2.2009, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 23
Всего: 44



Цитата(Zloxa @  3.2.2009,  13:08 Найти цитируемый пост)
Можно заменить конструкцию на:


так же можно воспользоваться sql%rowcount:

Код

begin
  UPDATE t_foo SET xxx='999' WHERE id=100;
  if sql%rowcount = 0 then
    INSERT INTO t_foo (id, xxx) VALUES (100, '999');
  end if;
end;



PM MAIL ICQ   Вверх
Zloxa
Дата 4.2.2009, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(DimW @  4.2.2009,  10:50 Найти цитируемый пост)
так же можно воспользоваться sql%rowcount:

При интенсивном удалении из той же таблицы, при таком подходе шанс поймать ora-00001 лишь слегка минимизируется.
В предложенном мной варианте, мы имеем некислый шанс потерять апдейт.

Я так понял проблема как раз таки вызвана тем, что присутствует еще и удаляющая сессия, назначение и принцип работы которой не раскрыты автором.



--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
DimW
Дата 4.2.2009, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 23
Всего: 44



Цитата(DimW @  4.2.2009,  10:50 Найти цитируемый пост)
так же можно воспользоваться sql%rowcount:

извиняюсь нельзя - при многопользовательском доступе не имеет смысла.
PM MAIL ICQ   Вверх
Zloxa
Дата 4.2.2009, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



ЗЫ Сорри вообще гоню.
Не понял я откуда у меня взялось убеждение, что есть еще и удаляющая сессия.


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
DimW
Дата 4.2.2009, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 23
Всего: 44



Цитата(Zloxa @  4.2.2009,  10:57 Найти цитируемый пост)
Я так понял проблема как раз таки вызвана тем, что присутствует еще и удаляющая сессия,


Zloxa,  что то мне кажется механизм где присутствуем еще и удаление несколько надуман, сложно представить жизненную ситуацию когда это рельно бы использовалось (имеется ввиду в контексте последовательного доступа к записи).
если задача именно такая, то dbms_lock по id в помошь.

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Oracle"
Zloxa
LSD

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

  • при создании темы давайте ей осмысленное название, описывающее суть проблемы
  • указывайте используемую версию базы, способ соединения и язык программирования
  • при ошибках обязательно приводите код ошибки и сообщение сервера
  • приводите код в котором возникла ошибка, по возможности дайте тестовый пример демонстрирующий ошибку
  • при вставке кода используйте соответсвующие теги: [code=sql] [/code] для подсветки SQL и PL/SQL кода, [code=java] [/code] - для Java, и т.д.

  • документация по Oracle: 9i, 10g, 11g
  • книги по Oracle можно поискать здесь
  • действия модераторов можно обсудить здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, LSD.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Oracle | Следующая тема »


 




[ Время генерации скрипта: 0.0840 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.