`
骑猪逛街666
  • 浏览: 140307 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Oracle高并发系列1:DML引起的常见问题及优化思路

阅读更多
[url]http://click.aliyun.com/m/21918/ [/url]


作者介绍
王鹏冲,平安科技数据库技术专家,浸淫数据库行业十多年,对Oracle数据库有浓厚兴趣,也对MySQL、MongoDB、Redis等数据库有一定架构和运维经验,目前正沉迷在PostgreSQL数据库与Oracle数据库的PK之中,重点在关系型数据库的分布式架构研究。


引言 


Oracle数据库是设计为一个高度共享的数据库,这里所说的“共享”,可以从数据库共享内存、后台进程、cursor、执行计划、latch等方面去理解。Oracle如此设计的目的是以最小的系统开销、最大化地支持更多的并发会话。也是基于这个设计思想,所以Oracle单个实例的垂直扩展能力一直是DB领域内的佼佼者。



之前曾经看到PG大牛的文章分析关于Oracle的CursorPin S为什么不会在PostgreSQL里面出现,其主要原因是PostgreSQL的执行计划不是全局共享的,而Oracle里面同样的Cursor在不同session间一般情况下都是可以共享的(Oracle在某些条件下会也触发重新硬解析)。这样的设计客观来讲其实各有优劣,虽然PG的plan cache是不同会话不共享的,避免了高并发时不同会话对同一个cursor产生争用,但是也意味着同样的并发会话数的情况下,PG的会话所需求的cache会更多,而且每个会话都至少要parse一次;或者反过来说同样的资源限制的前提下,Oracle支持的并发数更高。



引用一位Oracle 7的OCP,资深Oracle老司机的一段话:“早期Oracle就是使用session私有内存,但当负载并发增加时,内存消耗成了问题,而且执行计划无法共享,增加率parse时间,对于OLTP系统parse时间的增加对于整体执行时间影响较大。因此Oracle基于这一点进行了优化,包括session cached cursor和shared pool等,减少了SQL执行过程中的parsing time和planning time。但没有免费的午餐,肯定会有其它消耗,类似内存结构的并发保护上的成本。总之:



session级SQL解析是Oracle最开始采用过的技术。

任何应用都要针对其所采用的数据库的特点进行好的设计。



这里不探讨哪个数据库更NB,每种数据库技术的发展会受多种因素的影响,包括商业战略、市场需求、软硬件技术成熟度等。我们采用Oracle多年,对于Oracle数据库有深厚的感情,但是目前也同时义无反顾地投入开源数据库和NoSQL的怀抱,技术无好坏,最适合应用场景的就是最好的。这里只重点探讨,当Oracle数据库的这些“共享”资源,遭遇高并发时的问题发生的原因和应对措施。



这里谈的是思路,不是具体的命令。


这里的处理方法,是基于过往发生过的实际案例总结而来。



高并发的DML引发的问题



Oracle的表是堆表,索引是B树,当对表做DML时,Oracle会对table的block进行操作,同时也对索引树的block进行维护,那么当同一时间有大量会话都需要对索引(或表)的同一个block做维护时,就会产生索引(或表)上面的争用。当出现争用时,v$session_wait显示了当前的会话正在等待的event name。



  1 enq: TX - allocate ITL entry


这个等待事件表明,当前的会话正在等待一个block上面的事务槽的分配,可能是table block或index block。



可能的原因有:



Initial trans设置过小。

并发DML太高,ITL slot被其它会话占用还未释放、且该block上也无空闲空间可以增加新的ITL slot,故当暂无free的ITLslot可供使用,后续的会话只能等待。

设置合理,并发也不是非常高,但是正在运行的语句效率发生了变化,导致hold ITL的时间变长,进而引发了后续的拥堵。



解决思路:



已有的索引,进行Rebuild,重建时增加initrans,比如从16->32->64(重建索引时若加大pct free,只是刚重建完毕为每个block预留了更多空闲空间,但是随着后续索引的维护这些空闲空间有可能还会被占用)。

新建的索引,修改数据库开发规范,新建索引时默认initrans为16;

Table block一般很少出现上述问题,但是生产过程中我们的一个非常高频update的table也遇到过此问题,所以最后也修改了规范新建表时默认指定initrans为6。

如果确认是sql语句效率下降导致hold ITL时间变长,那么分析sql效率下降的原因并优化。



小知识点:



在v$lock中若看到某个会话正request一个lmode为4的锁,其原因之一就可能是ITL等待造成的,其它原因可能是并发操作主键、位图索引、分布式事务等。



  2 enq: TX - index contention


这个问题一般发生在表在高并发insert操作时,等待在字段类型是日期、自增序列的索引block上。因为应用始终插入的都是最新(high key)的值,导致这些索引一般都是右倾斜增长的,也就是说最近最频繁的操作都发生在索引最右边的那个叶子块上,叶子块的free空间很快被填满,然后叶子块要分裂,分裂过程总要去找free block,index spliter的进程会持有一个enq:TX锁,其它并发insert的进程一般也正是需往最右边的这个index leaf block去insert数据,所以都要等待这个spliter进程完成并释放这个锁。(竞争更加激烈时,甚至会在branch block的split时产生)



解决思路:  



删除无用索引。为什么把这个显而易见的措施放到第一位呢,其实是有来由的。很多开发人员其实并不知道一个表上若创建过多索引会对DML产生影响,只知道创建索引对查询带来帮助,有些夸张的甚至会为一个表的每个列上都创建单列或组合索引。但是事实证明,经过DBA的采样监控,很多索引可能一年半载都不会被用到,那么还不删除这些索引更待何时?

将索引改造为hash分区索引。原理是可以打散并发操作的叶子节点。

将索引改造为反序索引。原理同上,因为是reverseindex,同样可以打散high key的叶子节点。

设置更小的block size,比如8k -> 4k - 2k。原理一样,因为更小的索引block里面存放的条目更少,理论上减少了两个不同会话同时访问同一个block的几率,进而减少了争用。但是这个方案其实会有其它副作用,除非其它方案都不能考虑,否则不建议这个方案。

重建索引。 为什么重建索引对这个问题能够带来帮助呢,因为重建索引后减少了索引的碎片,索引block变得更加紧凑,减少了index leaf block split时寻找空块的时间,提高了Oracle进行索引分裂时的效率,进而可以减少等待时间。

如果index contention的对象不是leaf block,而是rootblock,则可以考虑通过以下方法激活索引的root block分裂时的优化:

1)alter system set events '43822 trace name context forever,level1';

2)event 43822启用后,对于root block的split进行了增强, 不会超过5次的index block reclamation,Oracle就会去申请分配新块了。



背景知识:



Oracle在索引split时中寻找可复用的free block的过程如下:



Oracle不会一开始就让index segment申请分配新的空间(这会造成index segment的空间过度增长) ,而是到该index segment的其它地方搜索是否存在可用的Free Block, 这些Free Block的要求是status是75%-100% Free的, server process会扫描这些75%-100% Free的block 并确认这些block 实际上是100%空的, 如果找到100% Free Block则使用;如果没有则继续搜索, 直到所有候选block都被检查过,这个行为叫做 probes on index block reclamation。每次寻找空块并failed ,oracle就会增加这个统计指标: “failed probes on index block reclamation”。Oracle内部机制会控制要找多少次,不会去FULL SCAN所有index block的,failed超过一定次数后就会申请分配新的block。



不能重用的原因有2个:  



可能这个块不是100%free的,而是70% ~ <100% free的, 也就是找到的这个block上面还有几行或者多行索引记录,所以不能被重用来做split。

可能这个块上还有一些其它的active transaction,所以它重用不了。



在这个过程中,Oracle还有机会找到的block其实已经是索引结构中的一个非空block,但是Oracle只会在splittingand relinking to index structure之后才会发现这个block其实是illegal的选择,这个时候Oracle会回滚这个操作,这个统计记录在‘transaction rollback’ in v$sysstat,然后继续寻找另外一个block。



Oracle进行找空块的过程中,如果这些块不在内存中,会增加物理读,如果这些块还需要做延迟块清除或者还要回滚,则需要触发更多系统递归操作,可见,如果“failed probes”过多,split效率低下时,会直接导致index contention增加。



  3 enq: HW –contention


TABLE的High WaterMark(即高水位线)标识table segment中已用空间和未用空间的边界,具体来讲,HWM以上的block的状态是:unformattedand have never been used; HWM以下的block的状态是:Allocated, but currentlyunformatted and unused、 Formatted and contain data、Formatted and empty because the data was deleted。当HWM以下的block都无空闲空间可以使用时,Oracle会推进HWM来申请分配新的block到segment里面,而HW enqueue锁被用来管理推进HWM分配新空间时的串行操作。



显而易见,当高并发的insert发生时,甚至表中若有LOB字段时情况更糟,HWM的推进分配新空间的速度赶不上并发会话所需空间的速度时,就会发生在HW的enq上的等待。



解决思路: 



删除无用索引。

改造为hash分区表。同一时间的并发的空间分配需求会被打散到多个分区段上。

提前手工allocatenew空间(可以做成定期自动任务)。

主动shrink回收可以重用的空间,避免业务高峰期的自动allocate竞争。

设置表空间更大的UNIFORM SIZE,每次allocate更多extent到表的HWM之上,避免HWM剧烈时偶尔还会等在表空间的extent分配上。

确保使用ASSM (Automatic segment spacemanagement) tablespace。

隐含参数_bump_highwater_mark_count,可以控制HWM每次推进的block个数。但是设置该隐含参数应该得到Oracle的支持,而且对其它小表有负面影响。

检查IO子系统性能,有时候IO性能的变化也会导致空间分配操作缓慢,进而引发等待。

LOB段空间的频繁重回收,可能也会导致该竞争,针对LOB可以适当增加chunk,每次分配更多空间;也可以主动allocate 或shrink

另外针对使用ASSM表空间的LOB有一个Bug 6376915注意检查是否已applied fixed patch,并且要通过设置event来启用。此event用于控制1次LOB chunk回收操作时的chunk个数(default是1),进而可以减少HWM enq等待发生的次数。

EVENT="44951 TRACE NAME CONTEXT FOREVER, LEVEL < 1 -1024 >"



  4 enq: US –contention


这个等待事件通常说明会话在等待Undo Segment,注意等待的原因一般其实并不是因为UNDO TABLESPACE没有空间了,UNDO表空间不足会直接报ORA-30036(NOSPACEERRCNT)。



造成这个等待的典型场景有:



如果UNDO表空间是AUTOEXTEND的,则Oracle会自动调整undo retention,在尽量保持retention参数设定的undo block保留期的基础上,还会尽量满足一些长查询的读一致性需求。那么当这个特性发挥作用时,很多UNDO segment都被用在了长查询(MAXQUERYLEN)的支持上,当突发很多并发会话同时需要申请分配undo segment时,Oracle的回收机制(UNXPSTEAL)就会捉襟见肘。

大量active的undo block正在回滚、无法重用,可能是由于不久之前刚kill了一个长事务造成的。

也可能是虽然有空闲空间,但是由于应用重启、或者准点抢售类的应用导致高并发事务进入数据库后,短暂时间内需要将大量的undo seg从offline变成online,而smon没有处理得那么快,故可能出现短暂的大量enq:US-contention,这个时候通常会伴随大量的'latch: rowcache objects'(on DC_ROLLBACK_SEGMENTS)。我们的一个保险类系统在双11抢售时后台数据库就曾经出现过这个问题。



解决思路:



如果预期要做抢售活动,可以提前维护,设置_ROLLBACK_SEGMENT_COUNT为一个较高的值,保持一定数量的undosegments始终是online状态。

设置event让SMON不会自动将undo segment OFFLINE:

alter system set events '10511 trace name context forever, level1 ';

将_UNDO_AUTOTUNE临时设置为FALSE,以避免当UNDO TBS很空闲时,Oracle自动将undo retention调得很大,提前占用过多undo segments。

设置_HIGHTHRESHOLD_UNDORETENTION,虽然允许Oracle自动调整undo retention,但是为它设置一个天花板,不会过份地受MAXQUERYLEN的影响。



本文重要提示:



上述所有隐含参数的介绍,一方面是为了加深对Oracle相关管理机制的了解,另一方面都是在常规手段包括应用层调优的手段无法奏效的前提下的应急方案,在生产环境启用之前请得到Oracle原厂的确认与支持,而且在高峰期或问题应急解决后务必要取消隐参。



不要随意在生产环境使用隐含参数,这是一个最基本的数据库运维原则!



总结



上面这些问题的解决思路其实都是治标不治本的,这些优化措施可能能够帮助你的系统度过当前的系统波峰,但是随着时间的推移当更大的波峰出现时,问题还会再次发生。优化“对数据库的需求”带来的效果永远大于优化“数据库所能提供的资源”,虽然有时候优化“对数据库的需求”的成本投入更高,但是投入与产出一般都是成正比的。从这个意义上来讲,若应用能够合理控制并发、系统架构中引入缓存层、采用异步队列处理机制、优化DB模型设计以及SQL写法等,这才是解决问题的根本之道。



本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2016-10-08

[url]http://click.aliyun.com/m/21918/ [/url]

分享到:
评论

相关推荐

    让Oracle跑得更快 Oracle 10g性能分析与优化思路.part2.rar

    第1章 引起数据库性能问题的因素 1 1.1 软件设计对数据库的影响 1 1.1.1 软件架构设计对数据库性能的影响 1 1.1.2 软件代码的编写对数据库性能的影响 2 1.2 数据库的设计 8 1.2.1 oltp数据库 9 1.2.2 olap数据库 10 ...

    oracle 常见等待事件:影响性能-性能优化

    - **影响**:这种等待事件可能导致并发性能问题,尤其是在高DML活动的情况下。 - **优化建议**: - 优化SQL查询,减少不必要的DML操作。 - 考虑增加DBWR进程的数量,提高写入速度。 - 增加物理磁盘数量,以降低...

    ORACLE中查找定位表最后DML操作的时间小结

    1:使用ORA_ROWSCN伪列获取表最后的DML时间  ORA_ROWSCN伪列是Oracle 10g开始引入的,可以查询表中记录最后变更的SCN。然后通过SCN_TO_TIMESTAMP函数可以将SCN转换为时间戳,从而找到最后DML操作时SCN的对应时间。...

    oracle四大宝典之4:Oracle性能优化

    Oracle数据库是全球广泛使用的大型关系型数据库管理系统,其性能优化是DBA(数据库管理员)日常工作中至关重要的一环。本篇文章将深入探讨Oracle性能优化的各个方面,以帮助你掌握提升数据库效率的关键技巧。 一、...

    oracle操作数据-DML语句.pptx

    oracle操作数据-DML语句.pptx

    Oracle DDL,DML,DCL,TCL 基础概念

    ### Oracle DDL、DML、DCL、TCL 基础概念 #### DDL (Data Definition Language) 数据定义语言 数据定义语言(DDL)主要用于创建、修改或删除数据库对象,如表、索引、视图等。这些操作通常涉及数据库结构的变更。 ...

    oracle的1000个常见问题

    6. **性能优化**:Oracle提供了一系列工具和特性来优化数据库性能,如索引、分区、物化视图、SQL调优顾问等。理解如何分析SQL执行计划、监控数据库性能以及调整参数,有助于提升系统响应速度和处理能力。 7. **故障...

    Oracle Database 性能调整与优化 系列书.rar

    2. **In-Memory Option**:Oracle 12c引入了内存优化特性,通过将数据部分或全部加载到内存中,显著提升查询性能。 3. **Automatic Workload Repository (AWR)** 和 **ASH (Active Session History)**:利用这些工具...

    oracle 常用sql语句和常见问题

    为解决这些问题,需要理解Oracle的锁定机制、优化器行为、并发控制(如MVCC)以及日志和归档模式。通过监控V$视图和DBA视图,可以获取系统状态信息,帮助诊断和解决问题。此外,定期进行数据库维护,如统计信息收集...

    让Oracle跑得更快.pdf-Oracle 10g 性能分析与优化思路

    1. **查询优化器**:Oracle 10g的CBO(Cost-Based Optimizer)能根据统计信息选择最优执行计划。理解并利用索引、绑定变量、Hint等技巧可以改善查询性能。 2. **SQL Tuning Advisor**:这个内置工具能够对慢速SQL...

    oracle 优化 ppt教程

    Oracle优化PPT教程通常会涵盖一系列关键概念和技术,旨在提高数据库的运行效率,减少资源消耗,提升用户体验。以下是对这个教程可能涉及的知识点的详细解释: 1. **SQL优化**:这是Oracle数据库优化的核心,涉及到...

    oracleDML触发器1.ppt

    Oracle DML触发器是数据库管理系统Oracle中的一种特性,它允许开发者在特定的数据操作语言(DML)事件(如INSERT、UPDATE、DELETE)发生时自动执行一段PL/SQL代码。DML触发器主要用于实现数据完整性、业务规则的强制...

    让Oracle跑得更快 Oracle 10g性能分析与优化思路.part1.rar

    第1章 引起数据库性能问题的因素 1 1.1 软件设计对数据库的影响 1 1.1.1 软件架构设计对数据库性能的影响 1 1.1.2 软件代码的编写对数据库性能的影响 2 1.2 数据库的设计 8 1.2.1 oltp数据库 9 1.2.2 olap数据库 10 ...

    优化oracle

    4. **并行执行**:Oracle支持并行查询和并行DML操作,通过将任务分解为多个子任务并发执行,可以显著缩短大型操作的时间。设置合适的并行度(DOP)至关重要,过高可能导致资源争抢,过低则无法充分利用硬件资源。 5...

    Oracle DML触发器在数据库编程中的应用.pdf

    Oracle DML 触发器可以用来解决数据库编程中的一些常见问题,如实现数据的一致性、自动备份数据、执行复杂的业务逻辑等。例如,在一个电商平台中,可以使用 DML 触发器来自动更新订单状态、发送确认邮件、执行库存...

    oracle+plsql性能优化

    1. SQL语句编写注意问题:编写高质量的SQL语句是优化数据库性能的基础。例如,在where子句中避免使用isnull或isnotnull,因为这会阻止索引的使用。另外,对于联接列,即使联接值为静态值,优化器同样可能不会使用...

    oracle四大宝典.rar

    "Oracle四大宝典"涵盖了Oracle数据库系统的核心知识领域,包括SQL基础、基本管理、备份与恢复以及性能优化,这些都是Oracle DBA(数据库管理员)日常工作中不可或缺的技能。 1. Oracle SQL基础:SQL(Structured ...

    oracle管理应用工具和sql高级应用视频教程详细完整版

    第一部分:Oracle数据库安装与应用操作 第一章:oracle数据库简介 第二章:oracle安装 第三章:SQL基础知识 第四章:使用SELECT语句 第五章:数据的限定与排序 第六章:多表连接技术 第二部分:ORACLE SQL高级应用 ...

    oracle优化规则总汇

    1. **选用适合的优化器**:Oracle提供了三种优化器:RULE(基于规则)、COST(基于成本)和CHOOSE(选择性)。COST优化器是最常用的一种,它基于对象的统计信息来决定最佳执行计划。为了使用COST优化器,必须定期...

    Oracle OLAP DML Reference 11g Release 2 (11.2)-1640

    1. **语法和命令**:文档详细介绍了OLAP DML的语法结构和一系列命令,如定义维度(dimensions)、层次(hierarchies)、成员(members)以及计算(calculations)。这些命令允许用户进行数据建模,创建复杂的多维...

Global site tag (gtag.js) - Google Analytics