Oracle Foreign key 无索引导致的死锁 deadlock 或者hang

2024-03-08 07:04

本文主要是介绍Oracle Foreign key 无索引导致的死锁 deadlock 或者hang,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 ---------------lock
死锁通常发生在主表和子表更新主外键上。更新主表的主键,那么子表的外键会被锁住

如果删除主表的行,那么子表会被锁住。

create table p(x int primary key);
create table c( x references p);
insert into p values(1);
insert into p values (2);
commit;

在一个seesion下执行

 insert into c values(2);

换一个session执行

SQL> delete from p where x = 1;

会发现hang住了。

 select table_name,
        constraint_name,        
        cname1 || nvl2(cname2, ',' || cname2, null) ||        
        nvl2(cname3, ',' || cname3, null) ||        nvl2(cname4, ',' || cname4, null) ||        
        nvl2(cname5, ',' || cname5, null) ||
        nvl2(cname6, ',' || cname6, null) ||        
        nvl2(cname7, ',' || cname7, null) ||        nvl2(cname8, ',' || cname8, null)        
        columns
 
   from (select b.table_name,                
                b.constraint_name,                
                max(decode(position, 1, column_name, null)) cname1,                
                max(decode(position, 2, column_name, null)) cname2,                
                max(decode(position, 3, column_name, null)) cname3,                
                max(decode(position, 4, column_name, null)) cname4,                
                max(decode(position, 5, column_name, null)) cname5,                
                max(decode(position, 6, column_name, null)) cname6,                
                max(decode(position, 7, column_name, null)) cname7,                
                max(decode(position, 8, column_name, null)) cname8,                
                count(*) col_cnt         
           from (select substr(table_name, 1, 30) table_name,                        
                        substr(constraint_name, 1, 30) constraint_name,                        
                        substr(column_name, 1, 30) column_name,                        
                        position                 
                   from user_cons_columns) a,                
                user_constraints b         
          where a.constraint_name = b.constraint_name               
            and b.constraint_type = 'R'         
          group by b.table_name, b.constraint_name         
         ) cons 
  where col_cnt > ALL 
  (select count(*)         
           from user_ind_columns i         
          where i.table_name = cons.table_name               
            and i.column_name in (cname1,
                                  cname2,
                                  cname3,
                                  cname4,                                  
                                  cname5,
                                  cname6,
                                  cname7,
                                  cname8)               
            and i.column_position <= cons.col_cnt         
          group by i.index_name         
         )
 
 

TABLE_NAME                     CONSTRAINT_NAME COLUMNS

--------------------------------------------- ---------------

C                              SYS_C007722     X

发现C上没有索引,这个问题可以通过创建索引来解决

SQL> create index idx_c on c(x);

Index created.

SQL> insert into c values(2);

1 row created

换个session2执行

SQL> delete from p where x = 1;

1 row deleted.

可以 看到不再hang住了。

---------------------------dead lock

INSERT

Insert发生阻塞的唯一情况就是用户拥有一个建有主键约束的表。当2个的会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另外一个会话提交或会滚。一个会话提交时,另一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。

UPDATE 和DELETE当执行Update和delete操作的数据行已经被另外的会话锁定时,将会发生阻塞,直到另一个会话提交或会滚。


 


Select …for update

当一个用户发出select..for update的错作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞。需要等另一个会话结束之后才可继续执行。
可以通过发出 select… for update nowait的语句来避免发生阻塞,如果资源已经被另一个会话锁定,则会返回以下错误:Ora-00054:resource busy and acquire with nowait specified.

select… for update wait 100;设置等待时间

死锁-deadlock
定义:当两个用户希望持有对方的资源时就会发生死锁.
即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚.
例子:
1:用户1对A表进行Update,没有提交。
2:用户2对B表进行Update,没有提交。
此时不存在资源共享的问题。
3:如果用户2此时对A表作update,则会发生阻塞,需要等到用户一的事物结束。
4:如果此时用户1又对B表作update,则产生死锁。此时Oracle会选择其中一个用户进行会滚,使另一个用户继续执行操作。
起因:
Oracle的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。

