深入内核:Oracle数据库里SELECT操作Hang解析

简介:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

崔华,网名 dbsnake

Oracle ACE Director,ACOUG 核心专家

编辑手记:感谢崔华授权我们独家转载其精品文章,也欢迎大家向“Oracle”社区投稿。

我们都知道在 Oracle 数据库里是“读不阻塞写,写不阻塞读”,那么是否可以认为在正常情况下,select 操作是怎样都能执行,始终不会被 hang 住的呢?注意这里提到的是正常情况下,不包括那些由于 latch 被 hold 住、或者 bug 等相关异常导致的 select 操作 hang 住的情况。

 

答案是:不可以这样认为的。


我们来举一个反例。

首先我们来分析一下在 sql 硬解析时在相关表对象上 library cache lock 的持有情况。这里我用到了10049事件,用10049事件,最重要的就是要知道如何设置它所对应的 level 值。

 

10049的level值可能会有如下一些组合:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

这里因为我要跟踪 sql 硬解析时相关表对象的 library cache lock 的持有情况,所以这里level 值取0x0210=0x0200|0x0010,即这里 level 值取528。

SQL> select to_number(‘210′,’XXXX’) 

from dual;

640?wx_fmt=png&wxfrom=5&wx_lazy=1

先在11.2.0.1里使用一下10049事件:

C:\Documents and Settings\cuihua>sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 星期三 6月 27 21:39:37 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

SQL> conn / as sysdba;

已连接。

SQL> oradebug setmypid

已处理的语句 

SQL> oradebug event 10049 trace

 name context forever,level 528

已处理的语句 

SQL> select count(*) from scott.emp;

  COUNT(*)

———-

        14 

SQL> oradebug tracefile_name

c:\app\cuihua\diag\rdbms\cuihua112\

cuihua112\trace\cuihua112_ora_2292.trc 

这个TRACE文件没有任何内容,看起来似乎是10049事件对11gR2无效或者 Oracle 改变了10049事件在11gR2中的 level 的定义(这个我不确定)。

 

我们换一个10gR2的版本:

SQL> select * from v$version;

640?wx_fmt=png&wxfrom=5&wx_lazy=1

SQL> oradebug setmypid

已处理的语句

SQL> oradebug event 10049 trace 

name context forever,level 528

已处理的语句 

SQL> select count(*) from scott.emp;

  COUNT(*)

———-

        13 

SQL> oradebug tracefile_name

d:\oracle\admin\cuihua\udump\cuihua_ora_5012.trc

 

从上述 trace 文件(d:\oracle\admin\cuihua\udump\cuihua_ora_5012.trc)中从前到后可以看到如下内容:

640?wx_fmt=png&wxfrom=5&wx_lazy=1
640?wx_fmt=png&wxfrom=5&wx_lazy=1

即针对上述 cursor 是以 NULL 模式持有 library cache lock,

针对表 scott.emp 是以 share 模式持有 library cache lock。

也就是说,只要我事先以 exclusive 模式在表 scott.emp上持有 library cache lock,那么后续的以硬解析方式执行的针对该表的所有sql(包括 select 语句)都将被 hang 住。

 

现在我们来测一下对一个表增加一个主键时的 library cache lock 的持有情况。

SQL> create table t2 as select * from emp; 

Table created

 SQL> select count(*) from t2; 

  COUNT(*)

———-

        13 

SQL> conn / as sysdba;

已连接。 

SQL> oradebug setmypid

已处理的语句 

SQL> oradebug event 10049 trace name

 context forever,level 528

已处理的语句 

SQL> alter table scott.t2 add constraint PK_T2 

primary key (EMPNO);

 表已更改。 

SQL> oradebug tracefile_name

d:\oracle\admin\cuihua\udump\cuihua_ora_6120.trc 

从这个trace文件(d:\oracle\admin\cuihua\udump\cuihua_ora_6120.trc)中我们可以看出对表t2的 library cache lock 的先后持有模式为:

640?wx_fmt=png&wxfrom=5&wx_lazy=1
640?wx_fmt=png&wxfrom=5&wx_lazy=1
640?wx_fmt=png&wxfrom=5&wx_lazy=1

即大部分时间 library cache lock 的持有模式都是N,只有在一头一尾的时候才是X。

但请注意这种情况下 select 操作是会被hang住的。


