我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

无法利用主外键时控制主子表的并发访问(一)

上一篇 / 下一篇  2008-01-26 23:56:10 / 个人分类:ORACLE

主子表的并发控制,一般是通过主外键的约束来实现。通过这种方式,保证子表插入数据的情况下,主表不能将记录删除。

目前碰到一个问题,无法通过主外键的约束来控制并发访问。

这篇讨论主外键是如何控制主子表的并发访问的。

 

 

构造一个简单的例子,来说明主外键对并发的控制:

SQL> CREATE TABLE T_P (ID NUMBER PRIMARY KEY, FLAG VARCHAR2(1));

表已创建。

SQL> CREATE TABLE T_FITPUB个人空间S$jl9N5f4` ZB
  2  (ITPUB个人空间D%Q_/N*g Nvg
  3   ID NUMBER PRIMARY KEY,
WlpJ"i,I V0  4   FID NUMBER,ITPUB个人空间 W~'\:M-]S
  5   FLAG VARCHAR2(1),ITPUB个人空间G:]1~#i suUHe
  6   FOREIGN KEY (FID) REFERENCES T_P
#|Q:|9QE.i0  7  );

表已创建。

SQL> INSERT INTO T_P VALUES (1, 0);

已创建1行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM T_P;

        ID F
c3Q&X L5r0---------- -ITPUB个人空间g*_$\P't:XU^;p
         1 0

现在新启动一个SQLPLUS,设置不同的SQLPROMPT,和会话一以示区别:

SQL> SET SQLP 'SQL2> '
h&]B*xhXa0SQL2> SELECT * FROM T_P;

        ID FITPUB个人空间\Csv:U0Rv/^.?
---------- -ITPUB个人空间|s3j0w g1Wj q\5GV!n
         1 0

现在在会话一对主表记录进行删除:

SQL> DELETE T_P WHERE ID = 1;

已删除1行。

在会话二对子表进行插入,引用会话一要删除的主表记录:

SQL2> INSERT INTO T_F VALUES (1, 1, 0);

会话二这时被锁住:

SQL> ROLLBACK;

回退已完成。

会话一回滚后,会话二插入成功:


9])t s-}MK6A0
已创建1行。

SQL2> ROLLBACK;

回退已完成。

SQL2> SELECT * FROM T_F;

未选定行

SQL2> SELECT * FROM T_P;

        ID FITPUB个人空间 z@9mfzXP
---------- -ITPUB个人空间 cO%l.L5J0d
         1 0

回到开始的状态,先删除主表:

SQL> DELETE T_P WHERE ID = 1;

已删除1行。

在会话二插入参考删除主表记录的子表记录:

SQL2> INSERT INTO T_F VALUES (1, 1, 0);

会话二处于被锁的状态,如果这时会话一提交:

SQL> COMMIT;

提交完成。

则会话二插入报错,主键不存在:

INSERT INTO T_F VALUES (1, 1, 0)
w6BC-hu%`2? x0U0*
3ZZW:UC+Z;v0
1行出现错误:
?G*q&q%k f+~,g0ORA-02291:
违反完整约束条件(TEST.SYS_C0012880) -未找到父项关键字


&p/U\oI9es0SQL2>

Oracle正是通过主外键的关系实现了主子表的并发控制,确保表的数据不会出现子表记录被插入但是对应的主表信息被删除的情况。

上面是对先删除主表记录的情况进行的分析,如果先插入子表的记录,而后进行主表记录的删除,那么情况和上面没有什么区别,都是后面的事务等待前一个事务的提交和回滚。下面通过例子简单描述一下:

SQL> INSERT INTO T_P VALUES (1, 0);

已创建1行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM T_P;

        ID FITPUB个人空间 u%Q0E2sH-G} r)i
---------- -ITPUB个人空间5c.b{O0H%bT,a8\
         1 0

SQL> INSERT INTO T_F VALUES (1, 1, 0);

已创建1行。

会话二的删除会被锁:

SQL2> SELECT * FROM T_P;

        ID F
#?X`J \w0---------- -ITPUB个人空间^ X0b)l] f|
         1 0

SQL2> DELETE T_P WHERE ID = 1;

会话一提交:

SQL> COMMIT;

提交完成。

会话二则报错:

DELETE T_P WHERE ID = 1
B MO(P7|9B&h }/Y0*
xX:Y x"J:Ii|0
1行出现错误:ITPUB个人空间:y tI$L*}2U
ORA-02292:
违反完整约束条件(TEST.SYS_C0012880) -已找到子记录

ITPUB个人空间i-Z f0v1t&W(GN
SQL2>

正常情况下,Oracle的主外键可以帮助我们在并发访问的情况下来维护数据的完整性。

 


TAG:

谷雨霖 引用 删除 pharos   /   2008-03-21 18:09:05
天天坚持写日志,赞一个!
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar