powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Add constraint foreign key блокирует таблицу?
13 сообщений из 13, страница 1 из 1
Add constraint foreign key блокирует таблицу?
    #39267653
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте. Есть 2 таблицы.

Код: 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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
-- 1 (справочник)
CREATE TABLE СХЕМА.ZZZ 
(
  ID    NUMBER(21)         NOT NULL,
  NAME  VARCHAR2(10 CHAR)  NOT NULL
);
CREATE UNIQUE INDEX СХЕМА.ZZZ_PK ON СХЕМА.ZZZ (ID);
ALTER TABLE СХЕМА.ZZZ ADD (CONSTRAINT ZZZ_PK PRIMARY KEY (ID) USING INDEX СХЕМА.ZZZ_PK);

-- 2 (партиционирована)
CREATE TABLE СХЕМА.YYY 
(
  ID               NUMBER(21)           NOT NULL,
  NAME             VARCHAR2(256 CHAR),
  DATE_CREATE      TIMESTAMP(6),
  ZZZ_ID           NUMBER(21) -- должен быть fk на СХЕМА.ZZZ
)
PARTITION BY RANGE (ID)
INTERVAL( 10000)
(  
  PARTITION P1 VALUES LESS THAN (10000),
  PARTITION VALUES LESS THAN (20000),
  и т.д.
)
ENABLE ROW MOVEMENT;

CREATE UNIQUE INDEX СХЕМА.YYY_PK ON СХЕМА.YYY (ID);
ALTER TABLE СХЕМА.YYY ADD (CONSTRAINT СХЕМА.YYY_PK PRIMARY KEY (ID) USING INDEX СХЕМА.YYY_PK);


-- создаю индекс
CREATE INDEX СХЕМА.YYY__ZZZ_ID ON СХЕМА.YYY (ZZZ_ID) LOCAL;

-- запускаю создание fk-констрейнта
ALTER TABLE СХЕМА.YYY ADD CONSTRAINT YYY__ZZZ_ID FOREIGN KEY (ZZZ_ID) REFERENCES СХЕМА.ZZZ (ID);


И сразу же начинаю инсертить в СХЕМА.ZZZ (причем id указываю существующий, т.е. должен получить ошибку).
Так вот ошибка вылазит только после того, как закончится создание fk-констрейнта.
Получается, создание fk-констрейнта на СХЕМА.YYY блокирует любой dml в нее?
Единственный обход - NOVALIDATE?


Код: plsql
1.
2.
3.
4.
5.
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE	11.2.0.2.0	Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39267657
Ярослав Батозский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
140907,

Думаю, если "вылазит ошибка", то надо привести текст этой самой ошибки.


И сразу же начинаю инсертить
непонятно, инсертить начинаешь до того как скрипт ДДЛ проиграет полностью ? В другой сессии ?
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39267691
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ярослав Батозский,

Ошибка про то, что строка с таким id уже существует. Делаю так специально.

Создание fk-констрейнта запускаю в первой сессии.
Инсерт делаю во второй сессии во время создания fk-констрейнта.
Инсерт висит, а как только создание fk-констрейнта завершается - выдает ожидаемую ошибку.

Получается, если таблица СХЕМА.YYY большая, и в нее постоянно идут инсерты-апдейты, то единственный способ не нарушить нормальный ход вещей - использовать слово NOVALIDATE при создании fk-констрейнта?

В таблицу СХЕМА.YYY инсерты-апдейты идут почти круглосуточно. Перерыв есть - полчаса.
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39267702
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В 11.2 (точнее с 11.1.0.6 ?) в очередной раз изменилось поведение блокировок для констрейнта FOREIGN KEY
Теперь на время создания (проверки валидности) вешается (пытается, по крайней мере) SHARE (S) TM блокировка на родительскую и дочернюю таблицу, что запрещает
изменение родительской и дочерней таблицы

нельзя построить констрейтн, пока по родительской или дочерней таблице есть незавершенная транзакция (в том числе и непрямая странная блокировка проскочила )

Хоть и заведен "Bug 8881121 : CHANGE TO DML LOCK MODES FOR FOREIGN KEY CONSTRAINTS", но теперь это считается expected behavior
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268327
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудров,

Спасибо.
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268424
Ярослав Батозский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

респект
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268688
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудров,

https://docs.oracle.com/cloud/latest/db112/SQLRF/clauses002.htm#SQLRF52180
ENABLE NOVALIDATE ensures that all new DML operations on the constrained data comply with the constraint. This clause does not ensure that existing data in the table complies with the constraint.
...
If you change the state of any single constraint from ENABLE NOVALIDATE to ENABLE VALIDATE, then the operation can be performed in parallel, and does not block reads, writes, or other DDL operations .


Т.е. сначала я создаю на колонке YYY.ZZZ_ID констрейнт с ENABLE NOVALIDATE (создание констрейнта происходит быстро и не блокирует dml в YYY).
Потом перевожу этот констрейнт в состояние ENABLE VALIDATE (проверка выполняется, но не блокирует dml в YYY).
Вроде так. Надо попробовать.
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268738
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
140907Потом перевожу этот констрейнт в состояние ENABLE VALIDATE (проверка выполняется, но не блокирует dml в YYY)Блокирует
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268805
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудров,

Возможно, блокирует. Но dml идет.

Код: 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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
-- сессия 1
prompt add constraint (enable novalidate)
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
alter table СХЕМА.YYY add constraint YYY__ZZZ_ID foreign key (zzz_id) references СХЕМА.ZZZ (id) enable novalidate;
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

prompt modify constraint (enable validate)
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
alter table СХЕМА.YYY modify constraint YYY__ZZZ_ID enable validate;
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

-- лог 1
add constraint (enable novalidate)
06-07-2016 13:27:54
Table altered.
06-07-2016 13:27:54

modify constraint (enable validate)
06-07-2016 13:27:54
Table altered.
06-07-2016 13:28:29


-- сессия 2
prompt insert into СХЕМА.YYY
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
begin
    for i in 8000001 .. 8200000 loop
        insert into СХЕМА.YYY (id, name, sys_date_create, zzz_id) 
        values (i, 't_'||i, sysdate, (select trunc(dbms_random.value(1, 1000000)) from dual));
        commit;
        sleep(1/1000);
    end loop;
end;
/
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

-- лог 2
insert into СХЕМА.YYY
06-07-2016 13:27:57
PL/SQL procedure successfully completed.
06-07-2016 13:28:27
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39268914
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм
А вот здесь, кстати, интересный момент
Действительно, при VALIDATE оно не держит блокировку постоянно, а пытается получить ее перед валидацией и непосредственно после окончания
Если ты в этом промежутке вставил и закоммитил записи -- все пролазит
Если не подтвердил -- валидация обломится
Т.е. поведение как в 10-ке
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39269617
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудров,

Похоже, в этом промежутке можно вставлять и не коммитить.

Код: 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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
-- Сессия 1
prompt add constraint (enable novalidate)
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
alter table СХЕМА.YYY add constraint YYY__ZZZ_ID foreign key (zzz_id) references СХЕМА.ZZZ (id) enable novalidate;
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

prompt modify constraint (enable validate)
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
alter table СХЕМА.YYY modify constraint YYY__ZZZ_ID enable validate;
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

-- Лог 1
add constraint (enable novalidate)
07-07-2016 12:13:23
Table altered.
07-07-2016 12:13:23

modify constraint (enable validate)
07-07-2016 12:13:23
Table altered.
07-07-2016 12:13:39


-- Сессия 2
prompt insert into СХЕМА.YYY (without commit)
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
insert into СХЕМА.YYY (id, name, sys_date_create, zzz_id) 
values (8200002, 't_8200002', sysdate, (select trunc(dbms_random.value(1, 1000000)) from dual));
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

-- Лог 2
insert into СХЕМА.YYY (without commit)
07-07-2016 12:13:26
1 row created.
07-07-2016 12:13:26


-- Сессия 3
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;
select max(id) from СХЕМА.YYY;
select to_char(sysdate, 'dd-mm-yyyy hh24:mi:ss') from dual;

