Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Паралеллльный инсерт / 25 сообщений из 50, страница 1 из 2
08.11.2017, 10:16
    #39549377
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Доброго дня уважаемые!

Вот такая ситуация

есть примерная такая табличка

Код: plsql
1.
create table tbl(ID NUMBER, str VARCHAR2(100);



id - Primary key
есть уникальный индекс по str

Есть процесс работающий по такому принципу
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
BEGIN
    BEGIN
        SELECT id
          INTO v
          FROM tbl
         WHERE str = some_value;
    EXCEPTION
        WHEN ndf THEN
            v   := NULL;
    END;
    IF v IS NULL THEN
        INSERT INTO tbl (str)
             VALUES (some_value)
          RETURNING id
               INTO v;
    END IF;
END;


Когда начало работать несколько параллельных процессов появились ошибки дубликатов при инсерте, т.к. между чтением и инсертом другой процесс успевал вставить запись.
Переделал код так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
BEGIN
    BEGIN
        SELECT id
          INTO v
          FROM tbl
         WHERE str = some_value;
    EXCEPTION
        WHEN ndf THEN
            v   := NULL;
    END;
    IF v IS NULL THEN
        BEGIN
            INSERT INTO tbl (str)
                 VALUES (some_value)
              RETURNING id
                   INTO v;
        EXCEPTION
            WHEN DUP_VAL_ON_INDEX THEN
                SELECT id
                  INTO v
                  FROM tbl
                 WHERE str = some_value;
        END;
    END IF;
END;


Но все равно выглядит некрасиво. Если соседний процесс, вставивший запись, откатит транзакцию получим исключение NO_DATA_FOUND.

А есть ли более красивые стандартные решения такой проблемы?
...
Рейтинг: 0 / 0
08.11.2017, 10:23
    #39549386
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Самонаполняющийся справочник следует наполнять в автономке.
...
Рейтинг: 0 / 0
08.11.2017, 10:31
    #39549395
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Elic,

Ну, это не справочник и его в автономку нельзя никак.
...
Рейтинг: 0 / 0
08.11.2017, 10:34
    #39549399
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Migelleнельзя никак.Тебе, конечно же, виднее.
...
Рейтинг: 0 / 0
08.11.2017, 10:37
    #39549401
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
MigelleЕсли соседний процесс, вставивший запись, откатит транзакцию, то зададимся вопросом, что же тебе вернул тогда запрос в обработчике DUP_VAL_ON_INDEX ?
...
Рейтинг: 0 / 0
08.11.2017, 10:54
    #39549416
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Elic,

В данном случае я упростил пример до того, что он стал выглядеть как справочник, но на самом деле это не так.

env,

ID генерится в триггере из сиквенса. После отката это будет несуществующий id
...
Рейтинг: 0 / 0
08.11.2017, 10:55
    #39549417
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
MigelleЕсли соседний процесс, вставивший запись, откатит транзакцию получим исключение NO_DATA_FOUND.

вот ето непонятно

......
stax
...
Рейтинг: 0 / 0
08.11.2017, 10:59
    #39549419
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
MigelleВ данном случае я упростил пример до того, что он стал выглядеть как справочник, но на самом деле это не так.Migelleавтономку нельзя никак.Это называется сериализация в конкуренции за ресурс.
...
Рейтинг: 0 / 0
08.11.2017, 11:24
    #39549442
982183
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Что-то подобное решали путем предварительного заполнения базы пустыми значениями, с генерацией необходимых ID.
Так что текущая работа делалась не инсертом а апдейтом.
...
Рейтинг: 0 / 0
08.11.2017, 11:38
    #39549453
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
StaxMigelleЕсли соседний процесс, вставивший запись, откатит транзакцию получим исключение NO_DATA_FOUND.

вот ето непонятно
stax

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	Процесс 1		Процесс 2	
Время		Результат		Результат
-----------------------------------------------
t1	Select	NO_DATA_FOUND 		
t2				Select	NO_DATA_FOUND 
t3	Insert	Ok		
t4				insert	DUP_VAL_ON_INDEX
t5	Rollback			
t6				Select	NO_DATA_FOUND 

Процесс 2 получает NO_DATA_FOUND

ElicЭто называется сериализация в конкуренции за ресурс.

Хорошо. А есть какие нибудь другие варианты решения?
...
Рейтинг: 0 / 0
08.11.2017, 11:47
    #39549458
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Migelleдругие варианты решения?Приведённый упрощённый пример тебе уже решили.
http://www.bugtraq.ru/forum/faq/general/smart-questions.html] RTFM
...
Рейтинг: 0 / 0
08.11.2017, 11:52
    #39549463
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Migelle,

t4 ждет
DUP_VAL_ON_INDEX не будет
соответственно не будет t6

.....
stax
...
Рейтинг: 0 / 0
08.11.2017, 12:06
    #39549473
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Staxt4 ждет
DUP_VAL_ON_INDEX не будет
соответственно не будет t6
stax
Хм... Точно!
...
Рейтинг: 0 / 0
08.11.2017, 12:20
    #39549485
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
ElicПриведённый упрощённый пример тебе уже решили
Я же сказал, что это не справочник и автономные транзакции не подходят. Это заголовок журнала, который не имеет права существовать без подчиненных записей.

Неужели если бы я добавил в пример десяток-другой полей как-то повлияло бы на логику работы?
...
Рейтинг: 0 / 0
08.11.2017, 12:23
    #39549487
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
MigelleЭто заголовок журнала, который не имеет права существовать без подчиненных записей.Ну и зачем параллельно создавать один и тот-же "заголовок"? Чтобы всем стоять в очереди?
http://www.bugtraq.ru/forum/faq/general/smart-questions.html] RTFM
...
Рейтинг: 0 / 0
08.11.2017, 14:23
    #39549568
Migelle
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
ElicНу и зачем параллельно создавать один и тот-же "заголовок"? Чтобы всем стоять в очереди? Потому что к заголовку параллельно добавляются подчиненные записи множеством процессов. Первый процесс создает заголовок, остальные пользуются им.

Это не справочник и автономная транзакция не подходит.
...
Рейтинг: 0 / 0
08.11.2017, 14:53
    #39549606
Паралеллльный инсерт
Если мастер-запись добавлять после дочерних, в конце основных манипуляций, то время конкуренции за мастера сократится и можно повысить troughput. Вставку мастера, если нет делитов, можно сделать как insert-select-where-not-exists и игнорировать dup_val_on_index.
...
Рейтинг: 0 / 0
08.11.2017, 15:18
    #39549635
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
де ФеррабляЕсли мастер-запись добавлять после дочерних, в конце основных манипуляций, то время конкуренции за мастера сократится и можно повысить troughput. Вставку мастера, если нет делитов, можно сделать как insert-select-where-not-exists и игнорировать dup_val_on_index.
1) шоб делать детей надо знать ид отца
2) insert-select-where-not-exists не поможет, будут дубли да и загадочный RETURNING id под вопросом

