insert 的enq: TM – contention的情况-2 —–只有主键约束无子表的情况

联系:QQ(5163721)

标题:insert 的enq: TM – contention的情况-2 —–只有主键约束无子表的情况

作者:Lunar©版权所有[文章允许转载,但必须以链接方式注明源地址,否则追究法律责任.]

insert 的enq: TM – contention的情况-1 —–对有主外键关系的表的操作
insert 的enq: TM – contention的情况-2 —–只有主键约束无子表的情况

####################################################################################
总结2 :
1,当存在pk时,无论有没有子表,对存在pk的表来说,无论有没有子表,update pk的操作会同时阻塞对该表做insert操作中那些pk跟update语句更改前、后两个值相关的会话。
2,当子表无事务时,我下面的简单的测试情况下(其他复杂情况没有测试)跟上述第一点结果相同
####################################################################################

测试6: 在测试5的基础上,测试一下子表无事务的情况下,对父表的update是如何影响父表的delete和insert的
首先,我们在Session 4(SID 116)对做commit,此时session 2(SID 220)会自动解锁,并报出来应有的违反约束的错误ORA-02292:
Session 4:

SQL> SELECT sid FROM v$session WHERE audsid = userenv('SESSIONID');
 
       SID
----------
       116
 
SQL> INSERT INTO DEPT VALUES (2,'LUNAR');
 
1 row created.
 
SQL> commit;
 
Commit complete.
 
SQL>
 
Session 2:
SQL> SELECT sid FROM v$session WHERE audsid = userenv('SESSIONID');
 
       SID
----------
       220
 
SQL> delete from dept where deptno = 1;
delete from dept where deptno = 1
*
ERROR at line 1:
ORA-02292: integrity constraint (LUNAR.FK_DEPTNO) violated - child record found
 
 
SQL>

现在,我们把所有的会话都做commit或者rollback,然后观察对父表的updae会不会对父表的其他DML操作有影响:
Session 2(SID 220):

SQL> select * from dept;
 
    DEPTNO DNAME
---------- ----------
         1 COSTCENTER
         5 baobao
         2 LUNAR
 
SQL> update dept set deptno =3 WHERE DEPTNO=2;
 
1 row updated.
 
SQL>
 
Session 4(SID 116):
SQL> DELETE FROM DEPT WHERE DEPTNO=1;
DELETE FROM DEPT WHERE DEPTNO=1
*
ERROR at line 1:
ORA-02292: integrity constraint (LUNAR.FK_DEPTNO) violated - child record found
 
 
SQL>
 
Session 5(SID 222):
SQL> INSERT INTO DEPT VALUES (3,'BAOBAO');
....HANG.....
 
Session 3观察:
       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
       220 TM    1062788          0          3          0          0
       220 TX    1310742      42714          6          0          1
       222 TM    1062788          0          3          0          0
       222 TM    1062790          0          3          0          0
       222 TX    1310742      42714          0          4          0
       222 TX    1507340      34195          6          0          0
 
 
SPID                            SID    SERIAL# STATUS
------------------------ ---------- ---------- --------
SQL_TEXT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID        EVENT                                                            STATUS
------------- ---------------------------------------------------------------- --------
12766                           222      49879 ACTIVE
INSERT INTO DEPT VALUES (3,'BAOBAO')
9pmgcjs6qd7sa enq: TX - row lock contention                                    ACTIVE

这里看见session 4对父表的delete不受session 2在父表的update的影响,而session 5对父表的insert 会被session 2在父表的update阻塞
被阻塞的对父表的insert操作等待事件为:enq: TX – row lock contention

在测试一次:
把上面所有会话都commit或者rollback,然后:

Session 2(SID 220):

SQL> select * from dept;
 
    DEPTNO DNAME
---------- ----------
         1 COSTCENTER
         5 baobao
         2 LUNAR
 
SQL> update dept set deptno =3 WHERE DEPTNO=2;
 
1 row updated.
 
SQL> rollback;
 
Rollback complete.
 
SQL> SELECT sid FROM v$session WHERE audsid = userenv('SESSIONID');
 
       SID
----------
       220
 
SQL>
SQL> update dept set deptno =3 WHERE DEPTNO=2;  ---------注意这里,deptno被更新为3
 
1 row updated.
 
SQL>
 
 
Session 4(SID 116):
SQL> SELECT sid FROM v$session WHERE audsid = userenv('SESSIONID');
 
       SID
----------
       116
 
SQL> INSERT INTO DEPT VALUES (6,'BAOBAO');
 
1 row created.
 
SQL> INSERT INTO DEPT VALUES (3,'BAOBAO');  -----------注意这里,只有插入deptno为3时才会被阻塞
..... HANG.....

这里我们看到,对父表的update阻塞了对其他会话对父表insert时pk的值=updae父表的pk的值的会话。
这个我们可以再做一个测试:
测试7,新建两个表,一个有pk,一个无pk,然后做同样的update和insert操作:
无pk的表:

CREATE TABLE LUNAR1
  (
    deptno NUMBER ,
    dname  VARCHAR2(10)
  );
 
insert into LUNAR1 values (1, 'LUNAR');
insert into LUNAR1 values (5, 'BAOBAO');
insert into LUNAR1 values (2, 'HAOBAOBAO');
commit;
 
sessin 1:
update LUNAR2 set deptno =3 WHERE DEPTNO=2;   ----注意这里,deptno被更新为3
 
session 2:
INSERT INTO LUNAR1 VALUES (7,'DABAOBAO');
INSERT INTO LUNAR1 VALUES (3,'DABAOBAO');     -----注意这里,插入了deptno为3的记录

这测试不会有任何问题。

现在我们改为带有pk的表:

CREATE TABLE LUNAR2
  (
    deptno NUMBER CONSTRAINT pk_LUNAR PRIMARY KEY,
    dname  VARCHAR2(10)
  );
   
insert into LUNAR2 values (1, 'LUNAR');
insert into LUNAR2 values (5, 'BAOBAO');
insert into LUNAR2 values (2, 'HAOBAOBAO');
commit;

SESSION 1:

SQL> update LUNAR2 set deptno =3 WHERE DEPTNO=2;    ----注意这里,deptno=2的记录被更新为deptno=3
 
1 row updated.
 
SQL>
 
SESSION 2:
SQL> INSERT INTO LUNAR2 VALUES (7,'DABAOBAO');
 
1 row created.
 
Elapsed: 00:00:00.00
SQL> INSERT INTO LUNAR2 VALUES (3,'DABAOBAO');    -----注意这里,只有deptno为3的插入被阻塞
....HANG.....
 
取消掉,改为插入deptno=2的试试看:
SQL> INSERT INTO LUNAR2 VALUES (3,'DABAOBAO');
^Z^CINSERT INTO LUNAR2 VALUES (3,'DABAOBAO')
            *
ERROR at line 1:
ORA-01013: user requested cancel of current operation
 
 
Elapsed: 00:09:31.33
SQL> INSERT INTO LUNAR2 VALUES (2,'DABAOBAO');     -----注意这里,只有deptno为2的插入被阻塞
....HANG.....

也就是说,对存在pk的表来说,无论有没有子表,update pk的操作会同时阻塞对该表做insert操作中那些pk跟update语句更改前、后两个值相关的会话
比如update LUNAR2 set deptno =3 WHERE DEPTNO=2,就会阻塞所有insert deptno=2和deptno=3的会话

——未完,待续—

此条目发表在 FAQ 分类目录,贴了 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

发表评论前,请滑动滚动条解锁
三十岁