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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

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 住。


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


相关文章
|
4天前
|
Oracle 安全 关系型数据库
Oracle数据恢复—Oracle数据库误删除的数据恢复方法探讨
删除Oracle数据库数据一般有以下2种方式:delete、drop或truncate。下面针对这2种删除oracle数据库数据的方式探讨一下oracle数据库数据恢复方法(不考虑全库备份和利用归档日志)。
|
14天前
|
存储 Oracle 关系型数据库
Oracle同一台服务器创建多个数据库
【8月更文挑战第30天】在 Oracle 中,可在同一服务器上创建多个数据库。首先确保已安装 Oracle 软件并具有足够资源,然后使用 DBCA 工具按步骤创建,包括选择模板、配置存储及字符集等。重复此过程可创建多个数据库,需确保名称、SID 和存储位置唯一。创建后,可通过 Oracle Enterprise Manager 进行管理,注意服务器资源分配与规划。
28 10
|
2天前
|
SQL 关系型数据库 MySQL
MySQL技术安装配置、数据库与表的设计、数据操作解析
MySQL,作为最流行的关系型数据库管理系统之一,在WEB应用领域中占据着举足轻重的地位。本文将从MySQL的基本概念、安装配置、数据库与表的设计、数据操作解析,并通过具体的代码示例展示如何在实际项目中应用MySQL。
7 0
|
14天前
|
存储 C# 关系型数据库
“云端融合:WPF应用无缝对接Azure与AWS——从Blob存储到RDS数据库,全面解析跨平台云服务集成的最佳实践”
【8月更文挑战第31天】本文探讨了如何将Windows Presentation Foundation(WPF)应用与Microsoft Azure和Amazon Web Services(AWS)两大主流云平台无缝集成。通过具体示例代码展示了如何利用Azure Blob Storage存储非结构化数据、Azure Cosmos DB进行分布式数据库操作;同时介绍了如何借助Amazon S3实现大规模数据存储及通过Amazon RDS简化数据库管理。这不仅提升了WPF应用的可扩展性和可用性,还降低了基础设施成本。
35 0
|
14天前
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
34 0
|
14天前
|
JSON 数据格式 Java
化繁为简的魔法:Struts 2 与 JSON 联手打造超流畅数据交换体验,让应用飞起来!
【8月更文挑战第31天】在现代 Web 开发中,JSON 成为数据交换的主流格式,以其轻量、易读和易解析的特点受到青睐。Struts 2 内置对 JSON 的支持,结合 Jackson 库可便捷实现数据传输。本文通过具体示例展示了如何在 Struts 2 中进行 JSON 数据的序列化与反序列化,并结合 AJAX 技术提升 Web 应用的响应速度和用户体验。
33 0
|
14天前
|
SQL 存储 数据库
|
Oracle 关系型数据库
Oracle操作总结
聚合函数: count sum max min avg count返回的结果集中行的数目 sum max min avg顾名思义。但是要注意聚合函数强调的是"结果集中……",强调了 现在进行的操作对象是结果集 注意NULL不参与聚合函数的预算,要想其参加运算那么要将其转换为非空的值 分组: 在一个查询中需要进行多次统计就需要就必须使用分组 where是分组前过滤,过滤的是原始数据。
834 0
|
30天前
|
存储 自然语言处理 Oracle
Oracle数据库字符集概述及修改方式
【8月更文挑战第15天】Oracle 数据库字符集定义了数据的编码方案,决定可存储的字符类型及其表示方式。主要作用包括数据存储、检索及跨系统传输时的正确表示。常见字符集如 AL32UTF8 支持多语言,而 WE8MSWIN1252 主用于西欧语言。修改字符集风险高,可能导致数据问题,需事先备份并评估兼容性。可通过 ALTER DATABASE 语句直接修改或采用导出-导入数据的方式进行。完成后应验证数据完整性。此操作复杂,须谨慎处理。
|
27天前
|
数据采集 Oracle 关系型数据库
实时计算 Flink版产品使用问题之怎么实现从Oracle数据库读取多个表并将数据写入到Iceberg表
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。

推荐镜像

更多