Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Одновременный вызов ХП с insert в одну таблицу / 14 сообщений из 14, страница 1 из 1
16.09.2010, 11:08
    #36849636
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
Доброго времени суток!

Есть следующая процедура:
Код: plaintext
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.
26.
CREATE PROCEDURE SCM.UPD_DATA(
    IN IN_T_ID INTEGER
    , IN IN_DATA XML
    )
DYNAMIC RESULT SETS  1 
------------------------------------------------------------------------
P1: BEGIN

	IF EXISTS(
		SELECT T_ID
		FROM TP
		WHERE T_ID = IN_T_ID
	) THEN
	    UPDATE TP
	    SET DATA = IN_DATA
		WHERE ID = IN_T_ID;
	ELSE 
		INSERT INTO TP (
		        T_ID
		        , DATA
		    ) VALUES (
		        IN_T_ID
		        , IN_DATA
		    );--
	END IF;	--
END P1;
Как мне можно устранить возможный конфликт при записи,
при одновременном вызове этой процедуры несколькими пользователями?

Таблица определяется как:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE "SCM"."TP"  (
		  "TP_ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (  
		    START WITH + 1   
		    INCREMENT BY + 1   
		    MINVALUE + 1   
		    MAXVALUE + 9223372036854775807   
		    NO CYCLE  
		    CACHE  20   
		    NO ORDER ) , 
		  "T_ID" INTEGER NOT NULL , 
		  "DATA" XML )   
		 IN "USERSPACE1" ; 

Заранее благодарен за помощь!
...
Рейтинг: 0 / 0
16.09.2010, 11:33
    #36849710
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
а зачем делать именно так?
Не проще ли пытаться сразу обновить запись, а если не получилось - то вставлять, а если не получилось - кидать эксепшн?
...
Рейтинг: 0 / 0
16.09.2010, 11:56
    #36849786
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
gardenmanа зачем делать именно так?
Не проще ли пытаться сразу обновить запись, а если не получилось - то вставлять, а если не получилось - кидать эксепшн?
Мне казалось, что так правильнее.
Можно поподробнее.
Но все таки вопрос в другом, как разграничить одновременный доступ к таблце при инсерте.
У меня вылетает "дупликейт кей эксепшн" - и я стал грешить на эту процедуру.
...
Рейтинг: 0 / 0
16.09.2010, 12:42
    #36849956
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
indicatrix,

В DDL, который вы привели нет ничего о ключах (PK,UK), приведите их пожалуйста.
Что-то мне подсказывает, что T_ID у вас уникальное. Это обязательно нужно делать?
А зачем тогда IDENTITY?
В хранимой процедуре можно обработать эксепшн, и посмотреть какой именно уникальный индекс или PK/UK нарушается.
типа так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
create procedure scm.test (
    in  in_id int,
    in  in_data varchar( 10 ),
    out o_msg varchar( 512 )
) 
begin
    declare sqlcode int default  0 ;
    declare exit handler for sqlexception
    begin
        get diagnostics exception  1  o_msg=message_text;
        set o_msg=('IN_ID='||char(in_id)||','||o_msg);
    end;
    . . .
@

call scm.test( 1 ,'XXX', ?)
@

В любом случае по TP_ID не может быть нарушения уникальности так как это identity.

Можно попробовать пойти другим путем: Попытаться вставить запись, если вставка не удалась, то пробовать изменить. Так будет ИМХО логичнее.
...
Рейтинг: 0 / 0
16.09.2010, 14:02
    #36850199
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
gardenmanindicatrix,

В DDL, который вы привели нет ничего о ключах (PK,UK), приведите их пожалуйста.
Что-то мне подсказывает, что T_ID у вас уникальное. Это обязательно нужно делать?
А зачем тогда IDENTITY?

T_ID внешний ключ, он неуникален, может повторяться.

DDL индексов ниже
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
ALTER TABLE TP 
	ADD CONSTRAINT P_P_TP_ID PRIMARY KEY
		("P_TP_ID");

ALTER TABLE TP 
	ADD CONSTRAINT "F_Reference_33" FOREIGN KEY
		("T_ID")
	REFERENCES STP
		("T_ID")
	ON DELETE RESTRICT
	ON UPDATE RESTRICT
	ENFORCED
	ENABLE QUERY OPTIMIZATION;

gardenman
В любом случае по TP_ID не может быть нарушения уникальности так как это identity.

Можно попробовать пойти другим путем: Попытаться вставить запись, если вставка не удалась, то пробовать изменить. Так будет ИМХО логичнее.
Сейчас сделали тест с одновременным вызовом процедуры, посыпались эксепшены.
SystemErr R com.ibm.websphere.ce.cm.DuplicateKeyException: 3;SCM.PT
Дупликейт кей эксепшн не может же сыпаться на форенкеи...
...
Рейтинг: 0 / 0
16.09.2010, 14:07
    #36850212
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
Господа, посоветуйте плз!

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

Как мне починить этот код?
...
Рейтинг: 0 / 0
16.09.2010, 14:42
    #36850325
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
Т.е. вы хотите сказать, что DB2 генерирует неуникальные IDENTITY значения?
Посмотрите внимательно на свою таблицу, может быть какой-нибудь кодер с кривыми руками все же создал там какой-нить индекс.