.....
stax
...
Рейтинг: 0 / 0
09.11.2017, 14:22
    #39550250
XMLer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
MigelleЭто заголовок журнала, который не имеет права существовать без подчиненных записей.

Ну так вставь фиктивную дочку а после, отдельным процессом, удали, если нужно.
Где вы такое находите....
...
Рейтинг: 0 / 0
09.11.2017, 14:29
    #39550259
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Staxде ФеррабляЕсли мастер-запись добавлять после дочерних, в конце основных манипуляций, то время конкуренции за мастера сократится и можно повысить troughput. Вставку мастера, если нет делитов, можно сделать как insert-select-where-not-exists и игнорировать dup_val_on_index.
1) шоб делать детей надо знать ид отца
Шоб делать детей - отца знать не надо, надо знать на кого записать приплод :)
А это вопрос техники генерации идентификаторов и не более того.
...
Рейтинг: 0 / 0
09.11.2017, 16:07
    #39550355
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
andrey_anonymousШоб делать детей - отца знать не надо, надо знать на кого записать приплод :)
А это вопрос техники генерации идентификаторов и не более того.

сдесь и обсуждается техника генерации идентификаторов и не более того

.....
stax
...
Рейтинг: 0 / 0
09.11.2017, 16:42
    #39550378
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Staxсдесь и обсуждается техника генерации идентификаторов и не более того
Тогда непонятно в чем проблема сгенерироать ID, накидать чилдов а затем финальным аккордом обозначить парента.
Если сомнения касаются FK, то обратите внимание на ник того, кто это предложил - должно стать яснее :)
...
Рейтинг: 0 / 0
09.11.2017, 17:33
    #39550421
d.nemolchev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Migelle,
Если ID в таблице не отрицательны, то можно так решить:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Begin
  Insert Into Tbl
    (Id, Str)
  Values
    (-trunc(Dbms_Random.Value(1, 1e9)), Some_Value)
  Returning Id Into v;
  Update Tbl t Set t.Id = Seq.Nextval Where t.Id = v Returning t.Id Into v;
Exception
  When Dup_Val_On_Index Then
    Null;
End;
/



Ваш триггер, генерирующий ID, должен поддерживать возможность пользовательской вставки ID:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
Create Or Replace Trigger Tbl_Bir_Trg
  Before Insert On Tbl
  For Each Row
  When (New.Id Is Null) /*важно!*/
Begin
  :New.Id := Seq.Nextval;
End;


или на худой случай вот так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
Create Or Replace Trigger Tbl_Bir_Trg
  Before Insert On Tbl
  For Each Row
Begin
  If :New.Id Is Null Then /*важно!*/
    :New.Id := Seq.Nextval;
  End If;



Хотя я, лично я, строго против таких триггеров и настоятельно рекомендую использовать явную генерацию ID в коде приложения. Триггеров при реализации штатного функционала вообще желательно по возможности избегать.
...
Рейтинг: 0 / 0
09.11.2017, 17:43
    #39550433
d.nemolchev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
Небольшие пояснения к предыдущему сообщению:
Insert пытается вставить значение в уникальный индекс.
При этом ID генерируется случайное, вне диапазона рабочих значений.
Диапазон генерируемых значений ID выбран в 1 млрд для уменьшения вероятности блокировок сеансов разных пользователей, одновременно пробующих выполнить вставку значений (разных) в уникальный индекс.
Если вставляемое значение уже есть в таблице, то улетаем в exception DUP_VAL_ON_INDEX.
В противном случае никто более в другой сессии не сможет вставить такое же значение, какое вставили мы - они будут ждать завершения нашей транзакции в силу наличия уникального индекса на таблице.
В случае успешной вставки строки заменяем случайный ID на штатный из последовательности и на этом всё.
...
Рейтинг: 0 / 0
09.11.2017, 17:50
    #39550440
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Паралеллльный инсерт
d.nemolchev,

у Migelle ситуация не с ID, а с str
20935441

....
stax
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Паралеллльный инсерт / 25 сообщений из 50, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]