因为一开头的X是 kglget,结尾才 kgllkdl(kgllkdl大致是 kgl lock delete 的意思,表示释放相应的 library cache lock),并且它们的 KGL Lock addr 相同:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

这也就意味着在添加主键的整个过程中,Oracle始终会以 exclusive 模式在表 scott.t2 上持有 library cache lock,直到最后主键添加完毕了才释放。

所以在 win32上的10.2.0.1中,在添加主键的过程中会一直阻塞查询(select)操作。

 

我们来测一下,同时开3个session。

Session 1:

SQL> create table t3(id number); 

Table created 

SQL> declare

  2    i number;

  3  begin

  4    for i in 1..3000000 loop

  5     insert into t3 values (i);

  6    end loop i;

  7    commit;

  8  end;

  9  / 

PL/SQL procedure successfully completed 

Session 2:

SQL> select * from v$mystat

 where rownum<2;

640?wx_fmt=png&wxfrom=5&wx_lazy=1

在 session 1中开始执行添加主键操作:

Session 1:

SQL> alter table scott.t3 add constraint PK_T3 primary key (id);

……开始执行

 

转到 session 2执行查询操作:

Session 2:

SQL> select * from t3 

where rownum<10;

……这里 hang 住了

 

转到 session 3并执行对 session2的等待事件的查询:

Session 3:

SQL> select t.event,t.state,t.seconds_in_wait 

from v$session t

 where sid=138;

640?wx_fmt=png&wxfrom=5&wx_lazy=1

从中可以看到 session 2在等待 library cache lock,同时它的STATE为waiting,SECONDS_IN_WAIT的值在递增。

这就验证了我们的结论:在 win32上的10.2.0.1中,在对表增加主键的过程中会一直阻塞对这个表的查询(select)操作。

 

现在我们再问一个问题:是不是所有对表的DDL操作,在DDL操作的执行过程中都会阻塞对这个表的select操作?

 

答案是:不是这样的。

 

我们来举一个反例。

现在我们来测一下对表 drop一个column 时 library cache lock 的持有情况:

SQL> desc t1;

640?wx_fmt=png&wxfrom=5&wx_lazy=1
SQL> select count(*) from t1;

640?wx_fmt=png&wxfrom=5&wx_lazy=1

同时开两个session。

在session 1中打开10049事件后drop表t1的列object_type:

Session 1:

SQL> conn / as sysdba;

已连接。 

SQL> oradebug setmypid

已处理的语句 

SQL> oradebug event 10049 trace 

name context forever,level 528

已处理的语句 

SQL> alter table scott.t1 drop

 column OBJECT_TYPE; 

表已更改。

SQL> oradebug tracefile_name

d:\oracle\admin\cuihua\udump\

cuihua_ora_5020.trc

session 2在 session 1执行 drop column 操作的同时查询表t1,结果是 select 操作并没有被 hang 住,且能看到正在被 drop 的列 object_type:

Session 2:

SQL> select owner,object_name,object_type

 from t1

 where rownum<10;

640?wx_fmt=png&wxfrom=5&wx_lazy=1
从 session 1所产生的 trace 文件

(d:\oracle\admin\cuihua\udump\cuihua_ora_5020.trc)中我们可以看出对表t1的 library cache lock 的先后持有模式为:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

即大部分时间对表 scott.t1 的 library cache lock 的持有模式都是S,最后才是X,所以这就可以解释为什么在对表 scott.t1 执行 drop column 操作的时候对它的select语句能够同时执行。

从 trace 文件来看,drop column 并不是不会阻塞 select 操作,只是阻塞的时间点要恰好是Oracle以X模式持有library cache lock时。

 

最后我们来测一下对一个表增加一个 unique constraint时library cache lock的持有情况

SQL> conn / as sysdba;

已连接。 

SQL> oradebug setmypid

已处理的语句 

SQL> oradebug event 10049 trace

 name context forever,

level 528

已处理的语句 

SQL> alter table scott.t2 add constraint UK_T2_EMPNO

 unique (EMPNO, ENAME);

表已更改。

 SQL> oradebug tracefile_name

d:\oracle\admin\cuihua\udump\cuihua_ora_5240.trc

 

从这个trace文件中我们可以看出对表 scott.t2 的 library cache lock 的先后持有模式为:

