zoukankan      html  css  js  c++  java
  • oracle为什么尽量不要使用外键的最好理解

    对于死锁问题相信大家都是很头疼的,为什么不要使用外键呢?最简单的回答就是太容易产生死锁了。

    经过个人的测试,我发现外键删除的时候,是按照表会话的顺序执行的,也就是说如果只有一个事务,只要子表删掉外键表的项,外键表就可以删除,但是如果同时有多个事务,这就难说了,具体举例子如下:

    首先我们创建表并创建数据,顺序执行如下代码:

    create table t_p (id number primary key, name varchar2(30)); 
    
    create table t_f (fid number, f_name varchar2(30), foreign key (fid) references t_p); 
    
    insert into t_p values (1, 'a'); 
    
    insert into t_f values (1, 'a'); 
    
    insert into t_p values (2, 'b'); 
    
    insert into t_f values (2, 'c'); 
    
    commit; 

     然后测试如下:我在本用户下(C##BENDIHELI)和System下开启两个sql工作表:

    其中在C##BENDIHELI记为sql1,system下记为sql2

    如果程序的执行顺序为:

    1.sql1:delete t_f where fid = 2; 

    2.sql2:delete c##bendiheli.t_f where fid = 1; 

    3.sql1:delete t_p where id = 2; 

    此时sql1等待,因为sql2未提交(这就是我理解的外键表需要找会话,本会话可以继续,如果有其他会话未提交,他就等待)

    4.sql2:delete c##bendiheli.t_p where id = 1; 

    此时sql2等待,因为sql1未提交

    现在的程序sql1的事务等待sql2的提交,sql2的事务等待sql1的提交,完了,锁住了。

    至于本人理解外键是按照会话寻找的原因是,即使我把2换成insert into c##bendiheli.t_f values(1,'duidu'),3仍然会等待,因为2没提交

    若我执行顺序为如下,则可以,这样就更能理解我的想法,就是外键按照非本会话的会话顺序执行

    1.sql1:delete t_f where fid = 2; 

    2.sql2:insert into c##bendiheli.t_f values(1,'duidu')

    3.sql1:delete t_p where id = 2; 

    此时sql1等

    4.sql2:commit;

    提交后sql1就不再等待

    解决方案:外键加索引

    create index ind_t_f_fid on t_f(fid);

    个人理解,这样就解决了外键按照会话找连接表的,而是通过索引来找,这样以来上方出现死锁的程序就不再出现死锁,因为这样在本事务内,直接找索引即可。 

    本文的理解借鉴于博主:https://blog.csdn.net/fenyu8/article/details/53811686

  • 相关阅读:
    水晶苍蝇拍:微薄投资感悟摘录(四) (2012-04-03 14:11:01)
    水晶苍蝇拍:投资感悟(三)(手打,有删减)
    水晶苍蝇拍:投资感悟(二)(2011-12-27 08:17:54)
    leetcode -- String to Integer (atoi)
    leetcode -- Longest Palindromic Substring
    leetcode -- Longest Substring Without Repeating Characters
    leetcode -- Add Two Numbers
    QQ截图工具截取
    LUA学习笔记(第5-6章)
    Lua5.2 请求 luasocket 相关模块时的 multiple-lua-vms-detected
  • 原文地址:https://www.cnblogs.com/ningxinjie/p/12765483.html
Copyright © 2011-2022 走看看