-- Лог 3
07-07-2016 12:23:43
8200001
07-07-2016 12:23:43
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39269621
140907
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И такое поведение, наверно, логично (иначе завершить валидацию на таблице, в которую постоянно идет dml, было бы очень затруднительно).
...
Рейтинг: 0 / 0
Add constraint foreign key блокирует таблицу?
    #39270305
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
140907Похоже, в этом промежутке можно вставлять и не коммитить.
Ты уверен, что вторая сессия у тебя не завершилась, отработав?
Или там не стоит какой-нибудь AutoCommit ?

Потому как у меня не воспроизводится
подготовка
Код: 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.
26.
27.
28.
29.
30.
31.
tst> alter session set ddl_lock_timeout=60; -- это чтоб оно сразу с ORA-00054 не валилось

Session altered.

tst> alter session set nls_date_format='dd-mm-yyyy hh24:mi:ss';

Session altered.

tst> create table p1(a number primary key);

Table created.

tst> insert into p1 select rownum from dual connect by level <= 1e6;

1000000 rows created.

tst> create table c1(b number);

Table created.

tst> insert into c1 select p1.a from p1, (select rownum from dual connect by level <= 10);

10000000 rows created.

tst> create index c1_idx on c1(b);

Index created.

tst> alter table c1 add constraint c1_fk foreign key (b) references p1 enable NOVALIDATE;

Table altered.

Незавершенная транзакцияИ поехали, сначала натыкаемся на первую блокировку:
Сессия 2:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
ts2> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:09:53

ts2> insert into u1.c1 values(1);

1 row created.

Сессия 1:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
tst> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:10:03

tst> alter table c1 modify constraint c1_fk enable VALIDATE;
-- ждем..

Сессия 2:
Код: 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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
ts2> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:10:12

ts2> @locks

Username     SID Terminal   Object Name                    COMMAND                  Hld/Req    ID1-ID2     Lock Type
---------- ----- ---------- ------------------------------ ------------------------ ------- -------------- ------------------------------
SYSTEM         8 LUBOMUDR   U1.P1                          SELECT                    RX/-   252814-0       TM - DML enqueue lock
SYSTEM         8 LUBOMUDR   U1.C1                          SELECT                    RX/-   252816-0       TM - DML enqueue lock
SYSTEM         8 LUBOMUDR                                  SELECT                     X/-   2031616-11789  TX - Transaction enqueue lock
U1           211 LUBOMUDR   U1.C1                          ALTER TABLE                -/S   252816-0       TM - DML enqueue lock -- Сессия 1 ждет 1-ю блокировку
U1           211 LUBOMUDR                                  ALTER TABLE                X/-   2228253-347142 TX - Transaction enqueue lock

-- Отменяем транзакцию
ts2> rollback;

Rollback complete.

ts2> @locks

no rows selected -- Блокировок нет, идет валидация

-- Начинаем новую транзакцию, не подтверждаем:
ts2> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:10:35

ts2> insert into u1.c1 values(1);

1 row created.

-- Через некоторое время
ts2> @locks

Username     SID Terminal   Object Name                    COMMAND                  Hld/Req    ID1-ID2     Lock Type
---------- ----- ---------- ------------------------------ ------------------------ ------- -------------- ------------------------------
SYSTEM         8 LUBOMUDR   U1.P1                          SELECT                    RX/-   252814-0       TM - DML enqueue lock
SYSTEM         8 LUBOMUDR   U1.C1                          SELECT                    RX/-   252816-0       TM - DML enqueue lock
SYSTEM         8 LUBOMUDR                                  SELECT                     X/-   2228242-347727 TX - Transaction enqueue lock
U1           211 LUBOMUDR   U1.C1                          ALTER TABLE                -/S   252816-0       TM - DML enqueue lock -- Сессия 1 ждет вторую блокировку

Сессия 1:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
alter table c1 modify constraint c1_fk enable VALIDATE
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


tst> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:11:42

Завершенная транзакция
Сессия 1:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
tst> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:38:01

tst> alter table c1 modify constraint c1_fk enable VALIDATE;
-- ждем...

Сессия 2:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
ts2> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:38:09

ts2> insert into u1.c1 values(1);

1 row created.

ts2> commit;

Commit complete.

ts2> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:38:20

Сессия 1:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
Table altered.

tst> select sysdate from dual;

SYSDATE
-------------------
08-07-2016 16:38:23

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


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