640?wx_fmt=png&wxfrom=5&wx_lazy=1
640?wx_fmt=png&wxfrom=5&wx_lazy=1

即大部分时间都是N,一头一尾才是X,这个和添加主键操作一样,在此不再赘述。

 

结论:不要随便在生产环境对大表执行DDL操作(如添加唯一性约束等),可能会导致针对这个表的所有 sql(包括select操作)在执行DDL操作的时间段都 hang 住。


本文出自数据和云公众号,原文链接


相关文章
|
25天前
|
Oracle 安全 关系型数据库
【Oracle】玩转Oracle数据库(六):模式对象管理与安全管理
【Oracle】玩转Oracle数据库(六):模式对象管理与安全管理
26 10
|
25天前
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(七):RMAN恢复管理器
【Oracle】玩转Oracle数据库(七):RMAN恢复管理器
44 5
|
6天前
|
DataWorks Oracle 关系型数据库
DataWorks操作报错合集之尝试从Oracle数据库同步数据到TDSQL的PG版本,并遇到了与RAW字段相关的语法错误,该怎么处理
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
22 0
|
6天前
|
算法 安全 Linux
深度解析:Linux内核内存管理机制
【4月更文挑战第30天】 在操作系统领域,内存管理是核心功能之一,尤其对于多任务操作系统来说更是如此。本文将深入探讨Linux操作系统的内核内存管理机制,包括物理内存的分配与回收、虚拟内存的映射以及页面替换算法等关键技术。通过对这些技术的详细剖析,我们不仅能够理解操作系统如何高效地利用有限的硬件资源,还能领会到系统设计中的性能与复杂度之间的权衡。
|
13天前
|
存储 Oracle 网络协议
Oracle 11gR2学习之二(创建数据库及OEM管理篇)
Oracle 11gR2学习之二(创建数据库及OEM管理篇)
|
17天前
|
Oracle 网络协议 关系型数据库
异地使用PLSQL远程连接访问Oracle数据库【内网穿透】
异地使用PLSQL远程连接访问Oracle数据库【内网穿透】
|
17天前
|
SQL Oracle 安全
Oracle数据库中的事务和锁
【4月更文挑战第19天】Oracle数据库的事务和锁是确保数据完整性和并发控制的核心机制。事务遵循ACID原则,保证操作的原子性、一致性、隔离性和持久性。通过COMMIT或ROLLBACK来管理事务更改。锁包括共享锁(读)、排他锁(写)、行级锁和表级锁,用于控制并发访问。自动锁机制在DML操作时生效,防止数据冲突。事务和锁共同维护数据库的稳定和安全。
|
17天前
|
存储 Oracle 关系型数据库
Oracle RAC:数据库集群的舞动乐章
【4月更文挑战第19天】Oracle RAC是Oracle提供的高可用性数据库解决方案,允许多个实例共享同一数据库,确保业务连续性和数据完整性。通过集群件和全局缓存服务实现服务器间的协调和通信。RAC提供高可用性,通过故障转移应对故障,同时提升性能,多个实例并行处理请求。作为数据管理员,理解RAC的架构和管理至关重要,以发挥其在数据管理中的最大价值。
|
17天前
|
监控 Oracle 安全
Oracle用户事件触发器:数据库世界的“福尔摩斯”
【4月更文挑战第19天】Oracle用户事件触发器是数据库中的监控机制,类似于“福尔摩斯”,在用户执行特定操作时自动触发。它们关注用户行为而非数据变化,可用于权限检查、安全监控、性能优化等。通过DDL语句创建,需注意逻辑清晰、条件合适及定期更新,以适应数据库变化和业务发展。掌握其使用能有效保障数据安全与稳定。
|
17天前
|
SQL 存储 Oracle
Oracle语句级触发器:数据库的“隐形哨兵”
【4月更文挑战第19天】Oracle语句级触发器是数据库中的自动执行程序,当特定事件(如INSERT、UPDATE、DELETE)发生时,会针对整个SQL语句触发。以新员工入职记录日志为例,创建语句级触发器可自动在操作后向日志表插入信息,减少手动工作并提高性能。虽然无法处理行级详细信息,但在处理大量数据时,相比行级触发器更高效。掌握触发器使用能提升数据管理效率和安全性。

推荐镜像

更多