И, кстати, когда я компилил ВАШ пример,
то в хранимке у вас есть выражение ID= IN_T_ID,
но между прочим в определении таблицы, приведенной вами - нет такого поля.
Сможете это объяснить?
...
Рейтинг: 0 / 0
16.09.2010, 14:43
    #36850329
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
возможно у вас несколько таблиц TP в разных схемах. Посмотрите внимательнее.
...
Рейтинг: 0 / 0
16.09.2010, 15:21
    #36850478
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
gardenman
И, кстати, когда я компилил ВАШ пример,
то в хранимке у вас есть выражение ID= IN_T_ID,
но между прочим в определении таблицы, приведенной вами - нет такого поля.
Сможете это объяснить?
Просто я изменил названия таблиц и полей, чтобы убрать громозкость.
Там нужно написать WHERE T_ID = IN_T_ID;
Хотя может я зря изменил названия.

gardenmanТ.е. вы хотите сказать, что DB2 генерирует неуникальные IDENTITY значения?
Посмотрите внимательно на свою таблицу, может быть какой-нибудь кодер с кривыми руками все же создал там какой-нить индекс.

Похоже на то.

Я сделал следующие вещи:
Код: plaintext
1.
2.
3.
select COLCARD, HIGH2KEY, LOW2KEY, AVGCOLLEN, NUMNULLS 
from SYSSTAT.COLUMNS 
WHERE TABNAME ='TP' AND COLNAME = 'TP_ID' AND TABSCHEMA='SCM';
Результат выдал:
Код: plaintext
1.
2.
COLCARD     HIGH2KEY      LOW2KEY     AVGCOLLEN      NUMULLS
 2710         3918          21             8                 0 

Далее я запустил:
Код: plaintext
1.
select max(TP_ID) from SCM.TP

который выдал мне значение 3919.

Т.е. Db2 будет выдавать существующий ID.
И поэтому сыпет исключения.
...
Рейтинг: 0 / 0
16.09.2010, 15:41
    #36850549
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
дальше я в скрипте попытался добавить запись в таблицу:
Код: plaintext
1.
2.
insert into TP(T_ID, data)
values( 1184 ,'<root xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events"></root>')
Результат:
Код: plaintext
1.
com.ibm.db2.jcc.b.lm: Одно или несколько значений в операторе INSERT, в операторе UPDATE или при обновлении внешнего ключа, вызванном оператором DELETE, недопустимы, поскольку первичный ключ, ограничение уникальности или индекс уникальности "3" запрещают повторение значений для этого ключа индекса в таблице "SCM.TP".. SQLCODE=- 803 , SQLSTATE= 23505 , DRIVER= 3 . 50 . 152 

Для проверки я запустил:
Код: plaintext
1.
2.
3.
4.
5.
SELECT INDNAME
  FROM SYSCAT.INDEXES
  WHERE IID =  3 
  AND TABSCHEMA = 'SCM'
  AND TABNAME = 'TP'
выдает P_P_TP_ID.

Т.е. он точно грешить на айдентити колонку.
Которая начинает "париться" после одновременного инсерта в таблицу при вызове ХП.
...
Рейтинг: 0 / 0
16.09.2010, 18:38
    #36851086
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
Код: plaintext
1.
2.
3.
select COLCARD, HIGH2KEY, LOW2KEY, AVGCOLLEN, NUMNULLS 
from SYSSTAT.COLUMNS 
WHERE TABNAME ='TP' AND COLNAME = 'TP_ID' AND TABSCHEMA='SCM';

Не пойму при чем тут статистика из таблицы?
При создании идентити колонки создается неявный SEQUENCE и изнчения берутся из него.
смотрите в SYSCAT.SEQUENCES
Я за свою жизнь ни разу не видел чтобы идентити дублировалось.
...
Рейтинг: 0 / 0
16.09.2010, 18:41
    #36851088
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
В других ветках я нашел вот такое полезное выражение, выдающее следующее значение для айдентити колонки
Код: plaintext
1.
2.
3.
4.
5.
6.
select s.LASTASSIGNEDVAL
from sysibm.syscolumns as c, sysibm.sysdependencies as d, sysibm.syssequences as s  
where c.tbcreator = d.dschema and c.tbname = d.dname 
and d.bname = s.seqname and d.bschema = s.seqschema 
and c.identity = 'Y' and d.dtype = 'T' and d.btype =  'Q' and s.seqtype = 'I' 
and C.name='TP_ID' and C.tbname='TP'

Его результат выдал значение 40!!!!!!!!
Теперь однозначно понятно где проблема.
Только я пока не знаю, что к ней приводит и как это дело поймать :(
Может если я буду использовать SEQUENCE у меня будет меньше проблем?
...
Рейтинг: 0 / 0
16.09.2010, 18:50
    #36851101
indicatrix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
gardenman
Не пойму при чем тут статистика из таблицы?


Да, те запросы ни при чем.
Я просто не знал как узнать следующее генерируемое значение.

gardenman
При создании идентити колонки создается неявный SEQUENCE и изнчения берутся из него.
смотрите в SYSCAT.SEQUENCES
Я за свою жизнь ни разу не видел чтобы идентити дублировалось.

У меня получается что это происходит.
Может дело в том, как эти данные были туда загружены.
Они были загружены с помощью процедуры db2move, описанной вот тут.

Но после этого я двигал индексы с помощью
Код: plaintext
1.
ALTER TABLE SCM.TP ALTER COLUMN TP_ID RESTART WITH  4000 ;
Эта проблема возникает периодически.
Мне приходится периодически двигать этот индекс.
Запись идет в эту таблицу только описанной выше процедурой.
...
Рейтинг: 0 / 0
16.09.2010, 19:02
    #36851120
gardenman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одновременный вызов ХП с insert в одну таблицу
авторЯ просто не знал как узнать следующее генерируемое значение.
Только дернув сиквенс. Для идентити можно сделать select from insert с последующим удалением строки. Это можно сделать одним запросом. Но естественно значение пропадет.
...
Рейтинг: 0 / 0
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Одновременный вызов ХП с insert в одну таблицу / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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