drop table p cascade constraints;
drop table c;
create table p(x int primary key);
create table c( x references p);
insert into p values(1);
insert into p values (2);
insert into c values (2);
commit;
 

---session 1

SQL> select * from p ;

                                      X
---------------------------------------
                                      1
                                      2

SQL> select *from c;

                                      X
---------------------------------------
                                      2

SQL> 
SQL> update p set x=3 where x=1
  2  ;

1 row updated


SQL> update c set x=3 where x=2;-------主外键存在情况,只要三个update 就行

1 row updated


SQL> 
SQL> select * from p ;

                                      X
---------------------------------------
                                      2
                                      3

SQL> select *from c;

                                      X
---------------------------------------
                                      3

SQL> 

---session 2

SQL> 
SQL> select * from p ;

                                      X
---------------------------------------
                                      1
                                      2

SQL> select *from c;

                                      X
---------------------------------------
                                      2

SQL> update c set x=1 where x=2;
update c set x=1 where x=2

ORA-00060: deadlock detected while waiting for resource
SQL> 
SQL> select * from p ;

                                      X
---------------------------------------
                                      2
                                      3

SQL> select *from c;

                                      X
---------------------------------------
                                      3

SQL> 

----没有主外键--------------deadlock 发生在session 1--P的update 成功了

---session 1

SQL> select * from p ;

                                      X
---------------------------------------
                                      1
                                      2

SQL> select *from c;

                                      X
---------------------------------------
                                      2

SQL> update p set x=3 where x=1;

1 row updated


SQL> update c set x=3 where x=2;
update c set x=3 where x=2

ORA-00060: deadlock detected while waiting for resource

SQL> 
SQL> 
SQL>  select * from p ;
SQL> 
SQL>  select * from p ;

                                      X
---------------------------------------
                                      3
                                      2

SQL> select *from c;

                                      X
---------------------------------------
                                      2 ---如果session 2 未commit还是2

SQL> commit;

Commit complete


SQL> select *from c;

                                      X
---------------------------------------
                                      3

SQL> 

---session 2

SQL> 
SQL> select * from p ;

                                      X
---------------------------------------
                                      1
                                      2

SQL> select *from c;

                                      X
---------------------------------------
                                      2

SQL> update c set x=3 where x=2;

1 row updated----立即成功


SQL> update p set x=3 where x=1;
SQL> 

0 rows updated----等待session commit, 如果commit 这边立即开始执行,记录没有了


SQL> select *from c;

                                      X
---------------------------------------
                                      3------这边是3

SQL> select * from p ;

                                      X
---------------------------------------
                                      3
                                      2

SQL> 

这篇关于Oracle Foreign key 无索引导致的死锁 deadlock 或者hang的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/786367

相关文章

浅谈mysql的not exists走不走索引

《浅谈mysql的notexists走不走索引》在MySQL中,​NOTEXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引,下面就来介绍一下mysql的notexists走不走索... 在mysql中,​NOT EXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引。以下

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

python3如何找到字典的下标index、获取list中指定元素的位置索引

《python3如何找到字典的下标index、获取list中指定元素的位置索引》:本文主要介绍python3如何找到字典的下标index、获取list中指定元素的位置索引问题,具有很好的参考价值,... 目录enumerate()找到字典的下标 index获取list中指定元素的位置索引总结enumerat

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Oracle 数据库数据操作如何精通 INSERT, UPDATE, DELETE

《Oracle数据库数据操作如何精通INSERT,UPDATE,DELETE》在Oracle数据库中,对表内数据进行增加、修改和删除操作是通过数据操作语言来完成的,下面给大家介绍Oracle数... 目录思维导图一、插入数据 (INSERT)1.1 插入单行数据,指定所有列的值语法:1.2 插入单行数据,指

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.