Oracle Acs资深顾问罗敏 老罗技术核心感悟:一个热门话题:数据库安全性

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

 

 

IT系统安全性,特别是数据库系统安全性,成了当下IT行业一个热门话题。本人曾听一位销售同事曾说:“在XX集团计划部,现在只要说申报与安全性相关的项目,准保一路绿灯。”

但也如另外一位同行所说:“安全性是说起来重要,做起来次要,忙起来不要。”无论重要也罢,次要、不要也罢。安全性特别是数据库安全性的确是值得深入探讨的话题,更具有广泛、全面实施空间的领域。

本章就将从数据库安全性需求及现状说起,再对Oracle数据库安全性解决方案进行一番介绍,然后结合某银行客户的安全性需求,制定安全性解决方案策略,最后系统描述了针对该银行的某关键业务系统的安全性评估情况。

数据库安全性需求及现状

IT 系统发展的一大趋势就是业务和数据的大集中。大集中之后的IT系统在系统的高可用性、高性能、可管理性、扩展性、安全性等方面,都将面临更严峻的挑战。具体在数据库安全性方面,在身份鉴别、数据存储层面、访问控制、安全审计和日志管理等诸多方面,IT系统都应得到进一步加强和加固,从而满足不断增长的数据安全管理和合规性需求。

目前,各类IT 系统安全事故的频发,例如客户资料流失等,不仅给各企业带来巨大损失,而且也造成非常不良的社会影响。于是,各行业领导都更高度重视数据库安全性。

安全性是涉及硬件、网络、操作系统、数据库软件、中间件软件、应用软件等各层面的系统工程。但是,据本人的了解,很多行业的安全性解决方案主要在服务器、网络等层面展开实施,例如某通信行业的4A认证体系。而在数据库层面,特别是Oracle数据库中,安全性实施的力度和强度并不充分。在大部分Oracle系统中,我们发现基本只采用了一些传统的安全性技术。例如:

  • 防范非法用户访问的身份认证,如操作系统层、数据库层的口令管理。
  • 基于数据库对象的防范非授权数据访问的权限控制。包括系统权限(system privileges)以及对象权限(object privileges)的设计,以及便于安全管理的角色(role)设计等。
  • 为实现记录级的安全控制,采用了视图(View)方式。
  • 关闭操作系统级不必要服务。如telnet、FTP服务等。

这种传统技术的安全保护强度是远远不够的,满足不了日益增长的安全性和合规性需求,导致数据库系统的各种安全风险暴露在外。例如,国内Oracle数据库几乎没有采取加密技术,特别是关键和敏感的客户资料全部是明文存储在数据库中;DBA权限过高,能访问所有应用数据;对重要操作行为缺乏审计等。

为什么在客户最为关注的Oracle数据库领域,客户反而没有充分实施安全解决方案呢?因为商务方面因素?的确Oracle大部分安全产品都需要单独购买。因为技术因素?的确Oracle大部分安全产品在实施方面还是有一定工作量和技术难度的,而且多数技术人员缺乏这方面实施经验。因为体制问题?的确很多行业明确规定安全性技术不能采用国外技术,只能采用国内自有技术体系。

但本人一次与一个国内重要客户DBA有关安全性的沟通内容,则耐人寻味,也有点啼笑皆非。

我问:“为什么你们的系统只在操作系统和网络层面实施安全性,而不在Oracle数据库内部加强安全性呢?”

 

DBA回答:“你们Oracle数据库现在就那么多Bug,就象个大马蜂窝,我们哪敢还去实施那么多安全性产品,去捅这个马蜂窝啊?你们Oracle更像个核反应堆,我们宁可在外面构筑铜墙铁壁,也不轻易碰你们这个核反应堆。”

我说:“再坚固的钢筋水泥也抵挡不住内部的核泄露啊,就象日本福岛核电站爆炸事故一样。”

DBA无语,但也未必赞同我的解释。

Oracle数据库安全性解决方案

从源头说起

在IT系统日益面临各种内外安全攻击和挑战的严峻环境下,为满足IT系统不断增长的安全需求,为符合各种安全性和合规性要求,Oracle数据库安全性技术和产品也在不断推陈出新,以下就是Oracle在不同版本下安全性技术不断发展的示意图:

 

anquan1

 

其实追根溯源从Oracle数据库诞生之日起,Oracle就非常重视数据库安全性。值得一提的是上图第一行所谓政府客户(Government Customer),实际上就是美国军方。Oracle数据库其实就是来源于当年的RSI公司(Oracle公司前身)为美国中央情报局设计开发的一套专用信息处理系统,因为该项目名称叫Oracle,所以RSI公司更名为寓意更深远、发音也更响亮的Oracle公司,并从此扬名天下。而在数据库安全领域,由于来源于政府和军方的缘故,Oracle具有先天优势,诸多产品如Oracle Label Security等也带有浓郁的美国政府特别是军方色彩。

从总体上而言,Oracle数据库是业界安全性方面最完备的数据库产品。在数据库安全性的国际标准中,Oracle通过了14项标准的测试,是所有数据库产品中通过安全性标准最多、最全面的产品。Oracle在C2级的操作系统上(如商用UNIX、VMS操作系统),不仅满足NCSC C2级安全标准,而且已经正式通过了NCSC C2标准的测试。在B1级的操作系统上不仅满足NCSC B1级安全标准,而且已经通过了NCSC B1级标准的测试。

 

数据库安全性全面解决方案

以下示意图从一个角度代表了Oracle数据库安全性全面解决方案:

 

anquan2

 

还记得前面一个DBA的话语吗?他把数据库安全性比喻成一个核反应堆。上图不就是非常形象的Oracle数据库安全性的核反应堆吗?

即在核反应堆的最外层,Oracle通过数据库防火墙(Database Firewall)产品构筑了一层坚固的钢筋水泥保护墙,用于阻断(Blocking)和记录(Logging)对数据库的恶意攻击。例如,监视数据库活动,防止未授权的数据库访问、SQL 注入、权限或角色升级、对敏感数据的非法访问等。
而在数据库内部,除传统的数据库用户、口令、角色、权限、审计等功能之外,在安全监控层、访问控制层和数据存储层面,均推出了功能更强、更符合安全性需求的产品和技术,使得Oracle数据库安全性得到全面加强。下图更清晰地展现了各层面的相关技术和产品:

 

anquan3

 

即在安全监控管理层,提供了对企业内部所有数据库的审计数据进行收集、监控、存储、检验和生成报表的集成化平台产品:Audit Vault;也提供了加强对历史数据的安全审计的产品:Total Recall;以及对企业数据库的配置进行集中管理的产品:Configuration Management。

在访问控制层面,不仅有传统的虚拟私有数据库(Virtual Private Database)技术,以及具有美国政府色彩的标签数据库(Oracle Label Security)技术,还有从10g以后发展的用于访问权限控制和职责分离(Seperation of Duty)的新产品:Oracle Database Vault。

在数据存储层面,既有对数据库内部敏感数据进行加密的高级安全产品(Oracle Advanced Security),也有对备份数据进行加密的Secure Backup技术,同时还有对敏感数据进行屏蔽或漂白,用于开发测试环境的Data Masking技术。

Oracle数据库安全性实施基本策略:快速原型法

由上可见,Oracle数据库安全性实施是涉及数据存储、访问控制和安全监控等多层面,由多项技术组成的庞大系统工程。为降低实施风险,特别是降低对应用程序的影响,建议采取如下图所示的快速原型法:

 

anquan4

 
即在全面分析安全性需求基础上,先采用Oracle数据库常规性安全性技术,并依赖现有IT技术框架,先满足数据库安全性基本需求,形成安全性原型系统。在原型系统基础上,根据安全需求的不断变化和分析,逐步采用更全面、深入的安全性产品和技术,丰富安全性原型系统,像滚雪球一样,最终逼近最终的安全性系统,全面满足数据库安全性需求。

 

17.3 某银行客户安全性需求和Oracle策略

以下我们通过对一个银行客户的安全性需求的详细分析,以及对应的Oracle安全性总体解决策略,来展现数据库安全性解决方案的全面性、系统性和复杂性:

 

类别 需求描述 Oracle解决方案策略
     
身份鉴别方 应对登录操作系统和数据库的用户进行身份标识和鉴别,严禁匿名登录 在Oracle数据库中,可采用审计技术,对登录客户身份进行记录。并可将ANONYMOUS用户状态保持为EXPIRED & LOCKED,严禁匿名登录。
为操作系统和数据库的不同用户分配不同的用户名 在Oracle数据库中,可采取如下安全措施:

l  严禁以IDENTIFIED EXTERNALLY方式创建用户

l  REMOTE_OS_AUTHENT参数设置为FALSE,禁止操作系统用户远程登录。

对服务器进行远程管理时,应采取加密通信方式,防止鉴别信息在网络传输过程中被窃听。 通过Oracle Advanced Security的Network Encrption功能实现Oracle Server和Client两段的网络加密传输。
首次登录应强制要求修改密码,应要求定期更改密码。 通过设置profile中的PASSWORD_LIFE_TIME、PASSWORD_GRACE_TIME等参数,并赋予相关用户,可实现定期更改密码需求。
不应允许用户间存在共用同一个访问帐户及密码的情况。 一方面,主要通过安全管理制度和流程控制加以保障。另一方面可根据需求,在技术上通过数据库、操作系统、网络身份认证,以及统一身份认证等技术和产品加以实现。
应明确禁止共享口令。 主要通过安全管理制度和流程控制加以保障。
对于新建的用户帐号,不同的帐号应设置不同的初始密码。 主要通过安全管理制度和流程控制加以保障。
应要求用户的口令长度最低为6位。 通过Oracle提供的缺省的口令复杂度检查函数:verification function,或者通过编写客户化口令复杂度检查函数,实现该功能。
应要求用户的口令必须包含字母和数字。 通过Oracle提供的缺省的口令复杂度检查函数:verification function,可实现该功能。
应设置用户口令的最长有效期为3个月。 通过设置profile中的PASSWORD_LIFE_TIME、PASSWORD_GRACE_TIME等参数,并赋予相关用户,可实现定期更改密码需求。
应确保对密码进行加密保护,不允许明文密码出现。 在Oracle数据库内部数据字典中,用户密码是加密的。为避免在应用程序、批处理和脚本中通过CONNECT命令中出现明文密码,可使用Oracle Wallet技术。
在收到用户重置密码的请求后,应先对用户身份进行核实在进行后续操作。 主要通过安全管理制度和流程控制加以保障。
访问控制方 根据“业务必需”原则授予不同用户为完成各自承担任务所需的最小权限,并在它们之间形成制约关系。 根据对不同应用系统的访问控制需求分析,一方面可通过常规的Oracle权限管理、角色管理等技术实现访问控制基本功能,另一方面,如果需要对内部职责进行更严格的划分和访问控制,例如防止DBA访问应用数据,应用系统管理员之间需要进行职责划分,则需要Database Vault技术才能满足相关需求,例如Realm的创建。
制定符合业务需求的访问控制制度,并形成访问控制策略的记录。 通过Database Vault技术,可实现应用系统管理员之间的职责划分,并对违反职责划分的访问行为进行记录和审计。
明确系统中每个用户的级别及权限。 根据对不同应用系统的访问控制需求分析,一方面可通过常规的Oracle权限管理、角色管理等技术为每个用户定义级别和权限。另一方面,如果需要对内部职责进行更严格的划分和访问控制,例如防止DBA访问应用数据,应用系统管理员之间需要进行职责划分,则需要Database Vault技术才能满足相关需求,例如Realm的创建。
操作系统和数据库特权用户需进行权限分离 主要通过安全管理制度和流程控制加以保障。
严格限制默认帐户的访问权限,重命名系统默认帐户,修改默认帐户口令。 在Oracle数据库安装完成之后,会自动安装管理帐户、非管理帐户、样本帐户等默认帐户,根据Oracle正常运行的需要,除SYSTEM、SYS、DBSNMP、SYSMAN、MGMT_VIEW之外,其它默认帐户均处于Expired and locked状态。

另外,Oracle还提供对默认帐户口令的检查功能。

及时删除多余的、过期的帐户,避免共享帐户的存在。 通过对Oracle帐户口令的有效管理,例如初始化参数和profile参数的有效设置,可将不合规的帐户设置为Expired and locked等状态。通过安全管理制度和流程控制,可及时删除这些帐户。
对操作系统用户、重要目录及文件进行权限设置。 由系统管理员对操作系统用户、重要目录及文件进行权限设置。在Oracle数据库层面,可对CRS Home、Oracle Base、Oracle Home等目录及文件系统进行权限设置和保护。
严格限制远程登录操作业务范围:实施严格的审批程序,对超出业务范围的操作请求应予以拒绝。 首先通过安全管理制度和流程控制加以保障,例如实施严格的审批程序,对超出业务范围的远程操作请求予以拒绝。

在常规技术方面,通过设置REMOTE_OS_AUTHENT参数为FALSE,禁止操作系统用户远程登录。

通过Database Vault的相关要素(IP地址、主机名等)和Command Rule的定义,对远程登录操作方式和操作内容进行限制。

仅在访问开始前激活远程登录端口,访问结束后应及时关闭。 主要通过安全管理制度和流程控制加以保障。
在进行远程登录操作时,不得将帐户信息通过远程网络存储到本地硬盘、软驱及其它外部存储介质。 一方面通过安全管理制度和流程控制加以保障,另一方面通过对应用程序进行规范化管理,禁止将在应用程序中将帐户信息存储到本地硬盘、软驱及其它外部存储介质。
远程登录操作应采用双因素验证方式,例如支持个人数字证书的VPN等。 通过配置SSL,以及使用Oracle Advanced Security的数字证书技术,可实现该功能。
建立远程登录操作文档记录,至少包括:远程访问人员、工作内容、持续时间,并要求监督人签字确认。 主要通过安全管理制度和流程控制加以保障。
保留对服务器的远程维护记录,对远程维护的内容和时间有严格的管理,完成远程维护后断开远程维护链路。 主要通过安全管理制度和流程控制加以保障。在技术方面,也可考虑通过Database Vault的审计功能,对远程维护操作进行记录。
安全审计方 审计范围应覆盖到服务器和重要客户端上的每个系统用户和数据库用户。 通过Oracle标准审计功能,可实现该功能。
审计范围包括重要用户行为,系统资源的异常使用和重要信息系统命令的使用等系统内重要的安全相关事件。 Oracle缺省审计功能就定义了若干重要行为的审计,例如DROP ANY TABLE、DROP USER、ALTER ANY TABLE、ALTER DATABASE 、ALTER SYSTEM等数十项操作的审计,因此建议打开Oracle缺省审计功能。另外,根据应用系统的需要,可定义更多的重大安全相关事件的审计。

通过Oracle资源管理器(Resource Manager),进行资源的合理规划和使用,可防止系统资源的异常使用。

审计记录包括时间、类型、访问者标识、访问对象标识和事件结果等。 Oracle数据库审计结果可存储在数据库内部或操作系统文件系统,并支持XML格式,以及支持支持Windows event viewer 和 SYSLOG。无论存储在何处,均能记录时间、类型、访问者标识、访问对象标识和事件结果等信息。
能够根据记录数据进行安全分析,并生成审计报表。 Oracle提供对审计数据的各种分析工具,例如对DBA_AUDIT_TRAIL、DBA_COMMON_AUDIT_TRAIL等视图的访问。特别是在Audit Vault中,内置了数十种审计报表,提供数据过滤、按条件值的突出显示、丰富多彩的图表功能等,并可创建客户化报表。另外,Audit Vault还具有多种分析模型,支持审计数据的商务智能。Audit Vault同时支持RAC和分区技术,为审计海量信息的分析工作提供了良好的技术基础架构。
保护审计记录,避免受到未预期的删除、修改或覆盖。 Oracle提供对标准审计记录(SYS.AUD$)的保护功能。

如果采用Audit Vault技术,可通过对Audit Vault服务器的数据库进行保护,例如Audit Vault服务器的RMAN备份恢复、访问控制等,可实现对审计数据的全方位保护。

日志管理方 日志系统应记录用户登录的时间、登录系统的方式、失败的访问尝试、系统管理员的操作、对系统日志的访问记录以及对其他涉及安全的访问记录。 在应用层面,需要应用程序能在日志系统中,记录用户登录的时间、登录系统的方式、失败的访问尝试等信息。

在系统层面,Oracle数据库、ASM、Listener、CRS各组件等均能在日志文件中记录重要事件和错误信息,供系统管理员和数据库管理员进行安全审计和故障诊断分析之用。

进一步,通过安全管理制度和流程控制加以保障。

对操作日志和处理日志进行定期检查,对其中可疑的记录进行分析审核。 Oracle数据库、Listener、CRS各组件等均能在日志文件中记录重要事件和错误信息,供系统管理员和数据库管理员进行安全审计和故障诊断分析之用。例如建议定期对数据库alert.log日志进行检查和分析,对诸如ORA-00600、ORA-7445等内部错误信息及时进行分析,并采取相应的解决措施。
严格控制对系统日志的访问,只有工作需要并通过审批的岗位人员才能查看系统日志。 在Oracle系统中,只有DBA组的用户,才能查看Oracle数据库、ASM和Listener日志文件,只有root用户才能查看CRS日志信息。因此,建议严格控制DBA组和root用户使用范围,从而达到对Oracle系统日志的访问控制需求。
设置日志服务器,方便日志的维护和统一管理 建议部署集中的日志服务器,并编写相关应用和脚本,定期将各服务器的日志传输和备份到该日志服务器中,实现日志的统一维护和管理。
及时将日志备份到日志服务器或安全介质内。 建议部署集中的日志服务器,并编写相关应用和脚本,定期将各服务器的日志传输和备份到该日志服务器中,并转储到磁带库等介质中,实现日志的统一维护和管理。
保证重要系统时钟时间保持同步。 保证重要系统时钟时间保持同步,不仅是日志管理方面需要,也是Oracle RAC系统的实施需要。建议部署集中的NTP时钟服务器,保证重要系统的时钟同步。

根据上述对该银行客户数据库安全性的需求分析,可总结如下特点:

  • 可通过Oracle常规安全性技术,满足大部分安全性需求。
  • 部分安全性需求需要通过Oracle 安全性高级技术和产品加以实现。例如数据库内部敏感数据加密、备份数据加密、网络传输加密等需求可通过Oracle Advanced Security,Secure Backup、Data pump加密等技术实现;访问控制需求可通过Oracle Database Vault等新技术加强实现;高级审计需求可通过集中审计平台(Oracle Audit Vault)加以实现。
  • 尚未提出数据屏蔽(Data Masking)、记录级访问控制(VPD、Oracle Label Security)、配置管理(Configuration Vault)、历史数据审计分析(Total Recall)等需求。

安全性需求需要通过安全管理制度和流程控制的改造和加强,加以保障。

 

从安全性评估开始

如前所述,IT系统安全性是涉及硬件、网络、操作系统、数据库软件、中间件软件、应用软件等各层面的系统工程。Oracle数据库安全性也是包括数据库防火墙、安全监控层、访问控制层和数据存储层面等诸多产品和技术。限于篇幅,本书无意介绍具体安全性产品和技术,也避免产品推广之嫌。另外,作为安全性系统工程,应先对现有系统数据库安全性展开评估,发现现有系统存在的各种安全风险和漏洞,然后再展开相对应的安全性加固工作。因此,本章下面将通过以一个银行系统为对象,展开安全性评估的介绍。

安全性评估内容

我们在参考了Oracle官方若干安全性评估文档、国内外若干行业的安全性评估标准、Oracle服务部门在国内若干实施案例,以及结合该银行系统特点,最终提出了如下的安全评估性分类和具体评估项目:

 

类别 评估项目 评估子项
     
数据库安装及配置安全性评估分析 缺省安全设置评估  
数据字典保护评估  
缺省表空间为系统表空间评估  
UNLIMITED表空间检查  
数据库软件版本显示评估 – 11g  
版本和安全补丁检查  
用户帐号安全性评估分析 缺省帐号保护评估  
缺省口令检查  
口令管理策略评估  
口令复杂度评估  
外部口令实施评估  
用户权限安全性评估分析 权限及角色评估  
系统权限评估  
对象权限评估  
SYSDBA角色访问控制检查  
Nologging表检查  
用户资源管理检查  
文件访问安全检查  
相关参数检查  
数据库网络传输安全性评估分析 网络连接安全性检查 动态管理Listener检查
Listener配置SSL检查
Listener配置口令检查
限制IP地址检查
连接超时检查
网络传输加密检查  
操作系统认证检查  
相关参数检查  
数据加密和访问控制评估分析 透明数据加密实施检查  
文件级加密检查  
应用级加密检查  
常规访问控制检查  
虚拟私有数据库(VPD)实施检查  
标签安全数据库(Label Security)实施检查  
数据屏蔽实施检查  
Oracle Database Vault实施检查  
数据库审计评估分析 标准审计评估  
FGA审计信息评估  
集中审计评估  
相关参数检查

 

评估方法和举例

该系统的详细评估报告长达近百页,以下我们从每个评估大类中挑选1个评估项目的详细内容,以舐读者,也让读者了解我们的评估过程,包括评估目的和内容、评估方法、评估结果、安全加固建议等。

  • 缺省安全设置
  • 评估目的和内容

10g 数据库在安装完成之后,在初始化参数和Profile参数方面将进行一些缺省的安全设置。通常情况下,应保持这些设置。

  • 评估方法

这些初始化参数和Profile参数包括:

 

参数名 缺省值 参数类型
     
AUDIT_TRAIL NONE 初始化参数
O7_DICTIONARY_ACCESSIBILITY FALSE 初始化参数
PASSWORD_GRACE_TIME UNLIMITED Profile参数
PASSWORD_LOCK_TIME UNLIMITED Profile参数
FAILED_LOGIN_ATTEMPTS 10 Profile参数
PASSWORD_LIFE_TIME UNLIMITED Profile参数
PASSWORD_REUSE_MAX UNLIMITED Profile参数
PASSWORD_REUSE_TIME UNLIMITED Profile参数
REMOTE_OS_ROLES FALSE 初始化参数

 

  • 评估结果

针对初始化参数检测方法如下:

SQL> show parameter;
NAME TYPE VALUE
------------------------------------ ---------------------- ----------------------
…
O7_DICTIONARY_ACCESSIBILITY boolean FALSE
audit_trail string NONE
remote_os_roles boolean FALSE
… 


上述初始化参数符合缺省安全设置。

针对Profile参数检测方法如下:

SQL> select * from dba_profiles;
PROFILE RESOURCE_NAME RESOURCE_TYPE LIMIT
-------------------- ---------------------------------------------------------------- ---------------- ----------DEFAULT COMPOSITE_LIMIT KERNEL UNLIMITED
DEFAULT SESSIONS_PER_USER KERNEL UNLIMITED
DEFAULT CPU_PER_SESSION KERNEL UNLIMITED
DEFAULT CPU_PER_CALL KERNEL UNLIMITED
DEFAULT LOGICAL_READS_PER_SESSION KERNEL UNLIMITED
DEFAULT LOGICAL_READS_PER_CALL KERNEL UNLIMITED
DEFAULT IDLE_TIME KERNEL UNLIMITED
DEFAULT CONNECT_TIME KERNEL UNLIMITED
DEFAULT PRIVATE_SGA KERNEL UNLIMITED
DEFAULT FAILED_LOGIN_ATTEMPTS PASSWORD 10
DEFAULT PASSWORD_LIFE_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_REUSE_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_REUSE_MAX PASSWORD UNLIMITED
DEFAULT PASSWORD_VERIFY_FUNCTION PASSWORD NULL
DEFAULT PASSWORD_LOCK_TIME PASSWORD UNLIMITED
DEFAULT PASSWORD_GRACE_TIME PASSWORD UNLIMITED
PROFILE_NEW COMPOSITE_LIMIT KERNEL DEFAULT
PROFILE_NEW SESSIONS_PER_USER KERNEL DEFAULT
PROFILE_NEW CPU_PER_SESSION KERNEL DEFAULT
PROFILE_NEW CPU_PER_CALL KERNEL DEFAULT
PROFILE_NEW LOGICAL_READS_PER_SESSION KERNEL DEFAULT
PROFILE_NEW LOGICAL_READS_PER_CALL KERNEL DEFAULT
PROFILE_NEW IDLE_TIME KERNEL DEFAULT
PROFILE_NEW CONNECT_TIME KERNEL DEFAULT
PROFILE_NEW PRIVATE_SGA KERNEL DEFAULT
PROFILE_NEW FAILED_LOGIN_ATTEMPTS PASSWORD UNLIMITED
PROFILE_NEW PASSWORD_LIFE_TIME PASSWORD DEFAULT
PROFILE_NEW PASSWORD_REUSE_TIME PASSWORD DEFAULT
PROFILE_NEW PASSWORD_REUSE_MAX PASSWORD DEFAULT
PROFILE_NEW PASSWORD_VERIFY_FUNCTION PASSWORD DEFAULT
PROFILE_NEW PASSWORD_LOCK_TIME PASSWORD DEFAULT
PROFILE_NEW PASSWORD_GRACE_TIME PASSWORD DEFAULT

SQL> select username,profile from dba_users;

USERNAME PROFILE
------------------------------------------------------------ --------------------
PROPS DEFAULT
MONITOR PROFILE_NEW
EXPUSER PROFILE_NEW
BOCRPT PROFILE_NEW
PERFSTAT DEFAULT
ORACLE_OCM DEFAULT
DIP DEFAULT
TSMSYS DEFAULT
DBSNMP DEFAULT
WMSYS DEFAULT
SYSTEM DEFAULT
OUTLN DEFAULT
BOCNET PROFILE_NEW
SYS DEFAULT



可见,该系统的MONITOR、EXPUSER、BOCRPT、BOCNET等用户采用的PROFILE为PROFILE_NEW,而PROFILE_NEW的FAILED_LOGIN_ATTEMPTS设置为UNLIMITED,不符合缺省安全设置。

  • 安全加固建议

建议执行如下命令,将PROFILE_NEW的FAILED_LOGIN_ATTEMPTS设置为缺省值10:

SQL> alter profile PROFILE_NEW limit FAILED_LOGIN_ATTEMPTS 10;

上述加固建议将使得客户尝试登录的错误次数上限为10,加强防范恶意用户攻击能力。

该安全加固措施实施难度小,不会产生其它风险。

  • 口令复杂度评估
  • 评估目的和内容

按照安全规范,用户的口令设置必须符合相关复杂性管理的相关规定。例如:

  • 口令不能等同于用户名
  • 长度必须为8 – 30位
  • 必须包含数据、字母,以及_、$、#等特殊字符
  • 必须使用大小写字母(11g)
  • 不得包含有意义的单词
  • 评估方法

可进行如下检查:

SQL> select * from dba_profiles where resource_name=’PASSWORD_VERIFY_FUNCTION’;

 

如果为空或DEFAULT VALUE,则系统没有设置口令复杂度检查。

  • 评估结果

上述语句检查结果如下:

 

PROFILE RESOURCE_NAME RESOURCE_TYPE LIMIT
-------------------- ---------------------------------------------------------------- ---------------- ----------DEFAULT PASSWORD_VERIFY_FUNCTION PASSWORD NULL
PROFILE_NEW PASSWORD_VERIFY_FUNCTION PASSWORD DEFAULT



可见,DEFAULT和PROFILE_NEW均没有进行口令复杂度检查。

  • 安全加固建议

Oracle已经提供了一个脚本utlpwdmg.sql,通过运行该脚本将创建口令复杂度检查函数verify_function,并为DEFAULT profile赋予该口令复杂度检查函数。

SQL> @?/rdbms/admin/utlpwdmg.sql;
SQL> select * from dba_profiles where resource_name='PASSWORD_VERIFY_FUNCTION';



可修改该脚本,为PROFILE_NEW设置口令复杂度检查。

对管理用户如SYS/SYSTEM的口令管理实施难度很小。但是,口令管理各参数涉及业务和按管理需求,另外,该系统各应用程序中直接写入了口令,因此,加强口令管理的难度较大。

  • SYSDBA角色访问控制检查
  • 评估目的和内容

根据安全管理规范,一方面可限制SYSDBA角色从远程登录,另一方面在本地以’/as sysdba’登录时,需要输入口令。

为实现上述目标,可将sqlnet.ora文件中的SQLNET.AUTHENTICATION_SERVICES设置为NONE。

  • 评估方法

检查sqlnet.ora文件中的SQLNET.AUTHENTICATION_SERVICES。

  • 评估结果

以下是该系统的sqlnet.ora文件内容:


# sqlnet.ora.netdb1 Network Configuration File: /oracle/app/oracle/product/10.2.0/db/network/admin/sqlnet.ora.netdb1
# Generated by Oracle configuration tools.

NAMES.DIRECTORY_PATH= (TNSNAMES)



可见,该系统目前没有进行SYSDBA角色访问控制。
 加固实施建议
可在sqlnet.ora文件进行如下配置:
SQLNET.AUTHENTICATION_SERVICES = (none)

该安全加固措施难度很小,并可以限制未获得密码的人员不能以SYSDBA身份登录数据库,但可能会对数据库日常管理造成一定影响。

  • 限制IP地址检查
  • 评估目的和内容

Oracle可在sqlnet.ora文件中,对tcp.validnode_checking、tcp.excluded_nodes、tcp.invited_nodes等参数进行设置,从而达到指定或限制IP地址访问数据库的目的。

  • 评估方法

检查sqlnet.ora文件是否包含类似如下的配置:

 

tcp.validnode_checking = YES

tcp.excluded_nodes = {list of IP addresses}

tcp.invited_nodes = {list of IP addresses}

其中tcp.validnode_checking = Yes将打开IP地址检查功能,tcp.excluded_nodes为禁止访问数据库的IP地址列表,tcp.invited_nodes为允许访问数据库的IP地址列表。

  • 评估结果

以下是该系统的sqlnet.ora文件内容:

# sqlnet.ora.netdb1 Network Configuration File: /oracle/app/oracle/product/10.2.0/db/network/admin/sqlnet.ora.netdb1
# Generated by Oracle configuration tools.

NAMES.DIRECTORY_PATH= (TNSNAMES)

可见,该系统目前没有进行IP访问地址的限制。

  • 安全加固建议

如果根据网络管理规范,需要加强访问数据库的网络连接安全,可直接在sqlnet.ora文件中手工增加上述配置。例如只允许指定WAS服务器、管理监控终端等访问数据库。

但需要重新启动Listener,应用也需要重新连接Oracle数据库服务器。

  • 透明数据加密实施检查
  • 评估目的和内容

为加强数据本身存储的安全性,Oracle提供了多种透明加密技术(Transparent Data Encryption),并可在表、字段、表空间(11g)等不同级别进行加密处理。对帐户信息、信用卡号等敏感和关键字段进行加密,将有效提高数据安全性,并满足日益增加的安全性和合规性要求。

  • 评估方法
执行如下脚本可查询当前数据库已经进行加密处理的字段:

SQL> select * from DBA_ENCRYPTED_COLUMNS;


在11g中,执行如下脚本可查询当前数据库已经进行加密处理的表:


SQL> select * from V$ENCRYPTED_TABLESPACES;

 

 

  • 评估结果

检查结果如下:

 

SQL> select * from DBA_ENCRYPTED_COLUMNS;

no rows selected


即该系统目前没有采取Oracle的数据透明加密技术。

  • 安全加固建议

为了提高数据安全性,特别是实现对关键而敏感数据的存储加密,建议尽快制定完备的数据存储加密实施计划。

为实现Oracle数据存储加密,需要采购Oracle Advanced Security选项,同时对数据库性能、存储空间略有影响。而且加密技术实施涉及安全需求分析,方案设计、测试和上线等工作,因此工作量和难度均较大。

  • 标准审计评估
  • 评估目的和内容

审计的主要功能是实现操作留痕,以此来发现系统可能存在的安全漏洞,辅助管理员及时修补,防止系统未来继续受到类似侵害。标准审计包含以下几种类型:

  • 语句审计:对一类特定数据库结构或对象执行的一组相关语句进行审计,而不针对某个数据库结构或对象,其包含对DDL和DML两类语句的审计;语句审计面向所有数据库用户或某些特定用户的操作。
  • 权限审计:审计使用了系统权限的语句,只有当用户执行的语句使用了系统权限,才会被审计;权限审计面向所有数据库用户或某些特定用户的操作。
  • 对象审计:审计所有具有对象权限执行的相关SELECT和DML语句,控制这些对象权限的GRANT和REVOKE语句也会被审计;引用TABLE、VIEW、SEQUENCE、独立的Procedure、Function和Package等语句可以被审计;而引用CLUSTER、INDEX、DB LINK 、SYNONYM的语句无法被直接审计,但可以审计对应的基表。对象审计只面向所有数据库用户。
  • 网络审计:可以揭示一些非连接错误的原因,例如加密配置的错误。
  • 管理用户审计:审计以SYSDBA/SYSOPER身份连接数据库的用户。

标准审计提供的功能可以粗粒度地、在数据库对象一级审计所有数据库用户或特定用户执行的语句。为正常操作、可疑操作提供了统计、追逐手段。

  • 评估方法

查看初始化参数和相关视图确认当前的标准审计配置情况。例如:

SQL> show parameter audit

SQL> select count(*) from sys.aud$;

SQL> select * from ALL_DEF_AUDIT_OPTS;

SQL> select * from DBA_STMT_AUDIT_OPTS

SQL> select * from DBA_PRIV_AUDIT_OPTS;

SQL> select * from DBA_OBJ_AUDIT_OPTS;

SQL> select * from DBA_AUDIT_TRAIL;

SQL> select * from DBA_AUDIT_OBJECT;

SQL> select * from DBA_AUDIT_SESSION;

SQL> select * from DBA_AUDIT_STATEMENT;

SQL> select * from DBA_AUDIT_EXISTS;


  • 评估结果

检查结果如下:

SQL> show parameter audit

NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
audit_file_dest string /oracle/app/oracle/admin/oraDB
 /adump
audit_sys_operations boolean FALSE
audit_syslog_level string
audit_trail string NONE

SQL> select count(*) from sys.aud$;

COUNT(*)
----------
 0

select * from ALL_DEF_AUDIT_OPTS;
select * from DBA_STMT_AUDIT_OPTS;
select * from DBA_PRIV_AUDIT_OPTS;
select * from DBA_OBJ_AUDIT_OPTS;
select * from DBA_AUDIT_TRAIL;
select * from DBA_AUDIT_OBJECT;
select * from DBA_AUDIT_SESSION;
select * from DBA_AUDIT_STATEMENT;
select * from DBA_AUDIT_EXISTS;
select * from DBA_AUDIT_POLICIES;
select * from DBA_FGA_AUDIT_TRAIL;

All no rows selected



可见,该系统目前没有进行任何标准审计操作。

  • 安全加固建议

建议针对不同的数据访问监控需求,合理使用标准审计技术。

审计操作涉及审计需求分析,方案设计、测试和上线工作,工作量和难度较大。

安全性评估总结

  • 安全性问题汇总

以下是针对该系统所发现安全性问题的汇总:

 

评估类别 评估项 问题描述 影响程度 解决方式建议 难度及风险 备注
             
数据库安装及配置 缺省安全设置 PROFILE_NEW的FAILED_LOGIN_ATTEMPTS设置为UNLIMITED 将PROFILE_NEW的FAILED_LOGIN_ATTEMPTS设置为缺省值10 小,无风险  
UNLIMITED表空间检查 BOCNET、BOCRPT具有UNLIMITED TABLESPACE权限 将不需要UNLIMITED TABLESPACE权限的用户,在指定表空间设置quota 中等难度和风险  
应用级用户对SYSTEM和SYSAUX表空间没有将使用限额设置为0 将应用级用户对SYSTEM和SYSAUX表空间的使用限额设置为0 小,无风险  
版本和安全补丁检查 10.2.0.4版本旧,而且没有实施PSU补丁和CPU补丁 升级到10.2.0.5,以及相应的PSU补丁和小补丁 大,有一定风险 参照版本和补丁分析报告
用户帐号安全性 缺省帐号保护评估 SYSTEM用户状态为LOCKED(TIMED),无法访问SYSTEM用户 将 SYSTEM用户恢复为OPEN状态 小,无风险  
缺省口令检查 处于OPEN状态的PERSTAT为缺省口令 修改缺省口令

删除PERFSTAT用户

小,无风险  
口令管理策略评估 口令管理没有严格的安全限制 根据安全管理需要,设置不同的口令管理参数 大,有一定风险 需要采购Oracle Advanced Security产品
口令复杂度评估 没有设置口令复杂度检查 运行Oracle提供的utlpwdmg.sql 大,有一定风险 涉及应用程序的改造
外部口令实施评估 没有使用外部口令 通过Oracle高级安全产品,实施外部口令管理 大,有一定风险 需要采购Oracle Advanced Security产品
用户权限安全性 权限及角色评估 角色激活无口令认证 为角色激活增加口令认证 大,有一定风险 重建角色,并重新为用户分配角色
  BOCNET、BOCRPT帐号被赋予了DBA角色 确认是否可以收回 小,有一定风险  
系统权限评估 BOCNET、BOCRPT具有UNLIMITED TABLESPACE权限 将不需要UNLIMITED TABLESPACE权限的用户,在指定表空间设置quota 中等难度和风险  
SYSDBA角色访问控制 没有进行SYSDBA角色访问控制 sqlnet.ora文件进行如下配置:

SQLNET.AUTHENTICATION_SERVICES = (none)

小,无风险  
Nologging表检查 存在大量设置为nologging方式的表 与应用开发团队确认这些nologging表 大,有一定风险  
用户资源管理检查 没有实施用户资源管理技术 根据不同用户级别资源管理需求,实施资源管理技术 大,有一定风险  
数据库网络传输安全性 网络连接安全性检查 没有进行SSL配置 实施SSL配置 大,有一定风险 需要采购Oracle Advanced Security产品
没有进行IP访问地址的限制 实施IP访问地址的限制,例如只允许指定WAS服务器、管理监控终端等访问数据库。 小,有一定风险 重新启动Listener,应用也需要重新连接
没有进行连接超时检查 实施连接超时检查 小,有一定风险 重新启动Listener,应用也需要重新连接
网络传输加密检查 服务器与客户端之间传递数据采用明文方式 Net8通讯等实施SSL加密传输 大,有一定风险 需要采购Oracle Advanced Security产品
数据加密和访问控制 透明数据加密 没有实施Oracle的数据透明加密技术 实施Oracle的数据透明加密技术 大,有一定风险 需要采购Oracle Advanced Security产品
文件级加密 没有采用Secure Backup技术 实施Secure Backup技术 大,有一定风险 需要采购Oracle Advanced Security产品
Data Pump没有采用加密口令技术 实施Data Pump加密口令技术 大,有一定风险 需要采购Oracle Advanced Security产品
应用级加密检查 采用应用级数据加密技术 为实现对数据存储更灵活的加密,建议考虑应用级数据加密技术的实施 大,有一定风险 需要采购Oracle Advanced Security产品
常规访问控制检查 BOCNET、BOCRPT等普通用户对保存在SYS用户中的REPORT_DIR、EXPDP_DIR等表有访问权限 与该系统应用团队沟通,如果不合理,建议改进。 中,风险待估  
  Recyclbin没有进行定期删除 DBA定期进行Recyclbin清理 小,有一定风险  
  普通用户对其他普通用户对象的访问权限较多 如无访问必要,建议收回 大,有一定风险 与应用紧密相关
虚拟私有数据库(VPD)实施检查 目前没有采用VPD技术 实施VPD技术 大,有一定风险  
标签安全数据库(Label Security)实施检查 没有采用Label Security技术 实施Label Security技术 大,有一定风险 该产品为Oracle安全产品选项
数据屏蔽实施检查 没有实施Data Masking产品 实施Data Masking产品 大,有一定风险 该产品为Oracle安全产品选项
Oracle Database Vault实施检查 没有实施Oracle Database Vault产品 实施Oracle Database Vault产品 大,有一定风险 该产品为Oracle安全产品选项
数据库审计 标准审计评估 没有进行任何标准审计操作 针对不同的数据访问监控需求,合理使用标准审计技术 大,有一定风险  
FGA审计信息评估 没有实施FGA审计操作 针对不同的数据访问监控需求,合理使用FGA审计技术 大,有一定风险  
集中审计评估 未实施Audit Vault产品 针对不同的数据访问监控需求,合理使用Audit Vault集中审计技术 大,有一定风险 该产品为Oracle安全产品选项
  • 安全性评估汇总
  • 虽然该系统存在一定的安全性问题,但在总体上,特别是在不涉及Oracle高级安全选项的常规安全性配置方面,并没有特别严重的安全性问题。
  • 该系统版本较低,是需要急待改进的问题。
  • 该系统目前存在的大部分安全问题的解决,一方面都涉及到Oracle安全性相关高级产品的采购和实施。例如:Oracle Advanced Security、Data Masking、Oracle Database Vault、Oracle Audit Vault等。另一方面与应用紧密相关,需要与应用开发团队全面合作,共同进行加固方案的设计和实施。
  • Oracle安全性相关高级产品的实施,都需要进行安全需求分析、方案设计、测试和上线等工作,工作量和难度均较大。

 

本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database Security Guide》 这是Oracle联机文档中有关数据库安全性的权威文档,涉及数据层、访问控制层、审计层等多个层面的产品和技术。
2. My Oracle Support 《Security Checklist: 10 Basic Steps to Make Your Database Secure from Attacks (Doc ID 1545816.1)》 “10件防止数据库遭受攻击的基本措施”―――― 看标题就很诱人。
3. My Oracle Support 《Security Vulnerability FAQ for Oracle Database and Fusion Middleware Products (Doc ID 1074055.1)》 “Oracle数据库和中间件安全性和易攻击性常见问题解答”――――题目同样诱人。
4. My Oracle Support 《All About Security: User, Privilege, Role, SYSDBA, O/S Authentication, Audit, Encryption, OLS, Database Vault, Audit Vault (Doc ID 207959.1)》 有关用户、权限、角色、审计、加密等多个Oracle数据库安全性产品和技术的资料集结地。
5. My Oracle Support 《System Change Number (SCN), Headroom, Security and Patch Information (Doc ID 1376995.1)》 什么叫SCN?Headroom?该文档给出了官方解释,包括SCN和Headroom概念、工作原理,以及可能遇到的Bug和patch等。
6. My Oracle Support 《UNIX: Checklist for Resolving Connect AS SYSDBA Issues (Doc ID 69642.1)》 当以SYSDBA方式连接数据库时,可能发生ORA-03113、ORA-01031、ORA-01034等多种错误。该文档给出了这些错误的发生原因和解决办法。

 

 

 

 

Oracle ACS资深顾问罗敏 老罗技术核心感悟:关于数据库碎片管理

 

关于数据库碎片管理

 

各行各业的数据库容量急剧增长是目前IT系统一个普遍的现象,除去正常业务增长因素,大量碎片的存在是导致这种现象的重要因素。其实,大多数DBA们都深知碎片的存在和带来的危害,但大家却很少进行计划性、系统化的碎片整理。为什么呢?通常的原因是:不了解如何评估碎片的严重性;不知道Oracle提供了哪些技术手段;业务系统高可用性太高,也不敢以在线方式进行碎片的整理… …

本章就将围绕碎片管理这个话题展开专题讨论,包括在表空间、表、索引等不同级别和对象方面进行碎片指标的介绍,以及Oracle公司提供的多种碎片整理技术,最后将结合一个案例,介绍碎片管理的实施过程。

希望本章能为大家在数据库空间管理方面起到一个抛砖引玉的作用,更希望各行各业有更多的客户能将碎片管理作为数据库运维中一项制度化、常态化的工作。

 

数据库空间碎片问题

 

10GB被压缩到1GB!

 

 

若干年前作为Oracle技术顾问,本人非常有幸参与了国家某基础数据库的建设工作。当2012年再次拜访该客户时,我向客户DBA询问了该库的最新容量,他告诉我已经增长到十几个TB了,而且说已经在考虑如何对数据库进行历史数据迁移等瘦身计划。凭借经验,我认为除了正常的业务高速增长因素之外,数据库一定存在大量碎片。于是,我让客户先查查碎片情况,别着急马上实施工程庞大的数据库瘦身计划。

果不其然,几天之后,突然接到客户DBA电话:

“罗老师,我们按你推荐的方法对系统进行了一次碎片分析,并对一张10GB的大表通过重建方式,进行了碎片整理,结果被压缩到1GB!”。

“哈哈,按照这个压缩比例,你们的库可能被压到几个TB,甚至1个TB”。我在电话里也不无得意道。

是的,根据个人对国内多个行业Oracle数据库系统的观察,大多数核心数据库空间在急剧膨胀。例如,以下就是某银行一个关键业务系统数据库空间增长情况和趋势分析:

 

 

suipian1

 

排除正常业务增长因素,大量碎片的存在是空间急剧膨胀的重要根源。而现状是大多数DBA们很少进行系统的碎片分析,更没有计划性、周期性、常态化地进行空间碎片整理了。于是,我们听到的更多是空间不断增长和性能下降的抱怨,还有每年不断增加的存储采购。

何谓碎片

客户经常会遇到这种问题:明明 dba_free_space等视图显示数据库有足够的空闲空间,但却遇到ora-1547、ora-1562、ora-1653等表示无法分配空间或空间不足的错误。通常而言,这就是遇到空间碎片问题了。

Oracle在表空间、表、索引等不同层面和对象方面都可能存在碎片。在表空间级,如果频繁进行创建、删除表和索引等DDL操作,会导致大量碎片。表空间级碎片通常有两种:一种是不连续的空闲空间,导致Oracle无法分配一个完整的extent,Oracle也无法对这种不连续的空闲空间进行合并(coalesce)操作。另一种是空闲空间相邻,Oracle SMON进程会定期进行合并(coalesce)操作,在一定程度上可以缓解碎片问题。

 

在表级,大量DML操作会导致大量碎片,特别是进行大量Delete操作之后,又进行大量Insert 操作,很容易产生碎片,这是因为Oracle的Delayed block cleanout特性所导致。所谓Delayed block cleanout特性,是指当对表进行DML操作之后,Oracle只会先将相应的数据块标识为修改状态,而不会立即真正在磁盘上执行这些操作,除非马上访问(Select)这些数据块。这样,当表的记录被Delete,空间可能还没有被真正释放,马上进行Insert操作,Oracle将不会将新记录插入到刚被Delete记录所占的空间,而是插入到新的extent之中,这样将导致表的空间急剧增长。

 

同样地,大量DML操作也会导致索引产生大量碎片,而且在原理上索引更容易产生碎片。例如,由于无法指定索引的PCTUSED属性,这样当一条记录被删除后,Oracle并不会重用该记录所对应的索引空间。而且针对update操作,Oracle在索引上实际是进行Delete和Insert和操作,非常容易产生碎片。

 

空间碎片带来的问题和风险

  • 空间浪费

首先,碎片带来的问题是空间的无谓浪费,导致客户在存储设备方面进行了很多不必要的扩容和投入。例如,根据我们的初步估算,如果技术方案和实施手段得当,上述银行系统至少能节省出1/3以上的空间。

  • 访问效率的低下

无论是联机交易应用,还是批处理应用,大量碎片的存在,都将导致访问效率低下,甚至极度恶化。如果是联机交易应用,由于索引碎片较多,将导致索引访问效率下降,极大影响以索引访问为主的联机交易应用性能。如果是后台批处理应用,由于表的碎片较多,特别是碎片表的高水位标志(HWM)较高,而实际记录数并不多,将导致以全表扫描、全分区扫描为显著特征的批处理应用效率低下,并且浪费大量内存和I/O资源。大量碎片的存在,也将导致RMAN备份和逻辑备份、统计信息采集等后台作业效率低下。

 

空间管理需求分析

如何有效加强各系统的空间管理,特别是合理运用Oracle相关技术有效解决碎片问题,将不仅是数据库系统目前急待解决的问题,而且也是客户运维团队一项长期、艰巨的工作任务。

以下是我们在日常工作中与客户运维团队的沟通中,了解到客户针对空间管理,特别是在碎片管理方面提出的需求:

  • 合理评估空间问题

首先,希望Oracle服务团队在表空间、表、索引等不同层面和不同数据对象方面,提供评估空间问题,特别是碎片问题的合理方法、指标和评估标准。

  • 合理选择技术方案

其次,客户希望Oracle服务团队在Oracle众多空间管理,特别是碎片管理方面的技术手段中,结合实际系统特点,在技术有效性、对生产系统影响、技术成熟性等方面进行综合平衡,提出针对表空间、表、索引等不同层面和不同数据对象的碎片管理技术方案。

  • 合理的实施计划

在上述技术方案基础上,根据客户系统特点,制定合理的的实施计划,以适当的资源投入,达到既合理解决空间问题,同时又能将对生产系统的影响降至最小等目的。

  • 实施效果评估分析

在上述实施计划基础上,选择典型系统实施之后,希望Oracle服务团队能进行空间管理,特别是碎片整理的整体效果评估,以及具体的量化比较和分析,评估内容包括:碎片整理的有效性、技术运用手段的合理性、对生产系统的影响等内容。

  • 空间管理的制度化和常态化建议

随着业务的不断发展,数据库系统出现空间问题,特别是碎片问题是不可避免的问题。客户希望Oracle服务团队在现有空间管理技术方案和实施基础上,不断完善技术方案,并总结实施经验,在数据库系统的空间管理制度化和常态化方面,提供建设性的建议,协助客户建立空间管理的一整套制度和方法。

 

碎片评估方法

表空间碎片评估方法

事实上,Oracle提供了多种方法和计算公式来评估表空间碎片情况。以下介绍几种:

 

 

  • FSFI值

 

以下语句将按表空间计算FSFI(Free Space Fragmentation Index)值:

 

 

select a.tablespace_name,
       sqrt(max(a.blocks) / sum(a.blocks)) * (100 / sqrt(sqrt(count(a.blocks)))) FSFI
  from dba_free_space a, dba_tablespaces b
  where a.tablespace_name = b.tablespace_name
 and b.contents not in ('TEMPORARY','UNDO')
 group by a.tablespace_name
 order by FSFI;

 

如果FSFI值 < 30%,则该表空间的碎片较多。

  • 按表空间显示连续的空闲空间

运行如下的Oracle公司提供的脚本,可按表空间显示连续的空闲空间:

========

Script : tfstsfgm

========

SET ECHO off 

REM NAME:TFSTSFRM.SQL 

REM USAGE:"@path/tfstsfgm" 

REM ------------------------------------------------------------------------ 

REM REQUIREMENTS: 

REM    SELECT ON DBA_FREE_SPACE 

REM ------------------------------------------------------------------------ 

REM PURPOSE: 

REM    The following is a script that will determine how many extents 

REM    of contiguous free space you have in Oracle as well as the  

REM total amount of free space you have in each tablespace. From  

REM    these results you can detect how fragmented your tablespace is.  

REM   

REM    The ideal situation is to have one large free extent in your  

REM    tablespace. The more extents of free space there are in the  

REM    tablespace, the more likely you  will run into fragmentation  

REM    problems. The size of the free extents is also  very important.  

REM    If you have a lot of small extents (too small for any next   

REM    extent size) but the total bytes of free space is large, then  

REM    you may want to consider defragmentation options.  

REM ------------------------------------------------------------------------ 

REM DISCLAIMER: 

REM    This script is provided for educational purposes only. It is NOT  

REM    supported by Oracle World Wide Technical Support. 

REM    The script has been tested and appears to work as intended. 

REM    You should always run new scripts on a test instance initially. 

REM ------------------------------------------------------------------------ 

REM Main text of script follows: 




create table SPACE_TEMP (   

 TABLESPACE_NAME        CHAR(30),   

 CONTIGUOUS_BYTES       NUMBER)   

/   




declare   

  cursor query is select *   

          from dba_free_space   

                  order by tablespace_name, block_id;   

  this_row        query%rowtype;   

  previous_row    query%rowtype;   

total           number;   




begin   

  open query;   

  fetch query into this_row;   

  previous_row := this_row;   

  total := previous_row.bytes;   

  loop   

 fetch query into this_row;   

     exit when query%notfound;   

     if this_row.block_id = previous_row.block_id + previous_row.blocks then   

        total := total + this_row.bytes;   

        insert into SPACE_TEMP (tablespace_name)   

                  values (previous_row.tablespace_name);   

     else   

        insert into SPACE_TEMP values (previous_row.tablespace_name,   

               total);   

        total := this_row.bytes;   

     end if;   

previous_row := this_row;   

  end loop;   

  insert into SPACE_TEMP values (previous_row.tablespace_name,   

                           total);   

end;   

.   

/   




set pagesize 60   

set newpage 0   

set echo off   

ttitle center 'Contiguous Extents Report'  skip 3   

break on "TABLESPACE NAME" skip page duplicate   

spool contig_free_space.lis   

rem   

column "CONTIGUOUS BYTES"       format 999,999,999,999   

column "COUNT"                  format 999999   

column "TOTAL BYTES"            format 999,999,999,999   

column "TODAY"   noprint new_value new_today format a1   

rem   

select TABLESPACE_NAME  "TABLESPACE NAME",   

       CONTIGUOUS_BYTES "CONTIGUOUS BYTES"   

from SPACE_TEMP   

where CONTIGUOUS_BYTES is not null   

order by TABLESPACE_NAME, CONTIGUOUS_BYTES desc;   




select tablespace_name, count(*) "# OF EXTENTS",   

         sum(contiguous_bytes) "TOTAL BYTES"    

from space_temp   

group by tablespace_name;   




spool off   




drop table SPACE_TEMP   

/   

===================================

Sample output from the above script:

===================================

Contiguous Extents Report 







TABLESPACE NAME        CONTIGUOUS BYTES 

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

RBS                 52,426,752 

RBS                 2,662,400 

RBS                  798,720 

RBS                   266,240 




... 




TABLESPACE NAME         CONTIGUOUS BYTES 

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

USERS                  20,480 

USERS                  16,384 

USERS                  10,240 

USERS                  10,240 

USERS                  10,240 

USERS                   4,096 







TABLESPACE_NAME        # OF EXTENTS  TOTAL BYTES 

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

RBS                     15   56,154,112 

SYSTEM                   10     927,744 

TEMP                   5     665,600 

TOOLS                  10   89,397,248 

USERS                   6      71,680



如脚本中的注释所言,一个表空间的extent数量越多,并且extent都比较小,则该表空间碎片现象比较严重。

表碎片评估方法

在表级,Oracle也提供了多种方法和计算公式来评估表的碎片情况。以下介绍一种按统计信息进行评估和分析的方法:

 

col frag format 999999.99
col owner format a30;
col table_name format a30;
select * from (
select a.owner,
 a.table_name,
 a.num_rows,
 a.avg_row_len * a.num_rows,
 sum(b.bytes),
 (a.avg_row_len * a.num_rows) / sum(b.bytes) frag
 from dba_tables a, dba_segments b
 where a.table_name = b.segment_name
and a.owner= b.owner
 and a.owner not in
 ('SYS', 'SYSTEM', 'OUTLN', 'DMSYS', 'TSMSYS', 'DBSNMP', 'WMSYS',
 'EXFSYS', 'CTXSYS', 'XDB', 'OLAPSYS', 'ORDSYS', 'MDSYS', 'SYSMAN')
 group by a.owner,a.table_name,a.avg_row_len, a.num_rows
 having a.avg_row_len * a.num_rows / sum(b.bytes) < 0.7
 order by sum(b.bytes) desc)
where rownum <= 100;


上述语句将以倒排序方式,显示碎片率最高的前100个表。上述方法主要基于相关统计信息进行,不排除由于统计信息采集和更新不及时而导致的误差。

索引碎片评估方法

Oracle在索引碎片分析方面提供了多种方法和计算公式。以下介绍两种:

  • 按BLEVEL分析
col tablespace_name format a20;
col owner format a10;
col index_name format a30; 
select id.tablespace_name,
 id.owner,
 id.index_name,
 id.blevel,
 sum(sg.bytes) / 1024 / 1024,
 sg.blocks,
 sg.extents
 from dba_indexes id, dba_segments sg
 where id.owner = sg.owner
 and id.index_name = sg.segment_name
 and id.tablespace_name = sg.tablespace_name
 and id.owner not in
 ('SYS', 'SYSTEM', 'USER', 'DBSNMP', 'ORDSYS', 'OUTLN')
 and sg.extents > 100
 and id.blevel >= 3
 group by id.tablespace_name,
 id.owner,
 id.index_name,
 id.blevel,
 sg.blocks,
 sg.extents
having sum(sg.bytes) / 1024 / 1024 > 100;



上述语句将显示索引高度Blevel >=3,并且索引大小超过100M的索引。

  • Analyze index方法

analyze index <Index_name> validate structure;

select DEL_LF_ROWS * 100 / decode(LF_ROWS, 0, 1, LF_ROWS) PCT_DELETED from index_stats;

 

上述语句中PCT_DELETED的含义为索引被删除项与索引项总数的所占比例,如果PCT_DELETED>=20%,则说明该索引碎片严重。

由于上述analyze语句会对被分析索引产生锁,即在生产系统运行会产生一定影响,因此我们建议优先考虑按BLEVEL分析方法。

 

Automatic Segment Advisor

  • 简介

Oracle从10g开始推出针对空间进行自动分析的工具:Automatic Segment Advisor。该工具通过分析AWR数据中相关数据段的空间使用情况和增长统计信息,以及取样数据,分析数据段的可回收空间。该工具缺省情况下将在数据库的维护窗口自动运行,也可根据客户需要手工运行。限于篇幅,我们在此不讨论手工运行方式的详细内容了。

Automatic Segment Advisor可提供如下具体建议:

  1. 如果发现数据数据段有大量空闲空间,并且是ASSM(Automatic Segment Space Management)管理模式,则推荐采用shrink技术。如果无法使用shrink技术,如不是ASSM管理模式,则推荐采用在线重定义技术(online table redefinition)。
  2. 如果发现某些表可以通过OLTP等压缩算法进行压缩,使得空间大大节省,该工具将提供相应的建议。
  3. 如果发现一个表的chain row超过一定阀值(Threshold),将相关建议记录在相关数据字典之中。
  • 查看Automatic Segment Advisor分析结果

通过以下一些脚本,可查看Automatic Segment Advisor分析结果,例如以下是查看Finding结果:

 

/*+ 查看Automatic Segment Advisor的Finding结果 */
select af.task_name, ao.attr2 segname, ao.attr3 partition, ao.type, af.message 
 from dba_advisor_findings af, dba_advisor_objects ao
 where ao.task_id = af.task_id
 and ao.object_id = af.object_id

TASK_NAME SEGNAME PARTITION TYPE MESSAGE
------------------ ------------ --------------- ---------------- --------------------------
Manual_Employees EMPLOYEES TABLE The free space in the obje
 ct is less than 10MB.
 
Manual_Salestable4 SALESTABLE4 SALESTABLE4_P1 TABLE PARTITION Perform shrink, estimated
 savings is 74444154 bytes.
 
Manual_Salestable4 SALESTABLE4 SALESTABLE4_P2 TABLE PARTITION The free space in the obje
 ct is less than 10MB.

/*+ 只查询可以进行shrink操作的对象 */
select f.impact, o.type, o.attr1, o.attr2, f.message, f.more_info
 from dba_advisor_findings f, dba_advisor_objects o
 where f.object_id = o.object_id
 and f.task_name = o.task_name
 and f.message like '%shrink%'
 order by f.impact desc;



以下脚本查看Recommendations结果:

 

/*+ 查看Automatic Segment Advisor的Recommendations结果 */
select tablespace_name, segment_name, segment_type, partition_name,
recommendations, c1 from
table(dbms_space.asa_recommendations('FALSE', 'FALSE', 'FALSE'));


TABLESPACE_NAME SEGMENT_NAME SEGMENT_TYPE
------------------------------ ------------------------------ --------------
PARTITION_NAME
------------------------------
RECOMMENDATIONS
-----------------------------------------------------------------------------
C1
-----------------------------------------------------------------------------
TVMDS_ASSM ORDERS1 TABLE PARTITION
ORDERS1_P2
Perform shrink, estimated savings is 57666422 bytes.
alter table "STEVE"."ORDERS1" modify partition "ORDERS1_P2" shrink space


上述脚本不仅告诉客户哪些表、索引存在碎片,而且还预估能回收多少空间,甚至还将产生推荐的空间回收语句,例如:alter table “STEVE”.”ORDERS1″ modify partition “ORDERS1_P2” shrink space。

建议根据Auatomatic Segment Advisor工具的分析结果,并结合上述手工脚本产生的结果进行综合评估,确定需要进行碎片整理的表、索引等对象清单和实施策略。

 

碎片整理方法

表空间级碎片整理方法

  • 技术简介

Oracle可通过如下命令进行表空间相邻空闲空间的压缩(Coalesce),达到碎片整理的目的:

SQL> alter tablespace <表空间名> Coalesce;

 

  • 技术特点

该技术主要针对传统的基于字典管理的表空间,而在基于位图管理的本地化管理的表空间中,Oracle可自动进行相邻空闲空间的压缩。

表碎片整理方法1:数据exp/imp及Data Pump技术

  • 技术简介

Oracle的传统技术Exp/Imp,以及10g开始提供的增强版Data Pump技术,可将存在碎片的表和索引进行数据逻辑卸出,再通过drop或truncate该表,以及数据加载操作,将该表重新创建为一个物理结构紧凑的表和索引,从而达到表和索引碎片压缩的目的。

  • 技术特点

数据exp/imp及Data Pump技术的特点是时间较长,而且在数据卸出和加载期间,为保证数据逻辑一致性,访问该表的应用将被停止。另外,访问该表的索引也需要重新创建。该类技术不需要数据库额外的空间,但需要一定的文件系统空间。

表碎片整理方法2:CTAS技术

  • 技术简介

CTAS技术即如下技术:

SQL> create table <新表名> as select … from <旧表名> …
SQL> drop table <旧表名>;
SQL> rename table <新表名> to <旧表名>;

该技术除了没有将数据卸出和加载之外,其它方面与上述exp/imp及Data Pump技术原理相当。

  • 技术特点

与exp/imp及Data Pump技术特点相当,但需要额外的数据库空间。

表碎片整理方法3:Move Tablespace技术

  • 技术简介

Move Tablespace技术即:

SQL> alter table <表名> move tablespace <表空间名>;


  • 技术特点

相比上述exp/imp、Data Pump和CTAS技术,Move Tablespace技术更快,而且该表的索引并没有删除,但索引状态将变为INVALID,需要重建(rebuild)。其它方面技术特点与上述技术相当,但不需要额外的数据库空间。

表碎片整理方法4:Shrink技术

  • 技术简介

上述传统的碎片整理技术,均需要业务停顿。相比之下,Oracle 10g开始提供的段收缩(segment shrink)技术,则具有明显优势。以下是该技术示意图:

 

suipian2

 

即shrink技术可将表和索引的高水位(HWM)下的碎片进行有效压缩,并将高水位(HWM)进行回退。该技术基本语法如下:

 

SQL> alter table <表名> enable row movement;
SQL> alter table <表名> shrink space cascade; --- 压缩表及相关数据段并下调HWM
SQL> alter table <表名> shrink space compact; --- 只压缩数据不下调HWM
SQL> alter table <表名> shrink space; --- 下调HWM;



即该技术可一次性压缩数据并下调HWM,也可分为两个阶段进行:第一阶段,在业务高峰时,只压缩数据但不下调HWM。第二阶段,在业务非高峰时,再下调HWM,并释放空闲空间。

  • 技术特点

该技术的特点和优势如下:

  • 可以在线进行,不影响正常应用访问。
  • 只能在ASSM(Automatic Segment Space Managment)管理的表空间上进行。该类表空间也必须是基于本地管理模式的。
  • shrink操作适合于如下数据段
  • 普通堆表和IOT表
  • 索引
  • 分区和子分区
  • 物化视图和物化视图日志
  • 在对表进行shrink操作时,对应的索引自动进行维护
  • 在对表进行shrink操作时,不会触发相应的触发器
  • 不需要额外的空间

表碎片整理方法5:Online Redefinition技术

  • 技术简介

Oracle在9i R2之后,提供了一个新的在线重新构造和重新定义表结构的功能:DBMS_REDEFINITION。该技术在几乎不中断业务的情况下,通过创建一个中间表,并通过内部机制,保证原表与中间表的数据同步,最后通过一个切换操作,完成表结构的在线重新定义。

以下是其原理图:

suipian3

 

以下给出一个通过该方法进行碎片整理的简单例子:

1.检查HR.EMPLOYEES是否具有按主键进行Online Redefinition能力
BEGIN
 DBMS_REDEFINITION.CAN_REDEF_TABLE('hr','employees',
 DBMS_REDEFINITION.CONS_USE_PK);
END;
/

2.创建一张与HR.EMPLOYEES同结构的临时表HR.INT_EMPLOYEES
create table hr.int_employees tablespace users as select * from hr.employees where 1=2;

3.对HR.EMPLOYEES表启动Online Redefinition
BEGIN
 DBMS_REDEFINITION.START_REDEF_TABLE('hr', 'employees','int_employees',
 '',dbms_redefinition.cons_use_pk);
END;
/

4.复制该表的索引、限制、触发器等依赖对象
DECLARE
num_errors PLS_INTEGER;
BEGIN
 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('hr', 'employees','int_employees',
 DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
END;
/

5.检查是否有除Primary、constraints之外的错误
select object_name, base_table_name, ddl_txt from
 DBA_REDEFINITION_ERRORS;

6.手工同步数据,该步骤为可选操作
BEGIN 
 DBMS_REDEFINITION.SYNC_INTERIM_TABLE('hr', 'employees','int_employees');
END;
/

7.完成Online Redefinition操作
BEGIN
 DBMS_REDEFINITION.FINISH_REDEF_TABLE('hr', 'employees','int_employees');
END;
/



除碎片管理之外,联机在线重定义技术还具有广泛的应用空间,例如:

  • 修改普通表或Cluster表的存储参数。
  • 将普通表或Cluster表移动到新的表空间。
  • 增加、修改和删除字段。
  • 将普通表转换为分区表,或反之。
  • 修改分区结构
  • 针对单个分区,修改物理属性。例如,将指定分区移动到新的表空间。
  • 为并行查询语句增加支持。
  • 修改物化视图日志表或Streams Advanced Queue表的物理属性。
  • 重建普通表或Cluster表,从而减少碎片。
  • 将普通表转换为按索引组织的表(IOT),或反之。
  • 将普通关系表转换为包含对象字段的表,或反之。
  • 将面向对象的表转换为普通关系表或包含对象字段的表,或反之。
  • 技术特点

Online Redefinition与shrink功能相似,该技术的最大特点是在不中断相关业务情况下,可联机在线进行碎片整理。而且根据Oracle实施经验,以及其它客户实施经验,由于Online Redefinition技术进行的碎片整理是重建该表,因此相比shrink技术,碎片整理效果更明显,但需要消耗一定的数据库空间,而且技术实施比shrink复杂。

索引碎片整理方法1:索引Rebuild和Coalesce技术

  • 技术简介

为有效降低索引碎片,Oracle提供了Rebuild和Coalesce两种技术,例如:

SQL> alter index <索引名> rebuild online parallel 4 nologging;

SQL> alter table <索引名> coalesce;

 

即Rebuild Index可以在线、并行、不产生日志方式进行。

  • 技术特点

以下是Oracle总结的两种技术特点和差异性:

 

Rebuild Index Coalesce Index
可快速将索引迁移到新的表空间 不能够将索引迁移到新的表空间
更高的成本:需要额外空间 更低的成本:不需要额外空间
创建新索引树,压缩索引高度 压缩同一个索引枝下的叶节点空间
在不需要删除索引情况下,可快速修改索引存储和表空间参数 快速释放叶节点空间

 

由于Rebuild Index在碎片整理方面优点更多,因此,在空间足够的情况下,建议尽量采用Rebuild Index技术。

索引碎片整理方法2:Shrink技术

  • 技术简介

Shrink技术同样适合于索引数据的压缩。技术原理实际上等同于Coalesce Index。

  • 技术特点

具有上述Coalesce Index的技术特点。

技术手段比较

以下是综合上述各种技术手段原理、特点而进行的比较分析,其中技术特点着重在能否在线、空间需求,以及技术复杂度三个方面。

 

序号 技术手段 适应场景 在线 空间需求 技术复杂度 说明
1. 表空间Coalesce 表空间 不需要 只适合于字典管理表空间
2. 数据exp/imp及Data Pump技术 需要 需要文件系统空间
3. CTAS技术 需要
4. Move Tablespace技术 不需要
5. Shrink技术 表、索引 不需要 中等
6. Online Redefinition技术 需要
7. Rebuild Index 索引 需要
8. Coalesce Index 索引 不需要

 

技术手段推荐

以下是根据上述技术原理及特点,并结合某项目具体需求和特点,我们建议采取的技术实施思路:

  • 由于该项目已经全部采用本地化表空间,因此无需采用表空间级碎片整理技术。
  • 针对表的碎片整理,优先考虑shrink技术。
  • 针对索引的碎片整理,优先考虑Rebuild Index技术。
  • 如果shrink技术实施效果不理想,或者有一定局限性,则采用Online Redefinition技术。
  • 如果因空间不够,导致Rebuild Index技术无法实施,再考虑Coalesce Index技术。

实施策略、组合和流程

碎片问题不仅造成空间浪费,而且极大地影响性能。碎片整理的上述技术其实不太复杂,但毕竟碎片整理是对生产系统数据展开的,而且现在关键应用系统的高可用性要求都非常高。因此,如何有效地展开碎片整理技术方案的制定,特别是选择测试和试点系统就尤显重要。以下就是针对某客户的碎片管理需求,以及Oracle相关技术特点,我们建议采取的实施策略:

测试和试点系统选择

首先建议选择典型系统进行测试和试点。例如可考虑选择碎片较严重,高可用性略低的系统,如非联机交易型历史数据查询等系统。

如有可能,先期在试点系统的测试演练环境进行。但根据我们了解,测试演练环境与生产系统虽然数据库逻辑结构相同,但基本上是通过Exp/Imp从生产系统构造的系统,因此测试演练环境的物理结构,特别是碎片情况与生产系统大不一样。另外,测试演练环境更缺乏生产系统真实的DML操作。因此,即便在演练环境进行了测试工作,直接在生产系统实施碎片整理,仍然将面临一定的难度和风险。

技术手段

  • 针对表的碎片整理,优先考虑shrink技术。
  • 针对索引的碎片整理,优先考虑Rebuild Index技术。

版本和补丁问题

  • 与shrink相关的Bug

上述主要运用的shrink技术是10g新特性,建议在实施之前,对shrink本身可能存在的问题提前进行分析和防范。

以下是11.2.0.4 patchset中修复的与shrink技术相关的Bug:

6653934 Dump / block corruption from ONLINE segment shrink with ROWDEPENDENCIES
6761624 ALTER INDEX .. SHRINK SPACE can deadlock with concurrent sessions
5215712 OERI [kcbrbrl_1] on table shrink space cascade in ASSM
5768710 ALTER TABLE SHRINK slow with LOB
6494048 Dump [ktsk_get_prevl2] from ALTER INDEX .. SHRINK SPACE

可见,在该项目大量现有10.2.0.4版本上,还可能包含上述与shrink相关的Bug。而在10.2.0.5之上的PSU 3中,没有再发现修复的与shrink相关的Bug。

因此,在该项目碎片管理方案实施中,建议考虑在已经升级到10.2.0.5版本的系统上进行。如果欲在10.2.0.4系统进行,建议先升级到10.2.0.5之后,再实施shrink技术。

  • 与Rebuild Index相关的Bug

以下是10.2.0.5 patchset中修复的与Rebuild Index技术相关的Bug:

7329252+ ORA-8102/ORA-1499/OERI[kdsgrp1] Index corruption after rebuild index ONLINE
3611750 ORA-1450 from online rebuild of index
7326645 ORA-903 / ORA-933 / ORA-911 during ONLINE index creation/rebuild
7697802 Bitmap index rebuilds slower with larger pga_aggregate_target
6767655 Dump [kauxs_do_journal] from concurrent DML while rebuilding index ONLINE
4598439 DBMS_STATS.DELETE_SCHEMA_STATS does not delete index stats after index rebuild
6674374 Optimize rebuild of Text index can fail with concurrent DML

可见,在该项目大量现有10.2.0.4版本上,还可能包含上述与Rebuild Index相关的Bug。而在10.2.0.5之上的PSU 3中,没有再发现修复的与Rebuild Index相关的Bug。

同样理由,建议在该项目碎片管理方案实施中,考虑在已经升级到10.2.0.5版本的系统上进行。如果欲在10.2.0.4系统进行,建议先升级到10.2.0.5之后,再实施Rebuild Index技术。

  • 与Online Redefinition相关的Bug

以下是10.2.0.5 patchset中修复的与Rebuild Index技术相关的Bug:

6679303 ORA-932 from SELECT of LONG RAW altered to CLOB/BLOB with online redefinition
7007594 ORA-600 [12261] at DBMS_REDEFINITION.FINISH_REDEF_TABLE of partitioned table
7573151 Wrong results after online redefinition of table in RAC (with DBMS_REDEFINITION)
7257038 Using DBMS_REDEFINITION on a Streams table causes “missing streams mvdd”
6335679 Cannot use online redefinition with a disabled VPD policy on a table

可见,在该项目大量现有10.2.0.4版本上,也包含上述与Online Redefinition相关的Bug。而在10.2.0.5之上的PSU 3中,没有再发现修复的与Rebuild Index相关的Bug。

同样理由,在该项目碎片管理方案实施中,如果欲实施Online Redefinition技术,建议在已经升级到10.2.0.5版本的系统上进行。如果欲在10.2.0.4系统进行,建议先升级到10.2.0.5之后,再实施Online Redefinition技术。

最佳实践经验

  • 实施时间点建议

尽管shrink和Rebuild Index均可以在不中断应用的情况下在线进行,但为保险起见,如果业务允许,还是尽量避免在业务高峰时进行。

  • Shrink技术实施建议

可考虑将shrink技术分两步进行:首先,先压缩数据但不下调HWM。其次,再下调HWM并释放空闲空间。

  • Rebuild Index技术实施建议

由于Rebuild Index出现问题的情况基本为ONLINE方式,因此如果业务允许,建议Rebuild Index以非ONLINE方式进行。

实施流程图

以下是综合上述各方面建议,而归纳总结的该项目碎片管理实施流程:

 

suipian4

各阶段工作细节

以下是上述实施流程图中各阶段的工作内容和提交物:

suipian5

 

上述方案的详细实施细节,考虑到篇幅就不在本书展开了。

 

15.5本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
1. Oracle联机文档 《Oracle Administrator’s Guide》第18章之“Reclaiming Wasted Space”小节 该小节专门讲述了如何回收空闲空间,特别是介绍了Automatic Segment Advisor的使用。
2. My Oracle Support 《Overview of Database Fragmentation in Oracle 7 [ID 1012431.6]》 虽然这是一篇基于Oracle 7的文档,但在数据库碎片原理方面并没有发生变化。该文档介绍的SYSTEM表空间碎片、表和索引碎片等原理,可以帮助我们了解碎片的基本原理和处理方法。
3. My Oracle Support 《Master Note: Troubleshooting Oracle Tablespace Management (Doc ID 1522807.1)》 这是一篇有关表空间管理方面问题的资料汇集地,当然也包括表空间碎片管理的文章。
4. My Oracle Support 《Script to Detect Tablespace Fragmentation [ID 1020182.6]》 这就是一个检测表空间碎片情况的官方脚本。
5. My Oracle Support 《Various Aspects of Fragmentation [ID 186826.1]》 如果此文档标题翻译成中文,应该是“碎片问题面面观”,可见此文档内容的丰富性。
6. My Oracle Support 《Script to Report Extents and Contiguous Free Space [ID 162994.1]》 这是一个检测扩展块和连续空闲空间情况的官方脚本。
7. My Oracle Support 《Script: Computing Table Size [ID 70183.1]》 如何计算表的空间使用情况?这是Oracle通过VSIZE函数进行表的空间使用情况计算的官方脚本。
8. My Oracle Support 《Script to Report Tablespace Free and Fragmentation (Doc ID 1019709.6)》 这是Oracle公司进行表空间碎片分析的另一个官方脚本。
9. My Oracle Support 《Script: To Report Information on Indexes (Doc ID 1019722.6)》 这是Oracle公司进行索引碎片分析的一个官方脚本。该脚本是通过“analyze index <Index_name> validate structure”命令进行索引分析,但该命令是要锁表的,小心点!
10. My Oracle Support 《Script to Report Space Distribution and utilization (Doc ID 135677.1)》 该文档的脚本对表空间使用情况进行了详细分析,特别是建议对Fragment输出结果高的表空间,可以进行COALESCE操作。

 

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟:话说故障诊断

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

话说故障诊断

故障处理的确是一个涉及面既广又非常深入的领域。但Oracle数据库故障诊断就像世上其它领域的故障诊断一样,都遵循“获取故障现象和数据->故障原因分析->提供解决方案->解决方案测试->正式实施解决方案->故障处理后的评估分析”的通用思路。因此,只要心态平稳、方法得当,再复杂的故障都会找出问题端倪,并通过与各方协调,最终得到解决的。

本章首先将以若干故障诊断案例开始,介绍其中的经验和感悟。然后将介绍故障信息采集的重要性,特别是RDA、AWR、ADDM、DiagCollection.sql、RACCheck、Hanganalyze等数据库故障诊断基本工具的运用,最后又将回到案例,与各位共同分享故障诊断其中的苦与乐。

 

通过案例看故障诊断

其实,作为Oracle公司的解决方案顾问,我已经基本远离了故障诊断这样具体而富有挑战性的一线工作。但最近有幸为某客户的数据库升级和迁移提供现场技术支持服务,再次品味了现场故障诊断的那份紧张、刺激,甚至些许的成就感。下面通过该案例中几个具体故障的解决,与大家一块儿分享其中的经验、方法和规律,还有“痛并快乐着”的切身感受。

故障1:数据没装进去

  • 故障现象

该系统投产前一天,应用开发商在进行正常的功能测试时,发现新系统中一张表的数据为空。由于该项目采取Exp/Imp方式进行升级和迁移,于是我让客户赶紧查一下Exp和Imp的日志文件。果然,在Imp日志文件中显示,该表在进行Imp操作时,出现如下一段错误信息,导致该表数据没有装进去。

 

IMP-00020: long column too large for column buffer size (number)

 

  • 故障原因和解决方法

有病不可怕,就怕病人说不清自己的症状,也怕没有相关的检查报告和指标。同样地,数据库出故障也不可怕,只要有错误信息,就可追根溯源了。以下就是Oracle关于IMP-00020错误的原因分析和解决方法:

 

IMP-00020: long column too large for column buffer size (number)

Cause: The column buffer is too small. This usually occurs when importing LONG data.

Action: Increase the insert buffer size 10,000 bytes at a time (for example). Use this step-by-step approach because a buffer size that is too large may cause a similar problem.


原来是客户在进行数据导入Imp操作时,BUFFER参数设置过小了,特别是在加载LONG类型字段时容易触发该问题,但根据上述关于该错误的Oracle官方解释,BUFFER参数设置过大也会出现相似问题。于是,我建议客户将BUFFER 参数由当前的1G先调大到1.5G,并重新进行Imp操作,没想到问题很快得到解决了。

 

  • 经验和体会

该问题从客户发现到找到原因和解决方法,前后不到5分钟,应该说非常快捷。这就是经验之一:出了问题别紧张,首先找问题错误信息,然后第一时间是在Oracle联机文档的错误信息手册《Oracle® Database Error Messages》中,去查找该错误信息的原因和解决办法,上述信息就是来自该手册。

经验:建议大家在自己笔记本中一定要安装Oracle不同版本的联机文档,看到错误信息,先查错误信息手册。Oracle联机文档的确是个宝藏,针对故障诊断也同样有效。甚至连网都不用上,错误信息手册是最快捷的故障诊断手段!

 

故障2:RAC安装不上

相比上述相对简单,而且影响面较小的故障,该项目面临的第一个也是影响更大的故障是:RAC安装不上!以下就是详细过程:

  • 故障现象

更准确而言,客户是在安装CRS时就失败了,以下是安装程序(OUI)界面显示的错误:

 

troubleshooting1

 

  • 故障原因

显然,OUI图形界面上的信息不足以分析问题原因,但Oracle已经告诉我们去看’C:\Programs Files\Oracle\Inventory\logs\installActions2012-10-10_11-56-34AM’安装日志文件,了解更详细信息了。以下就是该文件最后的部分内容:

… …
Command = C:\Windows\system32\cmd /c call D:\oracle\product.2.0\crs/install/crssetup.config.bat has failed
 Execution Error : failed waiting for completion of ocr configuration with CLSCFG
  [ 0 ] The operation completed successfully.
… …

 

 

 

接下来,通过上述“Execution Error : failed waiting for completion of ocr configuration with CLSCFG”信息,我们在metalink中找到了文章:《CRS Installation Failed with “failed to configure Oracle Cluster Registry with CLSCFG, ret 9” [ID 851742.1]》

该文章对错误原因描述如下:

Cause:
OUI did not handle the return code properly.
The return code [0] "The operation completed successfully" is actually a successful message.

 

哦,原来OUI犯了一个小小的错误:本来返回值0是正常的,但OUI却以为安装过程出问题,而停止安装过程了。

  • 解决办法

以下就是[ID 851742.1]给出的解决办法:

 

Solution:

To workaround the issue:
  1. Rerun $ORA_CRS_HOME\install\crssetup.config.bat from a command prompt window.
This will complete CRS service creation and bring up all CRS services on both nodes.
  1. Continue to run commands listed in $ORA_CRS_HOME\cfgtoollogs\configToolFailedCommands to complete the installation.
  2. The cluvfy command in the last step should return successful check result.

 

 

上述解决办法说白了,就是不使用OUI图形界面了,用户通过命令行方式一步一步进行手工安装,即可顺利安装成功。

 

  • 经验和体会

解决问题关键的第一步就是找准问题症状。在该问题中,就是在installActions2012-10-10_11-56-34AM安装日志文件中找到了上述错误信息。因篇幅因素,本书并没有展开该日志文件,其实找到上述错误信息并不容易。

经验之一:从日志文件最后部分查起,并找到发生该错误的起始时间,再往下查询。经验之二:重点查找“Error”、“Failed”等关键词,根据这些关键词所在的信息去Metalink进行搜索。再次重复该问题的错误信息:“Execution Error : failed waiting for completion of ocr configuration with CLSCFG”。

Metalink是个浩瀚的知识海洋,但我们要学会正确、高效的检索方法。

 

更严重的问题:RAC频繁宕机!

相比前面两个问题,该项目发生的更严重问题是:投产之后,RAC的一个节点频繁宕机。该问题不仅现象严重,而且原因复杂,困扰我们好长时间,最后不得不求助于Oracle全球技术支持中心。但最终还是我们自己找到了问题的症结,并得到彻底解决。以下就是详细过程:

  • 故障现象

该系统在投产之后第一天上午,客户突然反映应用程序连接不到第一个节点,我上去先通过crs_stat –t查询系统状态,果然发现第一个节点的ons、listener、数据库实例等状态为offline了。于是赶紧查询crsd.log日志,相关信息显示如下:


2012-10-23 02:04:13.452: [  CRSAPP][7404]32CheckResource error for ora.tjjm1.ons error code = 1

2012-10-23 02:04:13.452: [  CRSRES][7404]32In stateChanged, ora.tjjm1.ons target is ONLINE

2012-10-23 02:04:13.467: [  CRSRES][7404]32ora.tjjm1.ons on tjjm1 went OFFLINE unexpectedly

2012-10-23 02:04:13.467: [  CRSRES][7404]32StopResource: setting CLI values

2012-10-23 02:04:13.811: [  CRSRES][7404]32Attempting to stop `ora.tjjm1.ons` on member `tjjm1`

2012-10-23 02:04:56.305: [  CRSRES][7404]32Stop of `ora.tjjm1.ons` on member `tjjm1` succeeded.

2012-10-23 02:04:56.305: [  CRSRES][7404]32ora.tjjm1.ons RESTART_COUNT=0 RESTART_ATTEMPTS=3

2012-10-23 02:04:56.305: [  CRSRES][7404]32Restarting ora.tjjm1.ons on tjjm1

2012-10-23 02:04:56.461: [  CRSRES][7404]32startRunnable: setting CLI values

2012-10-23 02:04:56.461: [  CRSRES][7404]32Attempting to start `ora.tjjm1.ons` on member `tjjm1`

2012-10-23 02:05:55.196: [  CRSAPP][7404]32StartResource error for ora.tjjm1.ons error code = 1

2012-10-23 02:06:28.315: [  CRSRES][7404]32Start of `ora.tjjm1.ons` on member `tjjm1` failed.

2012-10-23 02:06:28.408: [  CRSRES][7404]32ora.tjjm1.ons failed on tjjm1 relocating.

2012-10-23 02:06:28.564: [  CRSRES][7404]32Cannot relocate ora.tjjm1.onsStopping dependents

2012-10-23 02:06:28.580: [  CRSRES][7404]32StopResource: setting CLI values

2012-10-23 02:18:35.794: [  CRSAPP][2732]32CheckResource error for ora.tjjm1.LISTENER_TJJM1.lsnr error code = 1

2012-10-23 02:18:35.810: [  CRSRES][2732]32In stateChanged, ora.tjjm1.LISTENER_TJJM1.lsnr target is ONLINE

2012-10-23 02:18:35.810: [  CRSRES][2732]32ora.tjjm1.LISTENER_TJJM1.lsnr on tjjm1 went OFFLINE unexpectedly

2012-10-23 02:18:35.810: [  CRSRES][2732]32StopResource: setting CLI values

2012-10-23 02:18:35.934: [  CRSRES][2732]32Attempting to stop `ora.tjjm1.LISTENER_TJJM1.lsnr` on member `tjjm1`

2012-10-23 02:20:58.161: [  CRSRES][2732]32Stop of `ora.tjjm1.LISTENER_TJJM1.lsnr` on member `tjjm1` succeeded.

2012-10-23 02:20:58.161: [  CRSRES][2732]32ora.tjjm1.LISTENER_TJJM1.lsnr RESTART_COUNT=0 RESTART_ATTEMPTS=5

2012-10-23 02:20:58.161: [  CRSRES][2732]32Restarting ora.tjjm1.LISTENER_TJJM1.lsnr on tjjm1

2012-10-23 02:20:58.426: [  CRSRES][2732]32startRunnable: setting CLI values

2012-10-23 02:20:58.426: [  CRSRES][2732]32Attempting to start `ora.tjjm1.LISTENER_TJJM1.lsnr` on member `tjjm1`

2012-10-23 02:22:39.468: [  CRSAPP][2732]32StartResource error for ora.tjjm1.LISTENER_TJJM1.lsnr error code = 1

2012-10-23 02:25:01.475: [  CRSRES][2732]32Start of `ora.tjjm1.LISTENER_TJJM1.lsnr` on member `tjjm1` failed.

2012-10-23 02:25:01.663: [  CRSRES][2732]32ora.tjjm1.LISTENER_TJJM1.lsnr failed on tjjm1 relocating.

2012-10-23 02:25:01.741: [  CRSRES][2732]32Cannot relocate ora.tjjm1.LISTENER_TJJM1.lsnrStopping dependents

2012-10-23 02:25:01.756: [  CRSRES][2732]32StopResource: setting CLI values

2012-10-23 09:35:27.166: [  CRSRES][8028]32In stateChanged, ora.tjcshow.tjcshow1.inst target is ONLINE

2012-10-23 09:35:27.166: [  CRSRES][8028]32ora.tjcshow.tjcshow1.inst on tjjm1 went OFFLINE unexpectedly

2012-10-23 09:35:27.166: [  CRSRES][8028]32StopResource: setting CLI values

2012-10-23 09:35:27.400: [  CRSRES][8028]32Attempting to stop `ora.tjcshow.tjcshow1.inst` on member `tjjm1`

2012-10-23 09:39:57.875: [  CRSAPP][8028]32StopResource error for ora.tjcshow.tjcshow1.inst error code = 1

2012-10-23 09:39:58.015: [  CRSRES][8028][ALERT]32`ora.tjcshow.tjcshow1.inst` on member `tjjm1` has experienced an unrecoverable failure.

2012-10-23 09:39:58.015: [  CRSRES][8028]32Human intervention required to resume its availability.

2012-10-23 09:39:58.015: [  CRSRES][8028]32Resource failed into UNKNOWN, killing dependents

2012-10-23 09:39:58.015: [  CRSRES][8028]32ora.tjcshow.tjcshow1.inst experienced a failure ontjjm1. Stopping dependent resources.

2012-10-23 09:39:58.015: [  CRSRES][8028]32StopResource: setting CLI values

2012-10-23 09:39:58.015: [  CRSRES][8028]32Attempting to stop `ora.tjcshow.tjcshow1.inst` on member `tjjm1`

2012-10-23 09:41:59.914: [  CRSRES][8028]32Stop of `ora.tjcshow.tjcshow1.inst` on member `tjjm1` succeeded.

2012-10-23 09:57:34.360: [  CRSRES][5104]32CRS-1002: 资源 'ora.oracle2.db' 已在成员 'tjjm1' 上运行

 

上述日志信息表示,在2012-10-23 02:04:13.452开始,CRS检测出ora.tjjm1.ons服务状态错误,并异常宕机了。虽然经过几次重新启动,但依然失败了。然后,ora.tjjm1.LISTENER_TJJM1.lsnr监听服务和数据库实例ora.tjcshow.tjcshow1.inst均相继宕机,并且重起失败。

  • 艰难的故障原因分析

是什么原因导致上述严重问题呢?我们马上检查了网络私网、交换机等硬件环境,一切正常。一时查不到原因,毕竟是已经投产的生产系统,时间紧迫,压力颇大。为加快问题解决,我们赶紧在Metalink创建了SR 3-6353478671,希望Oracle全球技术支持中心专家能与我们同步分析问题原因所在。

于是,象通常的SR处理流程一样,我们主动将crsd.log、ons.log等一大堆日志和配置文件都上传到SR中。但Oracle后台专家也一时一头雾水,只好让我们再设置相关跟踪标志,等待下次故障再次重现时,捕获更多信息。例如:

 

Please do the following the debug the ons


- set ons tracing with
crsctl debug log res "ora.tjjm1.ons:5"


- change the loglevel in $CRS_HOME/opmn/conf/ons.config on both nodes to 
 loglevel=9


- setup OSWatcher
We need the output of the OSWatcher to monitor the OS resources and network statistics.

 

 

我的妈呀,又是设置ons的debug级别,又是设置ons日志级别,还要OSWatcher信息,Oracle后台专家自己把自己陷入信息的海洋了,呵呵。

Oracle后台专家毕竟不在现场,需要各种日志诊断信息的确正常。但我们自己在现场更熟悉情况,应该能更有效地抓取真正对问题诊断有价值的信息。

 

我突然想起来,应该查一下Windows的事件查看器,看看在2012-10-23 02:00前后系统有没有报什么错误信息,果然发现操作系统报了一个Event ID = 5719的错误。这是什么错误呢?于是,只好去微软的站点去查询了。客户系统管理员真给力,很快就查到微软一篇讲述Event ID = 5719的官方文章:http://support.microsoft.com/kb/310339。客户按照该文章给出的解决方案,将注册表中的一个参数MaxDgramBuffering扩大了,但仍然没有解决问题。

眼看要前功尽弃了。怎么办?于是我们再次分析微软的官方文章,仔细研究Event ID = 5719的如下错误原因:

 

No Windows NT or Windows 2000 Domain Controller is available for domain<domain name>. The following error occurred:

There are currently no logon servers available to service the logon request.

 

原来该错误与Windows的Domain Controller有关。再结合我们自己做过的工作,哦,突然想起来了!我们在安装RAC时,当时administrator用户并不在Windows Domain里,我们是以standalone方式安装的,安装之后才将administrator用户加入到Domain中的。RAC运行之后,一定是CRS需要与Windows Domain进行通信,但我们初始安装时并没有在Domain中进行相应的配置,所以通信失败,报错了。

 

  • 解决办法

问题基本定位了,解决办法就简单了。由于已经投产,我们已经无法再重新安装系统了,于是只好将administrator用户退出Domain,将 RAC运行在最初安装时的状态。果然,之后再也没有出现Event ID = 5719错误了,更没有出现RAC的异常宕机了。

最后,我们将自己的分析结果和处理情况向Oracle后台专家沟通之后,也得到了专家的肯定。

  • 经验和体会

各位看了上述叙述,一定感受到该问题的复杂性,涉及操作系统、数据库等多个层面。其实由于书的篇幅所限,我们并没有在书中展开ons、listener等更多的日志和配置信息。当时我们在这些信息中查找问题的蛛丝马迹,真的非常辛苦。值得总结的经验有:

  • 还是要有分析问题的正确方法和思路。针对RAC问题,首先应通过‘crs_stat –t’去分析各服务的状态,然后应分析log日志信息,再查询ons等更细节的相关日志信息。
  • 分析问题要全面。此故障的突破点就是查询了Windows的系统日志,特别针对RAC问题,一定要查询系统日志。
  • 学会看日志文件。很多客户都不太愿意下功夫去仔细研究日志文件,其实看懂日志不仅是一门学问,而且是一个享受的过程。据说,Oracle很多后台专家就把研读日志文件作为一种享受。说实在的,读日志文件真有破案一样顺藤摸瓜的成就感。呵呵。

通过Meatalink的SR,借助Oracle后台专家的力量。虽然本故障最终是我们自己分析出原因并加以解决的,但Oracle后台专家在SR中还是给出了很多分析问题的思路和收集错误信息的方法,值得我们日后借鉴。

 

没完没了的收集数据

某日,作为服务解决方案顾问,为全面了解某大型国有银行客户对Oracle的使用情况,从而提出更有针对性的服务方案,本人通过Oracle一个后台系统对该客户在metalink中过去一年提交的SR(Service Requeset,服务请求)进行统计分析,分析的内容包括客户提交的各类SR 数量、 SR平均处理时长、Bug和非 Bug统计分析、按产品的SR分类统计等。

以下就是该客户2012年全年的1级问题处理时长统计分析图:

troubleshooting2

按照Oracle公司官方定义,1级问题是最严重的问题,包括数据库宕机、关键业务数据丢失等严重问题。从上述统计图可看出,该客户的1级问题平均解决时间达到了17.5天!难怪乎客户运维老总看到这组数字时,心惊肉跳地说:“幸亏去年的1级问题并不是导致业务彻底中断的真正1级问题,否则宕机17.5天,我的乌纱帽早就没了!”呵呵。

但大家通过仔细分析后发现,其实在17.5天中,等待客户处理的平均时间达到13天,也就是说Oracle公司包括Oracle Support部门和研发部门负责处理、需要承担责任的时间只有4天多,而主要责任在客户自己。客户需要在问题处理过程中承担什么责任呢?

在国内客户中,很多人提交SR之后,就以为万事大吉,坐等Oracle专家的灵丹妙药了。其实,Oracle专家也不是神仙,解决问题也有个逐步深入的过程,需要不断了解你的系统,甚至期待问题再次爆发,才能抓取更多信息,逐步定位问题并提供正确的解决方案。

在SR中有一个状态信息。分别表示该SR在等待Oracle Support工程师、Oracle研发团队进行处理,还是等待客户处理的状态。其中等待客户处理状态包括:CUS(等待客户回应)、WCP(等客户打补丁)、SLP(休眠,等待客户再启动)、LMS(留话/讯息)等。

在客户承担的责任中,一个重要工作就是负责收集和上传相关系统环境和出错信息,而为了得到这些信息,Oracle常见诊断工具的使用是必不可少的,例如RDA、AWR、OSWatch、DiagCollection等。该银行客户的SR等待客户处理平均时间达到13天,说明该客户一定不是非常熟悉这些工具的使用。也有另一种可能性:信息收集不全,或者Oracle Support工程师自身也缺乏经验,没有指导客户一次性收集全相关数据。于是,一遍又一遍、没完没了地收集数据,Oracle Suppot工程师就是给不出一个问题原因分析和解决建议,让该客户苦不堪言。

排除Oracle Support工程师自身原因,我们客户如何全面了解Oracle数据库常见诊断工具,特别是在故障发生时能主动、全面提供相关信息,无疑是提高故障处理效率的有效途径。凡事从自身做起,求人不如求自己。

下面就将介绍相关的Oracle数据库常见诊断工具的基本使用方法。

数据库常见诊断工具

RDA

RDA(Remote Diagnostic Agent)是Oracle Support部门为进行故障诊断分析,快速全面了解Oracle运行环境而提供的分析工具。RDA将采集硬件、操作系统、网络、数据库等各个层面的信息,RDA采集的信息将会为问题问题和故障诊断提供有力的帮助。

RDA工具只会查询Oracle运行环境的各类信息,不会去调整任何配置信息,因此不会对现有环境造成任何影响。

RDA支持各种主流平台,以及Oracle的数据库、RAC、ASM、Data Guard、Oracle应用服务器、ERP等各类产品。RDA的详细情况,请见RDA的最新文档:《Remote Diagnostic Agent (RDA) – Getting Started (Doc ID 314422.1)》。

  • 安装RDA
  • 在服务器上创建一个RDA目录,并保证有足够的空间。
  • 将RDA压缩文件(tar or rda.tar.gz file)FTP到该目录。
  • 解压RDA压缩文件。例如:
tar xvf rda.tar
或
gunzip rda.tar.gz
tar xvf rda.tar

 

  • 确保RDA相关命令的执行权限:

chmod +x <rda>

  • 运行RDA及产生RDA报告
  • 以Oracle用户,执行如下命令,进行初始的配置选择,确定信息采集范围:

$ ./rda.sh -S

  • 以Oracle用户,执行如下命令:

$ ./rda.sh

  • RDA产生的报告位于RDA output目录下,并以HTML文件形式存储。通过<output_directory>/<report_group>__start.htm可浏览RDA的相关内容。
  • RDA产生的所有报告以压缩文件打包形式位于RDA output目录下,例如.zip, .tar, .tar.gz, 或 .tar.Z等后缀形式。如果RDA报告是针对某个具体的SR,请将该压缩文件上传到metalink的相关SR。

以下就是某系统RDA报告的首页:

troubleshooting3

 

建议在发生具体问题时,在Oracle Support要求和指导下,从metalink下载最新的RDA工具和ReadMe文档,运行RDA工具,并将相关RDA报告上传。

AWR

AWR(Automactic Workload Repository)是Oracle 10g的新特性之一。通过AWR,Oracle可自动采集、维护和使用数据库运行的相关统计信息,进行问题诊断和自我调整。

  • Workload Repository的产生

缺省情况下,Oracle 10g每隔一个小时自动产生一个快照。通过如下命令可设置自动产生快照的频度:

SQL> EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(interval  =>  30);

如果设置interval为0,则系统将不自动产生快照。

通过如下命令,可手工产生快照:

SQL> EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;

 

  • AWR报告的产生

通过如下脚本,并选择文件输出格式为文本或HTML、快照天数、起始快照号和结束快照号等信息,将产生需要的AWR报告。

SQL>?/rdbms/admin/awrrpt.sql
  • AWR报告的分析

AWR报告包括了数据库运行的各个层面的大量信息,有效地利用AWR报告分析数据库运行状态以及进行故障诊断,是一项既需要扎实的数据库基础知识,又需要经验不断积累的过程。相关建议如下:

  • 先看系统整体状态,例如:Load Profile、Instance Efficiency Percentages、Top 5 Timed Events
  • 在RAC情况下,特别需要关注RAC Statistics中的Global Cache Load Profile、Global Cache Efficiency Percentages、Global Cache and Enqueue Services – Workload Characteristics、Global Cache and Enqueue Services – Messaging Statistics 等部分指标信息的变化情况。
  • 重点对Top-N SQL的质量进行分析。根据时间消耗、内存消耗、物理I/O等排序情况,对相关SQL语句进行执行计划分析等质量评估。
  • 对SGA的各种Buffer以及PGA等进行分析。
  • 通过对表空间、数据文件I/O的分析,对应用软件设计和物理设计进行评估。
  • 对Segment的逻辑读、物理读等进行分类分析,以确定系统的瓶颈。特别在RAC情况下,对Segments by Global Cache Buffer Busy、Segments by Current Blocks Received等内容的分析,可确定节点间通信和同步的对象。
  • 如果采用service技术,通过对Service Statistics信息的分析,可了解以Service为单位进行的性能指标,特别是系统负载情况分析。
  • 对其它可能造成数据库性能瓶颈的一些等待事件、Latch等进行分析。

ADDM

ADDM(Automatic Database Diagnostic Monitor)是Oracle 10g之后内置的自动进行问题分析的工具。ADDM利用Workload Repository存储的快照信息,可分析指定时间段的数据库各种问题。

  • ADDM报告的产生

通过如下脚本,选择起始快照号和结束快照号,将产生需要的ADDM报告。

SQL>?/rdbms/admin/addmrpt.sql
  • ADDM报告的分析
  • ADDM报告将提供系统自动发现的相关问题以及供解决方案
  • ADDM将对每类问题的根源进行分析,以及对系统的整体影响率,同时产生相关的优化建议
  • ADDM也将对没有问题的领域进行分析,从而避免DBA对该领域做过多的分析,尽可能减少问题分析的时间和付出

同样地,ADDM报告的分析既需要扎实的数据库基础知识,又需要经验不断积累、不断实践。

DiagCollection.pl

Clusterware作为Oracle的集群管理软件,功能的确强大,具有集群管理(Cluster Management)、节点监控(Node Monitoring)、事件服务(Event Services)、时钟同步(Time Synchronization)、网络管理(Network Management)、高可用性(High Availability)等诸多领域的功能,分别涉及CRS、CSS、EVM、CTSS、ONS等不同组件和服务。正因为功能太强大、组件太多,一旦Clusterware出现问题和故障,其诊断和分析过程也够DBA和系统管理员喝一壶的,呵呵。尽管Oracle自称为Clusterware的日志文件设计了一个统一的日志文件目录结构,如下图所示:

troubleshooting4

但DBA和系统管理员们从上述纷繁的日志目录结构中快速、准确地找到相关信息,并不是一件轻松的事情。这也是在与Clusterware相关的SR中,Oracle Support专家反复要求客户收集和上传日志信息,导致SR处理时间过长的一个重要原因。

幸亏Oracle 11g提供了一个diagcollection脚本,可以将上述Clusterware 日志统一打包成几个压缩文件,以便客户快速上传给Oracle Support部门,用于Clusterware相关SR 的快速、准确进行问题诊断和分析。相关技术细节如下:

  • diagcollection脚本位置

diagcollection脚本(diagcollection.pl)位于<Grid_Home>/bin目录之下,并且必须以root用户进行运行。

  • diagcollection脚本示例

以下为diagcollection脚本通过 “collect”选项进行clusterware日志文件收集,并在当前目录下生成4个打包和压缩文件的示例:

# /u01/app/11.2.0/grid/bin/diagcollection.pl --collect

Production Copyright 2004, 2008, Oracle.  All rights reserved

Cluster Ready Services (CRS) diagnostic collection tool

The following diagnostic archives will be created in the local directory.

crsData_host01_20090729_1013.tar.gz -> logs,traces and cores from CRS home. Note: core files will be packaged only with the --core option.

ocrData_host01_20090729_1013.tar.gz -> ocrdump, ocrcheck etc

coreData_host01_20090729_1013.tar.gz -> contents of CRS core files

osData_host01_20090729_1013.tar.gz -> logs from Operating System

...

 

  • diagcollection脚本其它功能

通过“clean”选项,可以清除当前目录下上次收集的日志文件包:

# /u01/app/11.2.0/grid/bin/diagcollection.pl –clean

通过“colletion”和“crs”选项,只收集和打包与Oracle Clusterware相关的日志:

# /u01/app/11.2.0/grid/bin/diagcollection.pl –collection –crs

通过“colletion”和“core”选项,只收集和打包与core相关的日志:

# /u01/app/11.2.0/grid/bin/diagcollection.pl –collection –core

 

“–collection –all”将收集所有日志,“–all”是缺省配置。

 

Dynamic Debugging

以root用户运行如下脚本,可对整个Clusterware,EVM及相关resource动态采集debug信息。

例如,对整个Clusterware动态采集debug信息的命令如下:

crsctl debug log crs “CRSRTI:1,CRSCOMM:2”

 

对EVM动态采集debug信息的命令如下:

crsctl debug log evm “EVMCOMM:1”

 

对某个resource动态采集debug信息的命令如下:

crsctl debug log res “resname:1”

 

建议在发生具体问题时,在Oracle Support要求和指导下,启动debug状态,并将相关日志和debug信息上传。

 

Component Level Debugging

以root用户运行如下脚本,可对整个CRS daemon,EVM及相关module采集debug信息。

crsctl debug log module_name component:debugging_level

 

其中:

  • debugging_level取值为1到5
  • module_name 为crs, evm, or css的模块名。运行如下命令,可得到crs, evm, or css的模块名:

crsctl lsmodules module_name

 

建议在发生具体问题时,在Oracle Support要求和指导下,启动相关模块的debug状态,并将相关日志和debug信息上传。

 

RACCheck

  • 概述

RACCheck工具全称叫做:RAC Configuration Audit tool,主要用于检查和审计RAC、Clusterware、ASM及GI环境的配置信息。检查和审计的领域包括:操作系统核心参数、操作系统Package、与RAC相关的操作系统其它配置信息、CRS/Grid Infrastructure、RDBMS、ASM、数据库参数、与RAC相关的数据库其它配置信息、11.2.0.3升级就绪评估。

  • 什么时候该运行RACCheck工具?

在《RaccheckUserGuide_v2_2_2》手册中,Oracle公司建议在如下几种情况下,应运行RACCheck工具:

  • 在RAC首次安装之后。
  • 在计划性地进行系统维护之前。例如,修改公网IP、数据库补丁安装等变更操作之前。
  • 在计划性地进行系统维护之后。例如,修改公网IP、数据库补丁安装等变更操作之后。
  • 每三个月一次。
  • 为解决与RAC相关问题,应Oracle Support工程师之建议。
  • RACCheck快速指南

以下是RACCheck工具使用的快速指南,RACCheck工具下载方式请见《RACcheck – RAC Configuration Audit Tool (Doc ID 1268927.1)》,详细操作说明请见《RaccheckUserGuide_v2_2_2》。

  • 若安装了Oracle产品,则以Oracle RDBMS安装用户登录系统。否则,以root用户进行登录。
  • 将zip包上传到需要进行检查的节点的某个目录。
  • 解压(Unzip)zip包。
  • 确认raccheck的权限为755(-rwxr-xr-x)。否则,执行如下命令:

$ chmod 755 raccheck

  • 执行raccheck:

$ ./raccheck

请根据提示回答相关问题,以下是该工具执行的相关片断内容:


CRS stack is running and CRS_HOME is not set. Do you want to set CRS_HOME to /oragi/11.2.0.3/grid?[y/n][y]y
Checking ssh user equivalency settings on all nodes in cluster
Node ratlnx02 is configured for ssh user equivalency for oracle user


Searching for running databases . . . . .

List of running databases registered in OCR
  1. maadb
  2. None
Select respective number to choose database for checking best practices. For multiple databases, select 1 for All or comma separated number like 1,2 etc [1-2][1].1

. .

Checking Status of Oracle Software Stack - Clusterware, ASM, RDBMS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 -------------------------------------------------------------------------------------------------------

Oracle Stack Status

Host Name CRS Installed ASM HOME RDBMS Installed CRS UP ASM UP RDBMS UP DB Instance Name


ratlnx01    Yes         Yes      Yes              Yes    Yes    Yes         maadb1
ratlnx02    Yes         Yes      Yes              Yes    Yes    Yes         maadb2

9 of the included audit checks require root privileged data collection . If sudo is not configured or the root password is not available, audit checks which  require root privileged data collection can be skipped.

  1. Enter 1 if you will enter root password for each  host when prompted
  2. Enter 2 if you have sudo configured for oracle user to execute root_raccheck.sh script
  3. Enter 3 to skip the root privileged collections
  4. Enter 4 to exit and work with the SA to configure sudo  or to arrange for root access and run the tool later.
Please indicate your selection from one of the above options[1-4][1]:-

Note: If you chose option 1, to provide root password when prompted, you will be prompted once for each node during the data collection phase for the nodes (unless expect is installed). If you do not enter the root password in a timely way (within RACCHECK_TIMEOUT) then the root privileged collections and audit checks for that node will be skipped.  For functionality of parallel execution of RACcheck on all cluster nodes, the expect utility MUST be installed.  For this reason it is highly recommended that the expect utility be installed on the systems.


Please indicate your selection from one of the above options[1-4][1]:- 1Is root password same on all nodes?[y/n][y]y

Enter root password :-

*** Checking Best Practice Recommendations (PASS/WARNING/FAIL) ***

Log file for collections and audit checks are at

/home/oracle/raccheck/raccheck_120211_112221/raccheck.log

. . . . . . . . . . . . . . .

 

 

  • raccheck工具执行完之后,将显示如下类似内容:

Detailed report (html) – /home/oracle/raccheck/raccheck_ratlnx01_120211_114104/raccheck_ratlnx01_120211_114104.html

 

UPLOAD(if required) – /home/oracle/raccheck/raccheck_ratlnx01_120211_114104.zip

 

  • 此时,可通过查看raccheck产生的上述html文件,了解RAC环境检查结果。或者将上述zip文件上传到相关SR,提供给Oracle Support工程师进行分析。

10046 event的设置

10046 event的设置等同于设置SQL_TRACE = TRUE,即主要针对存在性能问题的SQL语句收集跟踪信息。与设置SQL_TRACE = TRUE不同的是,设置10046 event时,可根据需要设置不同的跟踪级别,从而收集更详细的信息。例如:

  • Level = 1:启动标准的SQL_TRACE功能,该值为缺省值。
  • Level = 4:除Level = 1的功能之外,增加对BIND变量值的跟踪分析。
  • Level = 8:除Level = 1的功能之外,增加对wait等待事件的跟踪分析,例如对latch wait等待事件的跟踪分析。

在11g中,增加如下Level值:

  • Level = 16:针对SQL语句的每次执行过程,产生统计信息(STAT line dumps)
  • Level = 32:针对SQL语句的每次执行过程,不产生统计信息。

在11.2.0.2之后,增加如下Level值:

  • Level = 64:针对SQL语句的每次执行过程,自适应地产生统计信息。在这种设置下,假设语句执行时间超过1分钟,将产生统计信息。这样,Oracle自动针对资源消耗过大语句的执行过程收集更多统计信息。

在11g中,通过设置SQL_TRACE及选项方式,也可实现过去由设置10046和相关Level的功能。例如:

 

alter session set events ‘sql_trace wait=false, bind=true’;’

以下就是10046的不同Level值与11g中SQL_TRACE相关选项的对应关系:

Level 11g SQL_TRACE的选项
   
1 N/A
4 bind=true
8 wait=true
16 plan_stat=all_executions
32 plan_stat=never
64 plan_stat=adaptive

以下就是一些设置例子,在会话级进行如下设置:

 

alter session set events ‘10046 trace name context forever’;

alter session set events ‘10046 trace name context forever, level 8’;

alter session set events ‘10046 trace name context off’;

在11g中,针对上述设置可进行如下设置:

alter session set events ‘sql_trace’;

alter session set events ‘sql_trace wait=true’;

alter session set events ‘sql_trace off”;

在初始化参数中,可进行如下设置:

event=”10046 trace name context forever,level 4″

 

此时Oracle将对所有会话的SQL语句进行跟踪信息收集,因此建议谨慎为之,避免系统产生大量无用的跟踪信息。

在设置10046事件或SQL_TRACE=TRUE之后,系统将在udump目录产生相应的Trace文件。通常,Trace文件是上传给SR,供Oracle Support工程师分析的。若我们自己要分析Trace文件,则需要在相关文档的帮助下方能读懂。有兴趣的读者请参考《Interpreting Raw SQL_TRACE output (Doc ID 39817.1)》,本人就不在这里堆积这么晦涩难懂的东西了。呵呵。

 

数据库挂起(HANG)诊断信息的收集

可怕的数据库Hang

“数据库Hang住了,连 sqlplus 都进不去了!”这是数据库运行过程中,比较常见、也是比较难于处理的一类故障。

根据Oracle官方的解释,所谓数据库挂起(Hang),通常而言是因为某些进程可能正在非常繁忙地工作而没有释放相关资源,而其它进程被迫处于等待之中。其实导致数据库Hang的原因多种多样:某些应用性能差,把资源耗尽,可能导致数据库Hang;归档日志文件区满,会导致数据库Hang;NFS服务器宕机,或者连接NFS服务器的网络中断,将导致包括Oracle数据库在内的应用都出现Hang;Oracle数据库软件本身的Bug可能导致Hang… …。而且,数据库Hang与数据库运行缓慢并不是同一回事。

本节、本章,甚至本书都无法穷尽各种数据库Hang的故障及解决办法,但就像看病先要进行各种诊断一样,本节我们重点介绍数据库出现Hang时,如何进行诊断信息的收集。虽然下面介绍的一些诊断信息的获取,并不一定马上就能找到Hang的根源,但这些诊断信息不仅有助于问题的分析,而且至少能帮助我们排除一些问题原因,例如是不是应用问题,甚至帮我们避免类似问题的再次发生。

 

Hanganalyze和Systemstate Dumps信息的收集

Oracle公司建议针对数据库Hang,从如下三个方面进行信息的收集:

  • Hanganalyze和Systemstate Dumps
  • AWR/Statspack
  • RDA

AWR/Statspack、RDA就不赘述了。以下重点介绍Hanganalyze和Systemstate Dumps信息的收集。

Hanganalyze和Systemstate Dumps都可在指定时间段内提供数据库进程的相关信息。Hanganalyze用于判断数据库是处于Hang状态,还是运行时间很慢,并收集处于 Hang状态中的进程信息。而Systemstate Dumps则针对数据库所有进程进行信息的收集。

为收集Hanganalyze和Systemstate Dumps信息,首先需以如下方式连接到Oracle:

sqlplus ‘/ as sysdba’

如果无法登录10gR2以上版本,则尝试如下的preliminary方式登录:

sqlplus –prelim ‘/ as sysdba’

实际上,preliminary方式并没有创建Session,仅仅是连接到数据库,但能有限制地访问SGA等,从而收集Systemstate Dumps等诊断信息。

需要说明的是,在11.2.0.2以上版本,如果以preliminary方式登录系统,由于Hanganalyze需要进程状态对象和Session状态对象,而如上所述,preliminary方式并没有创建Session,因此,并不能收集到Hanganalyze信息,并报如下错误:

 

HANG ANALYSIS:

 

ERROR: Can not perform hang analysis dump without a process state object and a session state object.

( process=(nil), sess=(nil) )

 

在单机情况下,当数据库出现Hang或运行特别缓慢时,按如下方式进行Hanganalyze信息的收集:

 

sqlplus ‘/ as sysdba’

oradebug setmypid

oradebug unlimit

oradebug hanganalyze 3

收集第二个hanganalyze信息之前,等待至少1分钟

oradebug hanganalyze 3

oradebug tracefile_name

exit

 

按如下方式进行Systemstate Dumps信息的收集:

sqlplus ‘/ as sysdba’

oradebug setmypid

oradebug unlimit

oradebug dump systemstate 266

oradebug dump systemstate 266

oradebug tracefile_name

exit

 

在RAC环境下,首先有两如下两个Bug与Hanganalyze和Systemstate Dumps信息收集相关,这两个Bug会导致level 266或267的收集工作非常缓慢:

Document 11800959.8 Bug 11800959 – A SYSTEMSTATE dump with level >= 10 in RAC dumps huge BUSY GLOBAL CACHE ELEMENTS – can hang/crash instances

Document 11827088.8 Bug 11827088 – Latch ‘gc element’ contention, LMHB terminates the instance

 

因此,强烈建议先检查是否安装这两个Bug的补丁。如果安装了这两个补丁,则以如下方式进行Hanganalyze和Systemstate Dumps信息收集:

sqlplus ‘/ as sysdba’

oradebug setorapname reco

oradebug  unlimit

oradebug -g all hanganalyze 3

oradebug -g all hanganalyze 3

oradebug -g all dump systemstate 266

oradebug -g all dump systemstate 266

exit

 

如果没有安装这两个补丁,则以如下方式进行Hanganalyze和Systemstate Dumps信息收集:

sqlplus ‘/ as sysdba’

oradebug setorapname reco

oradebug unlimit

oradebug -g all hanganalyze 3

oradebug -g all hanganalyze 3

oradebug -g all dump systemstate 258

oradebug -g all dump systemstate 258

exit

在RAC环境下,将在每个实例的DIAG跟踪文件中产生相应的dump信息。

上述Hanganalyze的level设置成 3,表示在11g以上版本中,只针对被 Hang住的进程收集short stack信息。

Systemstate Dumps的level设置成258,表示一种快速收集方式,并可能丢失某些锁的信息。而Systemstate Dumps的level设置成266,则将收集更多信息,包括缓冲区、锁等信息。

 

11g的v$wait_chains

从11g开始,Oracle的后台进程dia0开始收集hanganalyze信息,并保存在所谓的“hang analysis cache”中,也就是v$wait_chains动态视图中。dia0每隔3秒采集本地实例的hanganalyze信息,每隔10秒采集Global,也就是RAC的hanganalyze信息。

这些信息对数据库出现Hang和资源竞争的诊断分析非常有用,Oracle内部很多工具也在运用这些信息,包括:Hang Management, Resource Manager Idle Blocker Kill, SQL Tune Hang Avoidance和PMON cleanup等。同样地,一些诸如Procwatcher的外部工具也在运用运用这些信息。

以下就是v$wait_chains视图的结构:


SQL> desc v$wait_chains
   Name Null? Type
   ----------------------------------------- -------- ----------------------
   CHAIN_ID NUMBER
   CHAIN_IS_CYCLE VARCHAR2(5)
   CHAIN_SIGNATURE VARCHAR2(801)
   CHAIN_SIGNATURE_HASH NUMBER
   INSTANCE NUMBER
   OSID VARCHAR2(25)
   PID NUMBER
   SID NUMBER
   SESS_SERIAL# NUMBER
   BLOCKER_IS_VALID VARCHAR2(5)
   BLOCKER_INSTANCE NUMBER
   BLOCKER_OSID VARCHAR2(25)
   BLOCKER_PID NUMBER
   BLOCKER_SID NUMBER
   BLOCKER_SESS_SERIAL# NUMBER
   BLOCKER_CHAIN_ID NUMBER
   IN_WAIT VARCHAR2(5)
   TIME_SINCE_LAST_WAIT_SECS NUMBER
   WAIT_ID NUMBER
   WAIT_EVENT NUMBER
   WAIT_EVENT_TEXT VARCHAR2(64)
   P1 NUMBER
   P1_TEXT VARCHAR2(64)
   P2 NUMBER
   P2_TEXT VARCHAR2(64)
   P3 NUMBER
   P3_TEXT VARCHAR2(64)
   IN_WAIT_SECS NUMBER
   TIME_REMAINING_SECS NUMBER
   NUM_WAITERS NUMBER
   ROW_WAIT_OBJ# NUMBER
   ROW_WAIT_FILE# NUMBER
   ROW_WAIT_BLOCK# NUMBER
   ROW_WAIT_ROW# NUMBER

 

Oracle没有提供gv$wait_chains视图,因为 v$wait_chains已经包含了RAC环境下多实例的信息。

以下是一个简单查询的例子:

 

SQL> SELECT chain_id, num_waiters, in_wait_secs, osid, blocker_osid, substr(wait_event_text,1,30)
  FROM v$wait_chains; 2
  
  CHAIN_ID NUM_WAITERS IN_WAIT_SECS OSID BLOCKER_OSID SUBSTR(WAIT_EVENT_TEXT,1,30)
  ---------- ----------- ------------ ------------------------- ------------------------- ------------------------------
  1 0 10198 21045 21044 enq: TX - row lock contention
  1 1 10214 21044 SQL*Net message from client

 

以下是查询前100个Hang chain进程的脚本:


set pages 1000
  set lines 120
  set heading off
  column w_proc format a50 tru
  column instance format a20 tru
  column inst format a28 tru
  column wait_event format a50 tru
  column p1 format a16 tru
  column p2 format a16 tru
  column p3 format a15 tru
  column Seconds format a50 tru
  column sincelw format a50 tru
  column blocker_proc format a50 tru
  column waiters format a50 tru
  column chain_signature format a100 wra
  column blocker_chain format a100 wra
  
  SELECT * 
  FROM (SELECT 'Current Process: '||osid W_PROC, 'SID '||i.instance_name INSTANCE, 
  'INST #: '||instance INST,'Blocking Process: '||decode(blocker_osid,null,'<none>',blocker_osid)|| 
  ' from Instance '||blocker_instance BLOCKER_PROC,'Number of waiters: '||num_waiters waiters,
  'Wait Event: ' ||wait_event_text wait_event, 'P1: '||p1 p1, 'P2: '||p2 p2, 'P3: '||p3 p3,
  'Seconds in Wait: '||in_wait_secs Seconds, 'Seconds Since Last Wait: '||time_since_last_wait_secs sincelw,
  'Wait Chain: '||chain_id ||': '||chain_signature chain_signature,'Blocking Wait Chain: '||decode(blocker_chain_id,null,
  '<none>',blocker_chain_id) blocker_chain
  FROM v$wait_chains wc,
  v$instance i
  WHERE wc.instance = i.instance_number (+)
  AND ( num_waiters > 0
  OR ( blocker_osid IS NOT NULL
  AND in_wait_secs > 10 ) )
  ORDER BY chain_id,
  num_waiters DESC)
  WHERE ROWNUM < 101;

 

以下是上述脚本的一个范例:

 

troubleshooting5

 

 

该范例表示进程25627正处于TX行级锁等待,并被进程21549锁住,而21549处于空闲等待“SQL*Net message from client”事件之中,也就是等待应用提供信息或处于网络等待之中。

在11.2以上版本中,在v$session视图中增加了一个字段:final_blocking_session,该字段表示在hang等待链中的根进程。例如,如下脚本可查询出final_blocking_session:

set pages 1000
 set lines 120
 set heading off
 column w_proc format a50 tru
 column instance format a20 tru
 column inst format a28 tru
 column wait_event format a50 tru
 column p1 format a16 tru
 column p2 format a16 tru
 column p3 format a15 tru
 column Seconds format a50 tru
 column sincelw format a50 tru
 column blocker_proc format a50 tru
 column fblocker_proc format a50 tru
 column waiters format a50 tru
 column chain_signature format a100 wra
 column blocker_chain format a100 wra
 
 SELECT * 
 FROM (SELECT 'Current Process: '||osid W_PROC, 'SID '||i.instance_name INSTANCE, 
  'INST #: '||instance INST,'Blocking Process: '||decode(blocker_osid,null,'<none>',blocker_osid)|| 
  ' from Instance '||blocker_instance BLOCKER_PROC,
  'Number of waiters: '||num_waiters waiters,
  'Final Blocking Process: '||decode(p.spid,null,'<none>',
  p.spid)||' from Instance '||s.final_blocking_instance FBLOCKER_PROC, 
  'Program: '||p.program image,
  'Wait Event: ' ||wait_event_text wait_event, 'P1: '||wc.p1 p1, 'P2: '||wc.p2 p2, 'P3: '||wc.p3 p3,
  'Seconds in Wait: '||in_wait_secs Seconds, 'Seconds Since Last Wait: '||time_since_last_wait_secs sincelw,
  'Wait Chain: '||chain_id ||': '||chain_signature chain_signature,'Blocking Wait Chain: '||decode(blocker_chain_id,null,
  '<none>',blocker_chain_id) blocker_chain
 FROM v$wait_chains wc,
  gv$session s,
  gv$session bs,
  gv$instance i,
  gv$process p
 WHERE wc.instance = i.instance_number (+)
  AND (wc.instance = s.inst_id (+) and wc.sid = s.sid (+)
  and wc.sess_serial# = s.serial# (+))
  AND (s.final_blocking_instance = bs.inst_id (+) and s.final_blocking_session = bs.sid (+))
  AND (bs.inst_id = p.inst_id (+) and bs.paddr = p.addr (+))
  AND ( num_waiters > 0
  OR ( blocker_osid IS NOT NULL
  AND in_wait_secs > 10 ) )
 ORDER BY chain_id,
  num_waiters DESC)
 WHERE ROWNUM < 101;


以下是上述脚本的一个范例:

 

troubleshooting6

 

可见,进程号2309是hang等待链中的根进程,杀掉该进程将解除该hang等待链。

主动进行Hang信息收集的方法

在很多情况下,当Hang发生时,DBA已经难于捕获相关诊断信息,如下一些主动进行Hang信息收集的方法值得一试:

  • HANGFG script

与上述手工收集Hanganalyze信息不同的是,HANGFG是Oracle提供的一套自动进行Hanganalyze信息收集的脚本。HANGFG的详细情况请见Oracle文档:《Document 362094.1 HANGFG User Guide》

  • LTOM

LTOM(The Lite Onboard Monitor)是Oracle提供的一个基于Java的实时信息诊断程序,并部署于客户端,LTOM以主动方式、自动地进行实时问题诊断和数据手机。HANGFG的详细情况请见Oracle文档:《Document 352363.1 LTOM – The On-Board Monitor User Guide》

  • Procwatcher

Procwatcher是Oracle提供的一个用于定期检查和监控数据库和Clusterware进程的工具。如下Oracle文档详细介绍了Procwatcher及在故障诊断中的运用:

Document 459694.1 Procwatcher: Script to Monitor and Examine Oracle DB and Clusterware Processes》

Document 1352623.1 How To Troubleshoot Database Contention With Procwatcher》

  • OS Watcher Black Box

OS Watcher Black Box是Oracle提供的一个用于自动进行 CPU、内存、I/O和网络数据采集和分析的工具。当数据库出现问题包括Hang时,该工具可在操作系统层面进行分析,并且开销很低,因此, Oracle建议尽量安装并运行该工具。OS Watcher Black Box的详细情况请见Oracle文档:《Document 301137.1 OSWatcher Black Box User Guide (Includes: [Video])》。

 

一些“自主知识产权”脚本

 

罗老师神秘的脚本

N年之前,我与一位第三方公司的同行一同在客户现场进行工作,由于每次我都运用自己编写的一些脚本进行问题分析和诊断,并且效果不错,引得他已经“觊觎”了很长时间。这天,他终于忍不住,对我提出如下要求:

“罗老师,能不能把你一些神秘的脚本发给我一下?”,他语气中带有点哀求。

“对不起,我这可是自有知识产权的,不能随便给人。”我和他调侃道。

看他一脸的失望,我又继续认真地解释道:“我这些脚本都很个性化,很凌乱,没有好好梳理,也没有什么注释,可能只有我自己才能看得懂。”但是,那次我还是非常仗义地将部分脚本,特别将容易看得懂的脚本,甚至加了若干注释之后发给了他,希望对他日后的工作有所帮助。

我的脚本从何如来?一方面是自己在学习和研究Oracle一些专题技术时,随时将相关命令和脚本整理成一个个文件。另一方面,也是在实际工作中,不仅自己编写了很多实用的脚本,也从Metalink、其它Oracle站点、网上论坛、其他同事,甚至客户那儿吸收了不少。于是,分门别类地就有了有关性能优化、故障诊断、分区、备份恢复、并行处理、10g、11g、12c、ASM、Clusterware、表在线重定义、Flashback、快速增量备份、压缩、坏块处理、DUL、碎片处理、健康检查、资源管理、TimesTen、GoldenGate等林林总总的脚本文件。其实,大家一看就知道,虽然有了分类,但未必科学合理。不过,在很多情况下,毕竟是自己梳理的,找起来非常方便,还非常实用,最终也解决了很多实际问题。

在此也建议读者自己也养成一个良好习惯,那就是在学习和工作中随时进行积累,日积月累地反复总结和提高,我们都会成为技术高手和专家的。只要功夫深,铁杵也能磨成针。

今天,也借写作此书的机会,将我这些“自主知识产权”的东西进行进一步的梳理,限于篇幅,摘取部分常用脚本奉献给诸位。

 

数据库空间使用情况脚本

/*+  数据库总使用空间 */

select sum(bytes)/(1024*1024*1024) from dba_data_files;




/*+  数据库空闲空间 */

select sum(bytes)/(1024*1024*1024) from dba_free_space;




/*+  按表空间显示的使用空间 */

select tablespace_name,sum(bytes)/(1024*1024) from dba_data_files group by tablespace_name order by 1;




/*+  按表空间显示的空闲空间 */

select tablespace_name,sum(bytes)/(1024*1024) Free_M from dba_free_space group by tablespace_name order by 1 ;




/*+  按表空间显示的空间使用率 */

SELECT a.tablespace_name,
sum(a.avail) "Total(Mb)",
sum(nvl(b.free,0)) "Free(Mb)",
nvl(round(((sum(nvl(b.free,0))/sum(a.avail))*100),2),0)  "Free%"
from (select tablespace_name, substr(file_name,1,45) file_name,
             file_id, round(sum(bytes/(1024*1024)),3) avail
      from   sys.dba_data_files
      group by  tablespace_name, substr(file_name,1,45),
                file_id) a,
      (select tablespace_name, file_id,
             round(sum(bytes/(1024*1024)),3) free
      from   sys.dba_free_space
      group by tablespace_name, file_id) b
where a.file_id = b.file_id (+)
group by a.tablespace_name

… …


与性能相关的脚本

 

/*+  查询当前正在运行的长事务(超过6秒)*/

select sid,sofar,totalwork, opname,target,time_remaining,elapsed_seconds,sql_hash_value
from v$session_Longops
where sofar <> totalwork
order by totalwork desc




/*+  查询上述长事务的SQL语句文本 */

select * from v$sqltext where HASH_VALUE=3500072035 order by piece;




/*+  查询所有长事务的SQL语句 */

select distinct hash_value,piece,sql_text  from v$sqltext, V$session_Longops order by HASH_VALUE,piece;



/*+  查询某表的索引设计情况 */

select table_owner,index_name,column_name,column_position from dba_ind_columns where table_name=upper('OP_INJ_WELL_DAILY') order by index_name,column_position;


/*+ 查询某个会话的当前SQL语句 */

select sid,sql_textfrom v$sqltext,v$session where v$sqltext.address=v$session.sql_address and sid=6 order by piece;



/*+ 查询重复分析的SQL语句 */

Select sql_text from v$sqlarea where executions = 1 order by UPPER(sql_text);

… …

 

 

与故障诊断相关的脚本

 

/*+  查询系统最高的等待事件 */

select * from v$system_event order by total_waits Desc;




/*+  某个等待事件的当前语句 */

select sql_text

  from v$sqlarea

 where address in

       (select sql_address

          from v$session

         where sid in (select sid

                         from v$session_wait

                        where event like '%db file scattered read%'))




/*+  查询导致cache buffers chains事件的最热对象 */

select *

  from (select c.owner, c.object_name, sum(a.tch)

          from x$bh a, v$latch_children b, dba_objects c

         where a.hladdr = b.addr

           and a.obj = c.object_id

           and b.name = 'cache buffers chains'

           and c.owner <> 'SYS'

         group by c.owner, c.object_name

         order by sum(a.tch) desc)

 where rownum <= 25;




/*+  根据PID查询SID */

select a.sid,a.serial#,a.status,a.machine,a.program,a.sql_address,a.command from v$session a,v$process b where

a.paddr=b.addr and b.spid='5926'




/*+  根据等待事件查询SID信息 */

select a.sid,b.event, b.p1, b.seq#, b.p2, b.p3, substr(a.program, 1, 20) program, substr(a.machine, 1, 10) machine

  from v$session a, v$session _wait b

 where a.sid = b.sid

   and b.event not like 'SQL%'

   and b.event not like '%time%'

   and b.event not like '%message%'

 order by 2




/*+  根据transaction号查询sid信息 */

select a.sid, a.serial#,a.username,a.status,a.machine,a.program,a.sql_address,a.paddr

  from v$session a, v$transaction b

 where a.taddr = b.addr

   and b.xidsqn = &sqn




/*+  查询当前SGA使用情况 */

select * from v$sgastat;




/*+  查询SGA动态分配情况 */

select component,current_size/(1024*1024) from v$sga_dynamic_components;

select * from V$SGA_DYNAMIC_FREE_MEMORY;




/*+  查询当前PGA的使用情况 */

select * from v$pgastat;




select name, sum(value / (1024 * 1024)) "Value - MB"

  from v$statname n, v$session s, v$sesstat t

 where s.sid = t.sid

   and n.statistic# = t.statistic#

   and s.type = 'USER'

   and s.username is not NULL

   and n.name in ('session pga memory', 'session pga memory max',

        'session uga memory', 'session uga memory max')

 group by name;




/*+  按小时统计日志产生量 */

select to_char(FIRST_TIME, 'yyyy-mm-dd hh24'), count(*)

  from v$log_history

 where thread# = 1

 group by to_char(FIRST_TIME, 'yyyy-mm-dd hh24')

 order by to_char(FIRST_TIME, 'yyyy-mm-dd hh24');




/*+  打开trace */

Exec dbms_session.set_sql_trace(True);




/*+  对某个Session打开Trace */

Exec dbms_session.set_sql_trace_in_session(sid,serial#,True);

… …

 

与分区相关的脚本

 

/*+  查询当前分区表设计总体情况 */

select partitioning_type, subpartitioning_type, count(*)

  from dba_part_tables

 where owner not in ('SYSTEM', 'SYS', 'GLOBAL', 'SH')

 group by partitioning_type, subpartitioning_type;




/*+  查询当前分区表设计详细情况 */

select *

  from dba_tab_partitions

 where table_owner not in ('SYSTEM', 'SYS', 'GLOBAL', 'SH')

 Order By TABLE_OWNER, TABLE_NAME, PARTITION_NAME;




/*+  查询当前分区表的分区字段 */

select * from dba_PART_KEY_COLUMNS Where object_type='TABLE' and owner not in ('SYSTEM','SYS','GLOBAL','SH');




/*+  查询当前分区索引设计总体情况 */

select *
  from dba_part_indexes
 where owner not in ('SYSTEM', 'SYS', 'GLOBAL', 'SH');




/*+ 查询当前分区索引设计详细情况 */

select *
from dba_ind_partitions
where index_owner not in ('SYSTEM','SYS','GLOBAL','SH') 
Order By INDEX_OWNER,INDEX_NAME,PARTITION_NAME,TABLESPACE_NAME
… …




限于篇幅,上述分区脚本没有罗列子分区的脚本,请在上述脚本中进行适当的修改即可,例如dba_tab_partitions修改为dba_tab_subpartitions。详细视图名称请见Oracle相关参考手册。

 

与RAC相关的脚本

 

/*+ RAC实例情况 */

select * from gv$active_instances order by inst_id,inst_number,inst_name;

 

/*+ 分析与GCS有关的等待事件 */

SELECT inst_id, event, p1 FILE_NUMBER, p2 BLOCK_NUMBER, WAIT_TIME

FROM gv$session_wait

WHERE event in (‘buffer busy global cr’, ‘global cache busy’,

‘buffer busy global cache’);

 

/*+ 一致性读(CR)效率分析,AVG RECEIVE TIME (ms)低于10ms表示一致性读(CR)效率正常 */

SELECT b1.inst_id,

b2.value “RECEIVED”,

b1.value “RECEIVE TIME”,

((b1.value / b2.value) * 10) “AVG RECEIVE TIME (ms)”

FROM gv$sysstat b1, gv$sysstat b2

WHERE b1.name = ‘global cache cr block receive time’

AND b2.name = ‘global cache cr blocks received’

AND b1.inst_id = b2.inst_id;

 

/*+ 当前块传输(Current Block Transfer)效率分析,AVG RECEIVE TIME (ms)低于15ms表示当前块传输效率正常 */

SELECT b1.inst_id,

b2.value “RECEIVED”,

b1.value “RECEIVE TIME”,

((b1.value / b2.value) * 10) “AVG RECEIVE TIME (ms)”

FROM gv$sysstat b1, gv$sysstat b2

WHERE b1.name = ‘global cache current block receive time’

AND b2.name = ‘global cache current blocks received’

AND b1.inst_id = b2.inst_id;

 

/*+ 当前块传输(Current Block Transfer)效率分析,AVG RECEIVE TIME (ms)低于15ms表示当前块传输效率正常 */

SELECT b1.inst_id,

b2.value “RECEIVED”,

b1.value “RECEIVE TIME”,

((b1.value / b2.value) * 10) “AVG RECEIVE TIME (ms)”

FROM gv$sysstat b1, gv$sysstat b2

WHERE b1.name = ‘global cache current block receive time’

AND b2.name = ‘global cache current blocks received’

AND b1.inst_id = b2.inst_id;

 

/*+  当前块服务(Current Block Service)效率分析,Current Blk Service Time (ms)低于10ms表示当前块服务效率正常 */

SELECT a.inst_id “Instance”,

(a.value + b.value + c.value) / d.value “Current Blk Service Time”

FROM GV$SYSSTAT A, GV$SYSSTAT B, GV$SYSSTAT C, GV$SYSSTAT D

WHERE A.name = ‘global cache current block pin time’

AND B.name = ‘global cache current block flush time’

AND C.name = ‘global cache current block send time’

AND D.name = ‘global cache current blocks served’

AND B.inst_id = A.inst_id

AND C.inst_id = A.inst_id

AND D.inst_id = A.inst_id

ORDER BY a.inst_id;

 

/*+  全局缓冲转换和获取(Global Cache Convert and Get)分析,Avg Cache Conv. Time(ms)和Avg Cache Get Time(ms)低于10ms表示全局缓冲转换和获取(Global Cache Convert and Get)效率正常 */

SELECT A.inst_id “Instance”,

A.value / B.value “Avg Cache Conv. Time”,

C.value / D.value “Avg Cache Get Time”,

E.value “GC Convert Timeouts”

FROM GV$SYSSTAT A, GV$SYSSTAT B, GV$SYSSTAT C, GV$SYSSTAT D, GV$SYSSTAT E

WHERE A.name = ‘global cache convert time’

AND B.name = ‘global cache converts’

AND c.name = ‘global cache get time’

AND D.name = ‘global cache gets’

AND E.name = ‘global cache convert timeouts’

AND B.inst_id = A.inst_id

AND C.inst_id = A.inst_id

AND D.inst_id = A.inst_id

AND E.inst_id = A.inst_id

ORDER BY A.inst_id;

 

/*+ 全局缓冲区延迟服务(Global Cache Defers)性能分析,上述指标小于0.3为正常值。该指标值高表示事例间由于数据访问集中,导致全局缓冲区出现大量延迟服务 */

SELECT a.inst_id “Instance”,

a.value “Defers”,

b.value “Current Blks Served”,

(a.value) / b.value “Current Blk Service Time”

FROM GV$SYSSTAT A, GV$SYSSTAT B

WHERE A.name = ‘global cache defers’

AND B.name = ‘global cache current blocks served’

AND B.inst_id = A.inst_id

ORDER BY a.inst_id;

… …

 

 

一个项目中的故障诊断

项目概述

数年前,作为Oracle技术咨询顾问,本人为国家某信息安全项目提供了相关服务。该项目数据量高达数百TB,并且需要具有全文检索功能。因此,海量数据的分区方案设计和相关技术应用、Oracle全文索引(Oracle Text)的运用等成为该项目的显著技术特点和难点。而且,为满足海量数据处理需求,当年Oracle刚刚出炉的ASM、Clusterware、大表空间、临时表空间组等新技术也在该项目中初露锋芒。总体而言,我们为该项目提供了如下方面的服务内容:

  • 参与该项目数据库物理设计,特别是分区和ASM方案设计
  • 参与该项目RAC架构设计和高可用性方案设计
  • 参与该项目数据加载方案设计
  • 为该项目提供故障诊断服务
  • 该为项目提供其它技术咨询和支持服务

当年该项目是部署在Oracle刚推出的10.1版本之上,大量运用了很多新技术和新特性,并且也使用到很多应用场景并不多的技术,如Oracle Text。这些都像一把双仞剑,既给该项目带来了鲜明技术特点和先进性,也同时带来了很多风险和问题。因此,本人在该项目前期参加完总体技术方案和关键技术方案设计之后,进入到项目详细实施阶段,则故障不断。这也回到了本章的主题:故障诊断。以下摘取当年一些典型故障,供大家参考。

下面的描述我们基本采取原汁原味方式,一方面大家可体会到当年客户的不满、抱怨等情绪,的确很多故障是Oracle新产品、新技术的Bug问题,但另一方面也有些是客户自己在设计和使用过程中的一些细节问题。这些问题毕竟是在当年的10.1版本,很多已经时过境迁了,但本人依然希望让大家感受一下当年问题的多样性和处理问题的思路。

Oracle Text索引空间不够问题

 

  • 错误现象1

客户的问题描述如下:

“目前我们的索引表空间存在下述问题:

我们的表索引建在表空间idx上,每天(含48个表分区)的索引分别建在表空间idx01,idx02,…上,然后进行分区交换。按道理说idx应该是空的,因为每个分区的索引都建在其它表空间上。但我们在测试中发现idx的被大量占用,而且这个表空间如果小了根本就不能工作。这个问题应该如何解释?我们建的表空间都采用类似下面的语句:

CREATE BIGFILE TABLESPACE “DATA20050408” NOLOGGING

DATAFILE’+DISKGROUP1′ SIZE 68G REUSE

EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64M SEGMENT SPACE MANAGEMENT  AUTO ;

由于我们每天要给表增加新的分区,增加分区时索引空间就会扩展。”

  • 错误现象2

客户的问题描述如下:

“我们在做分区交换时报下列错误:

 

SQL> alter table wyh exchange partition p5 with table wyh_stage5 including indexes

*

ERROR at line 1:

ORA-29955: error occurred in the execution of ODCIINDEXEXCHANGEPARTITION

routine

ORA-20000: Oracle Text error:

DRG-50857: oracle error in drvxtab.exchange_index_tables

User-Defined Exception

DRG-50857: oracle error in drvxtab.swap_index_temp_tables

ORA-00942: table or view does not exist

ORA-06512: at "CTXSYS.DRUE", line 160

ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 804

ORA-06512: at line 2

 

相关信息:

怀疑该问题与回收站有关。清空回收站后第一次运行脚本没有错误,第二次运行就报该错误。再次清空回收站后又能工作。”

  • 错误原因分

上述错误的原因在于数据装载脚本,而不是ASM存储管理的问题。具体原因如下:

  1. 现有脚本将主要业务表(BD_DXX)设计为按时间进行分区。初始建表时建立在缺省的数据表空间和索引表空间(IDX00)上。
  2. 当通过add partition命令增加分区时,Oracle自动维护Local索引。但此时Oracle是将增加分区的索引建立在缺省表空间IDX00上。
  1. 由于IDX00非常小,因空间不够,导致了上述错误:“IDX00被大量占用”以及表空间交换错误。注意:exchange的出错信息均是与索引表相关。
  • 解决办法

在每次执行add partition命令之前,增加如下命令,强制将分区索引建立在指定的索引表空间中:

 

exec ctx_ddl.drop_preference('store_20050425');

begin

ctx_ddl.create_preference('store_20050425', 'BASIC_STORAGE');

ctx_ddl.set_attribute('store_20050425', 'I_TABLE_CLAUSE','tablespace IDX20050425 storage (initial 1M)');

ctx_ddl.set_attribute('store_20050425', 'K_TABLE_CLAUSE','tablespace IDX20050425 storage (initial 1M)');

ctx_ddl.set_attribute('store_20050425', 'R_TABLE_CLAUSE','tablespace IDX20050425 storage (initial 1M) lob (data) store as (disable storage in row cache)');

ctx_ddl.set_attribute('store_20050425', 'N_TABLE_CLAUSE','tablespace IDX20050425 storage (initial 1M)');

ctx_ddl.set_attribute('store_20050425', 'I_INDEX_CLAUSE','tablespace IDX20050425 storage (initial 1M) compress 2');

ctx_ddl.set_attribute('store_20050425', 'P_TABLE_CLAUSE','tablespace IDX20050425 storage (initial 1M)');

end;

alter index idx_bf_dxx rebuild partition P200504250000 parameters(‘REPLACE STORAGE store_20050425’)


这样每次增加的索引都落在指定时间段的表空间中,不会都存储在缺省表空间(IDX00)上而导致上述问题。

诊断该问题之前,开发人员已经将IDX00扩大到100G,已经绕开上述问题。从另一个角度说明,如果分区索引建立在其对应的表空间,就能从根本上解决上述问题。

 

Oracle Text索引交换问题

  • 错误现象

开发人员按如下流程在进行数据的装载和Oracle Text索引的创建,出现如下错误:

 

  1. drop table test_stage;
  2. Create a non-partition table ‘test_stage’
  3. Load huge data by sql*loader into ‘test_stage’
  4. Create a text index on ‘test_stage’
  5. Exchange test_stage with a partition table ‘test’

alter table test exchange partition <> with table test_stage including
indexes;

ORA-38301:can not perform DDL/DML over objects in Recycle Bin

 

  • 错误原因分

这是由于Oracle 10g中一个新特性所诱发。在10g中为了有效地保护数据,减少用户意外操作所导致的数据损失。增加了回收站(recycle bin)的技术。在drop 一张表之后,系统并没有真正删除,而是进入了recycle bin。而为了用户能恢复数据,上述exchange操作仍然在操作recycle bin。而实际上recycle bin中的数据只能进行查询操作,DML、DDL等均不能进行。因此出现了上述ORA-38301错误,无法完成exchange操作。

该问题是否是Oracle产品的bug,Oracle技术支持部门和研发部门正在深入研究之中。

 

  • 解决办法

我们建议:在确定是否是bug之前,先采取饶开问题(Workaround)的方式。即强制不使用Oracle的recycle bin技术。在drop语句之后加上一个选项purge.例如:

drop table test_stage purge;

ASM空间管理问题

  • 错误现象

开发人员按如下流程进行操作:

  1. 重新建立1T容量的Disk Group。
  2. 第一次建立800G左右表空间时,v$disk_asm正常显示200M左右的free_mb。
  3. 在经历了一段时间的create partition table, exchange partition, create Text index等操作后,v$disk_asm显示free_mb为0。
  4. 但此时用户还能在剩余空间内继续创建新的表空间或者扩充现有表空间。
  5. 所有ASM数据文件的autoextenion参数设置为NO。
  • 错误原因分析1

为解决该问题,我们特意创建了一个SR:4376391.995

经Oracle技术支持人员分析,该问题可能与如下3个bug有关:

 

3416266:

Abstract: DISKGROUP SPACE EXHAUSTED ERROR DESPITE HAVING SPACE

4112580

Abstract: FREE_MB OF V$ASM_DISK INCORRECT AFTER 2 DISKS DROPPED

4128156

Abstract: ASM FREE SPACE NOT USED WHEN TABLESPACE CREATION USES MANY, SMALLER FILES

 

  • 错误原因分析2

通过Oracle内部文档《Note:294325.1:“free_mb for v$asm_disk or v$asm_diskgroup reports 0 if queried from db instance”》,上述现象的另一种解释如下:

Oracle在db instance中显示free_mb为0,但在asm instance中则能正常显示free_mb的实际值。Oracle的解释这是产品的正常现象,原因是为了降低db和asm两个instance之间的通信量。但在10g第二版中可能会修改此功能,即db instance中的v$asm_disk也会正常显示free_mb值。

  • 解决办法
  • 第一种原因

非常遗憾,针对上述三个bug,Oracle均没有在Linux Itanium平台单独开发patch。而是包含在10.1.0.5 patchset之中。

解决办法一:向Oracle技术支持和研发部门申请单独的Patch。Oracle称之为backport。

解决办法二:等待9月份发布的10.1.0.5 patchset for Linux Itanium。

  • 第二种原因

可以忽略。或者通过Grid Control来显示正常值。

 

ASM扩盘问题

  • 错误现象

4月4日,Oracle顾问在北京的测试现场进行增加磁盘操作时,由于系统使用了缺省的ASM_POWER_LIMIT=1,导致磁盘的rebalance过程非常长。因此,对正在rebalance的盘进行了drop操作。Drop命令成功之后,v$asm_disk仍然显示DISKGROUP1包含该磁盘。而且ASM事例系统后台出现如下错误:

ORA-7445: CORE DUMP [KFGPPARTNERS()+264] WHEN DOING REBALANCE

  • 错误原因分析和解决办法

针对上述问题1,Oracle顾问建立了SR:4376391.995。根据Oracle技术支持部门的分析,确认该问题是Bug:3631330。详细情况如下:

Abstract: ORA-7445: CORE DUMP [KFGPPARTNERS()+264] WHEN DOING REBALANCE

Details:

Internal ASM state does not properly reflect a disk drop. v$asm_disk then contains disks that do not belong to a diskgroup after the drop.Subsequent operations may also dump (eg: in kfgpPartners)

The bug is fixed in 10.1.0.4.

There is no workaround mentioned in the bug.

 

从Oracle内部站点了解到,Oracle针对Linux Itanium只提供10.1.0.5 patchset。根据初步计划,该patchset将在2005.8.29才提供。而且没有Bug: 3631330的单独patch。

实际上,我们按正常操作次序,重新建立了DISK GROUP,一切正常。即该问题是一种特定情况下才会发生。

数据库core文件问题

  • 错误现象

在数据库运行期间,在RAC1和RAC4两组RAC环境中,均出现如下现象:在$ORACLE_HOME/bin目录下每隔10分钟,出现一个core文件,大小为81M左右。消耗了大量/home区的本地磁盘资源,当磁盘资源消耗到100%之后,导致数据库崩溃。

  • 错误原因分析

通过 SR : 4441689.993,15406066.6分析,该问题是与如下两个bug有关:

Bug 4401180 – ONS CORES DUMP IN MALLOC_Y

Bug 3924540 – ONS PROCESS CRASHES EVERY 10 MINS

 

  • 解决效果

在6月29日和6月30日分别对RAC1和RAC4的8台数据库安装该patch之后,没有再出现core文件。该问题已经得到解决。

 

ORA-12805错误

  • 错误现象

在测试期间进行查询操作的时候,会比较频繁地出现ORA-12805: parallel query server died unexpectedly。

  • 原因分析和解决办法

该错误有两种原因:

  • 原因1:属于正常现象

在此情况下,是将RAC环境配置成了一个或多个并行节点组,实现节点间的并行处理。主要是通过instance_groups、parallel_instance_group参数进行这种设置。

当并行节点组内的一个节点的Oracle事例被关闭时,在正常工作的节点会出现ORA-12805: parallel query server died unexpectedly错误。该现象是正常情况。Oracle的TAF只能提供当客户端到服务器端出现故障时,进行透明的切换。而服务器和服务器之间的并行处理作业出现故障时,不能提供透明切换功能。

该错误的解决办法是重新执行一遍查询语句。或不启动并行操作。

详情请见:《A Parallel Query Errors Out With ORA-12805 When The Other Node Crashes in RAC or OPS (Doc ID 200260.1)》

  • 原因2:Bug 3649839

第二种原因是Bug 3649839导致。即:Intermittent ORA-12805 on internode parallel create/rebuild index

可惜Oracle没有在10.1.0.3中提供独立的patch 3649839。而是含在2005年8月份发布的10.1.0.4中。

根据测试环境的实际配置,我们认为该错误是第二种原因所导致。我们会根据客户需要,请求Oracle研发部门在10.1.0.3中提供相关patch。

 

10.7本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database Administrator’s Guide》 该文档是DBA必读文档,涵盖了DBA日常运维管理工作的方方面面。作为DBA,故障诊断是其重要工作职责,此文档也提供了与日常运维管理相关的诸多常见故障的处理过程。
2. Oracle 11g R2联机文档 《Oracle® Database Performance Tuning Guide》 DBA的一项重要工作就是性能分析和优化。该文档是Oracle联机文档中有关优化的专著,不仅有优化方法论,也有多种性能诊断工具和优化方法的介绍。
3. My Oracle Support 《CRS Installation Failed with “failed to configure Oracle Cluster Registry with CLSCFG, ret 9” [ID 851742.1]》 这就是本章第一节案例中,CRS无法安装的原因分析和解决过程的文档。
4. My Oracle Support 《Remote Diagnostic Agent (RDA) – Getting Started (Doc ID 314422.1)》 介绍RDA的标准文档。什么是RDA?如何下载?如何使用?如何上传RDA报告?……
5. My Oracle Support 《Automatic Workload Repository (AWR) Reports – Start Point (Doc ID 1363422.1)》 了解AWR的入门文档,也是深入了解AWR的起点。
6. My Oracle Support 《How to Use AWR Reports to Diagnose Database Performance Issues (Doc ID 1359094.1)》 AWR报告一个重要作用就是用于诊断性能问题。该文档包括了更多通过AWR报告分析性能问题的文档。
7. My Oracle Support 《How To Investigate Slow or Hanging Database Performance Issues (Doc ID 1362329.1)》 数据库慢或挂起了,怎么办?别着急,先分清楚究竟是慢还是挂起,然后通过10046、AWR、Errorstack、ADDM等去收集数据,进行诊断。
8. My Oracle Support 《Best Practices: Proactive Data Collection for Performance Issues (Doc ID 1477599.1)》 解决性能问题最有效的办法就是主动预防和提前诊断。该文档从方法论,到诊断工具等,相信大家从中收获不少。
9. My Oracle Support 《FAQ: Database Performance Frequently Asked Questions (Doc ID 1360119.1)》 数据库发生性能问题涉及太多方面了。如何诊断和分析?该文档介绍了Oracle的最佳实践经验,例如如何主动进行避免性能问题,也介绍了100046、systemstates、Errorstack等诊断工具,以及Log File Sync、Cache Buffers Chains Latch等与性能相关的等待事件的处理。
10. My Oracle Support 《Oracle Clusterware 10gR2/ 11gR1/ 11gR2/ 12cR1 Diagnostic Collection Guide (Doc ID 330358.1)》 这是一篇专门介绍如何收集Clusterware诊断信息的工具DiagCollection的文档,就在整理该文档时,才发现该工具过时了,应该采用新的TFA Collector工具。这就是日新月异的IT行业,呵呵。
11. My Oracle Support 《TFA Collector – Tool for Enhanced Diagnostic Gathering (Doc ID 1513912.1)》 TFA Collector是Oracle最新的诊断信息收集工具,比DiagCollection功能更强、更有效。大家慢慢开始学会使用这个新工具吧。
12. My Oracle Support 《RACcheck – RAC Configuration Audit Tool (Doc ID 1268927.1)》 又一个被新工具替换的工具。新工具叫做:ORAchk
13. My Oracle Support 《EVENT: 10046 “enable SQL statement tracing (including binds/waits)” (Doc ID 21154.1)》 专门讲述设置10046事件的文档。
14. My Oracle Support 《Interpreting Raw SQL_TRACE output (Doc ID 39817.1)》 如何看懂像天书一样的SQL_TRACE输出文件?请看这篇文档吧。
15. My Oracle Support 《How to Collect Diagnostics for Database Hanging Issues (Doc ID 452358.1)》 如何诊断数据库挂起问题?一个首要工作就是收集相关信息。
16. My Oracle Support 《Troubleshooting Database Contention With V$Wait_Chains (Doc ID 1428210.1)》 这就是有关11g v$wait_chains的官方详细文档。

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟:11g性能管理新工具:SPM

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

我们经常会遇到应用软件在开发测试环境和生产环境性能不一致的问题,以及升级之后应用性能衰减等问题。除去管理、实施、沟通、协调等因素,一个重要原因就在于不同环境绝对隔离,相互之间缺乏有效的关联技术。例如开发测试环境和生产环境是相互独立的,升级前后的系统也是相互独立的。

11g新的性能管理工具SPM就是这种不同环境之间的关联技术。通过SPM,我们可以将开发测试环境和生产环境,以及升级前后的系统有效地关联起来,使得不同环境之间的应用软件性能不会出现衰减。

本章先从一些典型场景和问题着手,然后全面介绍SPM原理和运用过程,以及SPM的管理等技术点,最后将介绍有关SPM的更多参考资料。

 

一些典型场景

  • 典型场景1

“系统性能这么差,肯定是应用软件问题,这帮开发人员可能就没有好好测试,就直接投到生产系统了。”—- 负责运维的DBA经常这么抱怨道。

“我们的应用在开发和测试环境都跑得好好的,肯定是这帮DBA瞎改什么配置,搞得应用出了问题,特别是把语句执行计划搞得变了。”—- 应用开发团队一方面觉得委屈,另一方面又觉得问题可能是出在生产系统环境。

在很多大型企业,特别是国企,应用软件设计开发和系统运行维护分属两个相对独立的部门或团队,管理上的过于职责分明和缺乏有效沟通更加剧了这种分歧和对立。

  • 典型场景2

日益发展的IT技术既给现有IT系统提供了更先进的平台和更广泛的技术,但系统升级、变更可能带来的风险,又让决策者们彷徨犹豫。终于升级到11g了,但是新系统却出现了性能衰减。于是,各方抱怨又纷至沓来:

“我们原来在10g跑得好好的,怎么一跑到11g就出现这么多问题,你们11g到底行不行啊?” —- 应用开发、运维等各方客户齐声抱怨道。

“我们不敢奢望11g比10g跑得快,但你们Oracle能不能保证我们的应用在11g下起码别比10g跑得慢啊?” —- 客户几乎是在哀求了。

“… …”

针对上述一些典型场景和客户需求,除了需要在项目管理、沟通协调等方面加强工作之外,Oracle在技术方面有什么招数吗?有!Oracle 11g的SPM(SQL Plan Management)就是解决上述问题的典型技术。

 

SPM原理

传统技术手段

众所周知,SQL语句执行性能好坏主要取决于语句执行计划,而Oracle优化器特别是基于成本优化器(CBO),主要依靠所访问表和其它对象的统计信息、优化器版本、优化器参数、系统硬件配置和参数设置、SQL Profile等信息,来综合分析并确定语句最佳执行计划。保证语句执行计划最优和稳定的一种重要手段就是统计信息的准确性和实时性,大部分DBA和开发人员也深知及时采集和更新统计信息的重要性。但确定执行计划的因素的确太多,例如上述的优化器版本、参数等信息,因此仅仅依靠统计信息还不能确保语句执行计划的最优化和稳定性。

Oracle传统上有哪些保证语句执行计划稳定性的技术呢?第一种就是在语句中增加提示(HINT),强制Oracle优化器采用某种固定的执行计划。另一种就是使用存储大纲(Stored Outline)技术,即将优化的执行计划提示信息存储在Oracle内部一组表格中,强制相关SQL语句使用这些存储大纲。这两种技术一个共同特点就是将相关SQL语句的执行计划固定下来,而不考虑未来环境变化,例如数据库版本升级之后是否会带来新的更优化的执行路径。

SQL Profile则是Oracle从10g开始提供的另一种确保语句执行计划最优化的技术。相比表和索引有统计信息,SQL Profile就是一条SQL语句的统计信息。例如,当我们遇到一个复杂且资源消耗非常大SQL语句时,Oracle可采用一些取样数据,或者可以执行该语句一个片段,以及分析该语句的历史执行情况,这些信息就是语句的SQL Profile。Oracle通过预先采集SQL Profile信息,来评估整体执行计划是否最优化。即当Oracle正式执行该SQL语句时,优化器不仅利用该语句所访问对象的统计信息,而且利用已产生的该语句SQL Profile信息,来产生整体上更优的执行计划。

11g SQL执行计划管理技术:SPM

在上述传统性能管理技术基础上,Oracle 11g推出了更先进的SQL执行计划管理技术:SPM,全称为SQL Plan Management技术。

SPM在原理上通过维护一个SQL执行计划的基线(Baseline),来自动控制SQL语句执行计划的演化过程。当启用SPM技术之后,优化器新产生的执行计划只有证明不会导致性能衰减时,才能加入到执行计划基线中。也就是说,只有基线中的执行计划才能被真正执行。如后所述,Oracle可以自动产生SQL语句的执行计划基线,也可以通过SQL Tuning Sets等手工方式产生。

SPM的最大好处就在于维持SQL语句的性能稳定性,避免性能衰减,同时也能有效减轻DBA工作负担,使得DBA们不用花费大量精力去识别、分析性能衰减问题并加以解决。

以下就是SPM原理图:

 

spm1

 

在启用SMP技术之后,当一个SQL语句被重复执行多遍,Oracle会将这些语句记录在语句日志(Statement log)中,优化器也会将这些语句的执行计划保存于执行计划历史(Plan History)记录中,包括SQL语句文本、Outline、绑定变量、编译环境信息等。当优化器新产生一个语句执行计划时,只有当Oracle通过验证该执行计划不会导致性能衰减之后,才会加入到Plan Baseline中并得到使用。而这种验证工作则是11g新的自动SQL优化任务(Automatic SQL Tuning Task)中的一部分,该任务将在每天晚上的维护窗口自动运行,并只针对资源消耗过大的SQL语句进行分析。该任务将自动分析这些新执行计划,并验证是否为可接受的(Accepted),同时加入Plan Baseline中。这样,Plan Baseline中的执行计划都是Accepted的。显然,一个语句的第一个执行计划构成最初的的Plan Baseline,但后续新产生的执行计划则只是保存在Plan History中,只有当验证性能不衰减之后,才能加入Plan Baseline。

如上图所示,Statement log、Plan history、Plan baseline和SQL Profile等都存储在SQL Management Base(简称SMB)中,SMB其实是数据字典一部分并存储在SYSAUX表空间中。针对SMB,Oracle提供了自动空间管理功能,例如保存期限、空间限额等,后面将详细介绍之。

 

 SPM使用过程

SPM使用主要分为如下两种方式:

快速逐次捕获(On the fly capture)

通过设置初始化参数OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES为TRUE,将开启SPM的快速逐次捕获(On the fly capture)功能,该参数缺省值为FALSE。同时参数OPTIMIZER_USE_SQL_PLAN_BASELINES保持为缺省值TRUE。

如下图所示,当该参数设置为TRUE之后,Oracle将自动识别重复执行的SQL语句,并将记录在Plan History中。其中第一次执行的SQL语句执行计划将自动成为Plan Baseline。

spm2

批量加载(Bulk loading)

如下图所示,通过dbms_spm包,DBA可手工批量加载(Bulk loading)SQL语句的Plan Baseline。

spm3

 

具体而言,包括如下三种方式:

  • 通过LOAD_PLANS_FROM_CURSOR_CACHE过程从cursor cache中加载。例如:

SQL> exec DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(<sql-id>);

  • 通过LOAD_PLANS_FROM_SQLSET过程从STS(SQL tuning set)中加载。例如:

SQL> exec DBMS_SPM.LOAD_PLANS_FROM_SQLSET(‘mySQLTuningSet1’)

  • 通过*_STGTAB_BASELINE过程创建一个中间表(Stage表),并通过Data Pump将这些表迁移到目标数据库中。

SPM适用场景

升级场景

以下是10g到11g中SPM的使用示意图:

spm4

以下是详细介绍使用过程:

 

首先在现有10g环境将捕获的SQL语句执行计划存储在STS 中,例如:

 

BEGIN
DBMS_SQLTUNE.CREATE_SQLSET('STS102WKLD');
DBMS_SQLTUNE.CAPTURE_CURSOR_CACHE_SQLSET(
sqlset_name => 'STS102WKLD',
time_limit => 120,
repeat_interval => 5);
END;
/


上述脚本首先创建一个名称为STS102WKLD的STS,其次采集时长为120秒,每隔5秒采集一次当前SQL语句执行计划于该 STS中。

然后执行如下脚本:

BEGIN
DBMS_SQLTUNE.CREATE_STGTAB_SQLSET(table_name => 'STGTAB102');
DBMS_SQLTUNE.PACK_STGTAB_SQLSET(
     sqlset_name => 'STS102WKLD',
     staging_table_name => 'STGTAB102');
END;
/



即先创建一个名为STGTAB102的中间表,并将STS102WKLD中的内容包装到STGTAB102中。

  1. 执行如下脚本:

$ exp system/manager file=STGTAB102.dmp tables=STGTAB102

$ imp system/manager file=STGTAB102.dmp full=y

 

即通过export/import将STGTAB102表内容导入到11g目标数据库中。

  1. 执行如下脚本:
DECLARE
my_plans pls_integer;
BEGIN
DBMS_SQLTUNE.UNPACK_STGTAB_SQLSET(
     sqlset_name => 'STS102WKLD',
     sqlset_owner => '%',
     replace => TRUE,
     staging_table_name => 'STGTAB102');
my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(
     sqlset_name => 'STS102WKLD',
     sqlset_owner => 'SYS',
     basic_filter => 'sql_text like ''%''',
     fixed => 'YES',
     enabled => 'YES',
     commit_rows => 1);
END;
/




上述脚本先将STGTAB102表打开并存储到名为STS102WKLD的STS中,然后再通过LOAD_PLANS_FROM_SQLSET过程将这些语句的执行计划导入到Plan Baseline中。

升级中SPM的进一步使用场景

以下是在升级过程中,SPM的进一步使用场景示意图:

 

spm5

 

以下是详细使用过程:

  • 在升级到11g之后的初始阶段,例如一个季度内,将优化器参数optimizer_features_enable先保留为升级前的版本,如2.0.2,并运行相关应用,同时通过设置optimizer_capture_sql_plan_baselines=true,自动捕获相关语句在10.2.0.2优化器下生成的最佳执行计划,并加入到baseline中。
  • 当升级到11g之后的初始阶段结束后,将optimizer_features_enable参数设置到新版本值,如2.0.1。这样,如果新版本优化器产生了衰减的执行计划,Oracle也会使用升级前优化器产生的执行计划,确保性能不衰减。而且,新版本优化器可能产生性能更好的SQL语句执行计划。

新软件开发场景

在11g环境下假设已经使用了SPM技术,可将SQL Plan Baselines数据在开发、测试和生产数据库之间进行迁移,确保性能的稳定。以下就是示意图:

 

spm7

以下就是详细使用过程:

  1. 在开发测试环境执行如下脚本:
DECLARE
spm number;
BEGIN
DBMS_SPM.CREATE_STGTAB_BASELINE(
     table_name=>'SPM_SAVED',
     table_owner=>'SYSTEM');
spm := DBMS_SPM.PACK_STGTAB_BASELINE(
     table_name=>'SPM_SAVED',
     table_owner=>'SYSTEM');
END;
/

 

即先创建一个名为SPM_SAVED的stage表,再将SQL Plan Baselines数据导入SPM_SAVED表。

  1. 在开发测试和生产环境分别执行如下脚本:

$ exp system/manager file=SPM_SAVED.dmp tables=SPM_SAVED

$ imp system/manager file=SPM_SAVED.dmp full=y

 

即通过export/import将SPM_SAVED表内容导入到11g生产数据库中。

  1. 在生产环境执行如下脚本:
DECLARE
spm number;
BEGIN
spm := DBMS_SPM.UNPACK_STGTAB_BASELINE(
table_name=>'SPM_SAVED',
table_owner=>'SYSTEM');
END;
/

 

即将SPM_SAVED表内容导入到11g生产数据库的SQL Plan Baselines中。

 

SPM相关技术点

SQL Plan Baseline的演化过程

当优化器产生一个语句的新执行计划,Oracle将该执行计划作为一个非接受(nonaccepted)执行计划保存在执行计划历史记录(Plan history)中。只有当该执行计划被验证不会导致性能衰减,才会加入到SQL Plan Baseline中。所谓执行计划验证过程也叫执行计划演化过程,就是将新的、非接受的执行计划与SQL Plan Baseline中某个执行计划进行比较,并确保该执行计划性能更佳的过程。通常,可通过如下两种方式进行验证:

  • 通过EVOLVE_SQL_PLAN_BASELINE函数

例如,如下语句:

 

variable report clob

exec :report:=DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(-
sql_handle=>'SYS_SQL_593bc74fca8e6738');


Print report

 

 

该语句将返回一个报告,告知执行计划历史记录中的指定执行计划是否被通过验证,并加入到Plan Baseline中。

  • 通过运行SQL Tuning Advisor

通过手工和自动运行SQL Tuning Advisor,将对执行计划历史记录中的指定执行计划进行验证和演化。当SQL Tuning Advisor发现新执行计划性能好于SQL Plan Baseline中某个执行计划,则新执行计划加入到SQL Plan Baseline中。

SPM相关视图

与SPM相关的主要视图是dba_sql_plan_baselines,例如:

 

select signature, sql_handle, sql_text, plan_name, origin, enabled, 
        accepted, fixed, autopurge
from dba_sql_plan_baselines;
SIGNATURE  SQL_HANDLE  SQL_TEXT PLAN_NAME       ORIGIN       ENA ACC FIX AUT
--------- ------------ -------- ---------------- ------------ --- --- --- ---
8.062E+18 SYS_SQL_6fe2 select.. SQL_PLAN_6zsn…   AUTO-CAPTURE YES NO  NO  YES
8.062E+18 SYS_SQL_e23f select.. SQL_PLAN_f4gy…   AUTO-CAPTURE YES YES NO  YES
…



其中:

  • SIGNATURE, SQL_HANDLE, SQL_TEXT和 PLAN_NAME等字段主要用于查询条件之用。
  • ORIGIN字段则表示该Plan Baseline是自动捕获(AUTO-CAPTURE),还是手工加载(AUTO-CAPTURE),以及通过SQL Tuning Advisor手工(MANUAL-SQLTUNE)或自动演化(AUTO-SQLTUNE)而来。
  • ENABLED和 ACCEPTED字段。只有当ENABLED和 ACCEPTED字段都为Yes,优化器才考虑使用该执行计划。ENABLED字段表示该执行计划为可使用状态,而ACCEPTED字段表示该执行计划是否为Baseline。通过ALTER_SQL_PLAN_BASELINE()函数,可以将一个Baseline执行计划临时设置为不可用的,例如:
exec :cnt := dbms_spm.alter_sql_plan_baseline(-
               sql_handle => 'SYS_SQL_6fe28d438dfc352f', -
               plan_name       => 'SQL_PLAN_6zsnd8f6zsd9g54bc8843',-
               attribute_name  => 'ENABLED', attribute_value => 'NO');

 

  • FIXED字段值为Yes,则表示优化器只考虑该执行计划。例如,假设一个SQL语句有10个Baseline执行计划,其中3个为FIXED,则优化器只考虑3个FIXED的执行计划。一个Plan Baseline如果包含至少一个FIXED执行计划,则该Plan Baseline称之为FIXED Plan Baseline。如果一个新执行计划加入到FIXED Plan Baseline中,只有当新执行计划为FIXED的,该执行计划才可使用。

同样地,通过DBMS_SPM.ALTER_SQL_PLAN_BASELINE()函数,可将一个Plan Baseline执行计划设置为FIXED的,或反之。

DBMS_SPM包的更详细内容,请参考《Oracle® Database PL/SQL Packages and Types Reference11g Release 2 (11.2)》相关章节。

SPM数据的自动管理

以下是SPM数据的自动管理示意图:

 

spm8

 

SPM数据SMB(SQL Management Base)存储在SYSAUX表空间中,SMB空间上限缺省值为SYSAUX表空间的10%,Oracle自动每周对SMB空间进行检测。通过如下命令,可调整SMB空间上限值SPACE_BUDGET_PERCENT,例如:

SQL> exec dbms_spm.configure(‘SPACE_BUDGET_PERCENT’,20);

SPACE_BUDGET_PERCENT取值范围为1到50。

如果SMB空间超过了上限,Oracle将警告信息记录在alert.log文件中,直至SMB空间上限值扩大,或者SYSAUX空间扩大,或者通过删除SQL Plan Baseline、SQL Profile之后,使得SMB空间下降。

Oracle每周定期主动对53周(1年)没有使用到的SQL Plan Baseline数据进行清理,该任务每周在维护窗口自动运行。通过如下命令,可调整保存期限值PLAN_RETENTION_WEEKS,例如:

SQL> exec dbms_spm.configure(‘PLAN_RETENTION_WEEKS’,105);

PLAN_RETENTION_WEEKS取值范围为5到523,即5周到10年。

通过如下视图,可查询SMB的当前配置:

SQL> select * from DBA_SQL_MANAGEMENT_CONFIG;

通过如下命令,可手工删除SMB相关数据:

SQL> exec :cnt := dbms_spm.drop_sql_plan_baseline(‘SYS_SQL_37e0168b04e73efe’);

 

本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database Performance Tuning Guide》 请大家重点阅读第15章 “Using SQL Plan Management”和第20章“Using Plan Stability”
2. My Oracle Support 《Master Note: Plan Stability Features (Including SQL Plan Management (SPM)) (Doc ID 1359841.1)》 了解SPM技术的主目录文档。
3. My Oracle Support 《FAQ: SQL Plan Management (SPM) Frequently Asked Questions (Doc ID 1524658.1)》 针对SPM,大家一定有形形色色的各类问题,估计大家的绝大部分问题都能在这篇文档中找到答案。
4. My Oracle Support 《How to Use SQL Plan Management (SPM) – Example Usage (Doc ID 456518.1)》 使用SPM技术的一个详细例子。
5. My Oracle Support 《Loading Hinted Execution Plans into SQL Plan Baseline. (Doc ID 787692.1)》 原来的SQL语句通过Hint方式确保了执行计划的最优化,如何将这个执行计划变成SQL Plan Baseline?这篇文档给出了详细的过程。
6. My Oracle Support 《How To Configure Automatic Purge(Drop) Of SQL Plan Baseline(SPM). (Doc ID 1438701.1)》 SPM的Baseline数据缺省保存一年,如何调整保存期限?这篇文档给出了具体方法。
7. My Oracle Support 《How to Load SQL Execution Plans in to a STS so that they can be Transferred (to 11g) and Loaded into a SQL Plan Baseline. (Doc ID 801033.1)》 该文档介绍了如何将10g的执行计划导入STS,并最终导入到11g的SPM的详细过程。
8. My Oracle Support 《HOW TO LOAD SQL PLANS INTO SPM FROM AWR (Doc ID 789888.1)》 如何将AWR中的SQL执行计划导入到SPM?这篇文档给出了详细过程。

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟: 11g性能优化新技术: SQL Query Result Cache

 

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

第一次听说SQL Query Result Cache这个11g新技术,是在2007年11月的Oracle公司内部11g培训课程中。可能是因为11g新特性太多,而且那次连续几天的培训,被老师轰炸得审美疲劳了,对这个新技术并没有留下太深印象。当时只是感觉Oracle又多了个什么Cache,也没完全弄明白其原理,也不知道与传统Buffer Cache有什么区别,更不知道这个技术适合于什么场景。

待日后有精力再深入研究该技术,特别是结合客户相关实际问题,才猛然发现Oracle这个新技术太牛了!Oracle公司也太富有创新能力了,居然在几十年难得一动的SGA和Shared_Pool内存架构中增加了Result Cache结构,并提供了新的SQL Query Result Cache技术,解决了很多重复查询语句导致资源开销过大的典型问题。

Result Cache到底是什么新技术?如何使用?适合于什么应用场景?… …。希望本章的内容能回答这些问题,更希望您别像我当年一样,仅仅是走马观花地了解一下而已,而是能立马激动起来,并能运用到您的实际应用开发工作中去。呵呵。

Result Cache原理

基本原理

11g出了个SQL Query Result Cache的新特性,简称Result Cache技术吧。其基本原理就是将SQL语句查询结果数据直接存储在内存中,这样后续相同查询语句就直接从该内存中读取了,这将极大地提高该类语句重复查询性能。

为此,Oracle在SGA的Shared Pool内存中专辟了一个Result Cache内存,如下图所示:

 

result_cache1

 

 

 

 

 

 

 

 

 

以下就是Result Cache的工作原理图:

result_cache2

 

 

 

即:

  1. 当第一个会话进行第一次查询时,将首先从硬盘读取数据 。
  2. 第一个会话同时将该数据存储在SQL Query Result Cache区域 。
  3. 第二个会话进行相同语句查询时,Oracle直接从SQL Query Result Cache区域读取数据 ,将极大地提升查询效率。

可见,Result Cache具有跨语句、跨会话能力,同时当数据发生变更时,Result Cache中相关数据将变为非法(INVALID)状态,Oracle会自动重新从硬盘读取变更数据,并再次存储在Result Cache之中。

 

Result Cache与Buffer Cache的区别

当2007年11月在参加11g新特性培训中,第一次听说这个技术时,一时没有反应过来:“Oracle不是将查询数据已经存储在Buffer Cache中了吗?怎么又来一个Result Cache呢?”后来,稍加琢磨,反应过来了:Buffer Cache中存储的是需要访问的数据,其作用只是将需要到硬盘访问的数据变为内存访问了,而Result Cache是访问数据的结果数据。因此,Result Cache的作用比Buffer Cache有效多了。

例如:


SELECT department_id, AVG(salary)
FROM emp
GROUP BY department_id;
… …
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      16045  consistent gets
          0  physical reads
          0  redo size
        726  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         12  rows processed



上述语句如果使用Buffer Cache技术,Oracle只是将employees表所有记录存储在Buffer Cache中,后续语句仍然要从Buffer Cache中访问employees表所有记录,并进行按department_id的部门平均工资统计,例如上述语句依然有16045次consistent gets访问。而如果使用了Result Cache技术,Oracle则将该语句如下查询结果存储到Result Cache中:


DEPARTMENT_ID AVG(SALARY)

------------- -----------
          100  8601.33333
           30        4150
                     7000
           20        9500
           70       10000
           90  19333.3333
          110       10154
           50  3475.55556
           40        6500
           80  8955.88235
           10        4400
           60        5760


已选择12行。


后续语句直接从Result Cache中访问这些结果数据,显然结果数据比明细数据少得多。再看该语句的资源消耗情况:

 

 SELECT /*+ RESULT_CACHE */ department_id, AVG(salary)
 FROM emp
 GROUP BY department_id;
… …
统计信息

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

          0  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
        726  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         12  rows processed

可见,此时Oracle不仅没有访问硬盘(physical reads = 0),而且也根本没有访问Buffer Cache(consistent gets=0)!

因此,Result Cache技术非常适合于满足如下条件的场景:

  • 查询的记录数很多,但返回结果数据较少的应用
  • 重复查询频度比较高
  • 数据相对静态,变化量不大

例如,数据仓库系统的各种统计运算就是比较典型的应用场景。

 

 Result Cache使用过程

初始化参数的设置

欲使用Result Cache,首先需要考虑初始化参数的设置。以下是几个典型参数的含义和配置建议:

  • RESULT_CACHE_MODE

该参数表示是否需要采用Result Cache技术,取值如下:

  • MANUAL:表示当在语句中增加相关HINT(RESULT_CACHE)时,才使用Result Cache技术。该值为缺省值。
  • FORCE:表示只要有可能,所有查询语句都将使用Result Cache技术。

无论该参数如何设置,Oracle将优先考虑RESULT_CACHE和NO_RESULT_CACHE的 hint。

  • RESULT_CACHE_MAX_SIZE

该参数设置Result Cache的最大容量。如果设置为0,则将关闭Result Cache功能。该参数的缺省值,依赖于内存管理模式和相关参数配置。例如:

  • 当只设置memory_target参数时,RESULT_CACHE_MAX_SIZE = memory_target*0.25%。
  • 当设置sga_target参数时,RESULT_CACHE_MAX_SIZE = sga_target*0.5%。
  • 当设置shared_pool_size参数时,RESULT_CACHE_MAX_SIZE = shared_pool_size*1%。

该参数最大不能超过shared_pool_size的75%。

  • RESULT_CACHE_MAX_RESULT

该参数为单个SQL查询语句设置可使用的最大Result Cache容量,缺省为RESULT_CACHE_MAX_SIZE的5%。

  • RESULT_CACHE_REMOTE_EXPIRATION

该参数表示当SQL语句访问远程数据库对象时,允许远程对象数据发生变化的过期时间。缺省值为0,表示一旦远程对象数据发生变化,相关查询的Result Cache数据变为INVALID。

Result Cache的使用

当上述初始化参数设置好之后,我们就可以考虑Result Cache技术的使用了。通常,我们不建议通过采取RESULT_CACHE_MODE设置为FORCE而强制使用Result Cache的策略。因为,这将导致系统将所有查询操作结果都考虑进行缓存,反而会增加系统不必要的开销。

如果将RESULT_CACHE_MODE设置为MANUAL,则语句中应增加/*+ RESULT_CACHE */的HINT。如下例所示:

SELECT /*+ RESULT_CACHE */ department_id, AVG(salary)

FROM emp

GROUP BY department_id;

执行计划如下:

result_cache3

 

可见,执行计划中增加了RESULT CACHE操作,所访问的Object Name “8k66uas70mk859zxgaq75kfq9u”是该语句结果集在Result Cache中的编号(Cache_ID)。

以下语句就是强制不使用Result Cache技术,即便RESULT_CACHE_MODE设置为FORCE。

SELECT /*+ NO_RESULT_CACHE */ department_id, AVG(salary)

FROM emp

GROUP BY department_id;

 

再看如下语句:

SELECT prod_subcategory, revenue
FROM (SELECT /*+ RESULT_CACHE */ p.prod_category,
                                  p.prod_subcategory,
                                  sum(s.amount_sold) revenue
      FROM products p, sales s
       WHERE s.prod_id = p.prod_id and
            s.time_id BETWEEN to_date('01-JAN-2006','dd-MON-yyyy')
                              and
                              to_date('31-DEC-2006','dd-MON-yyyy')
      GROUP BY ROLLUP(p.prod_category, p.prod_subcategory))
WHERE prod_category = 'Women';

 

如果在上述in-line视图中使用了Result Cache技术,Oracle将不会再进行视图的合并(Merge)等变更操作,而是直接将视图结果存储在Result Cache中,后续查询包括外围条件发生变化,例如prod_category = ‘Men’,都将使用Result Cache技术。

 

Result Cache的管理

DBMS_RESULT_CACHE包的使用

通过11g的 DBMS_RESULT_CACHE包,可以对Result Cache进行相关管理工作:

  • Result Cache状态

如下语句可查询Result Cache状态:

SQL> SELECT DBMS_RESULT_CACHE.STATUS FROM DUAL;

STATUS

——–

ENABLED

 

  • Result Cache的使用情况

如下语句可查询Result Cache的使用情况:

SQL> set serveroutput on;

SQL> exec DBMS_RESULT_CACHE.MEMORY_REPORT;
R e s u l t   C a c h e   M e m o r y   R e p o r t

[Parameters]
Block Size          = 1K bytes
Maximum Cache Size  = 3168K bytes (3168 blocks)
Maximum Result Size = 158K bytes (158 blocks)
[Memory]
Total Memory = 107812 bytes [0.044% of the Shared Pool]
... Fixed Memory = 9460 bytes [0.004% of the Shared Pool]
... Dynamic Memory = 98352 bytes [0.040% of the Shared Pool]
....... Overhead = 65584 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 29 blocks
........... Used Memory = 3 blocks
............... Dependencies = 1 blocks (1 count)
............... Results = 2 blocks
................... SQL     = 2 blocks (2 count)




PL/SQL 过程已成功完成。

 

 

  • 清空Result Cache

如下语句可清空Result Cache,包括所有已存在的结果集数据:

SQL> exec DBMS_RESULT_CACHE.FLUSH;

PL/SQL 过程已成功完成。

SQL> exec DBMS_RESULT_CACHE.MEMORY_REPORT;

R e s u l t   C a c h e   M e m o r y   R e p o r t
[Parameters]
Block Size          = 1K bytes
Maximum Cache Size  = 3168K bytes (3168 blocks)
Maximum Result Size = 158K bytes (158 blocks)
[Memory]
Total Memory = 9460 bytes [0.004% of the Shared Pool]
... Fixed Memory = 9460 bytes [0.004% of the Shared Pool]
... Dynamic Memory = 0 bytes [0.000% of the Shared Pool]




PL/SQL 过程已成功完成。

 

  • 将指定表的Result Cache设置为INVALID

如下语句将HR用户下的EMP表的Result Cache设置为INVALID:

SQL> EXEC DBMS_RESULT_CACHE.INVALIDATE(‘HR’,’EMP’);

PL/SQL 过程已成功完成。

 

相关视图的使用

  • (G)V$RESULT_CACHE_STATISTICS

该视图显示Result Cache设置和该内存使用情况的统计信息。例如:

ID NAME VALUE
1 Block Size (Bytes) 1024
2 Block Count Maximum 3168
3 Block Count Current 32
4 Result Size Maximum (Blocks) 158
5 Create Count Success 2
6 Create Count Failure 0
7 Find Count 1
8 Invalidation Count 1
9 Delete Count Invalid 0
10 Delete Count Valid 0
11 Hash Chain Length 1
  • (G)V$RESULT_CACHE_MEMORY

该视图显示Result Cache所有内存块和相关统计信息。

 

  • (G)V$RESULT_CACHE_OBJECTS

该视图显示Result Cache中被缓存的对象,包括结果集数据和依赖的表及相关属性数据。例如,以下是部分字段查询结果:

ID TYPE STATUS BUCKET_NO HASH NAME
0 Dependency Published 371 2.947E+09 HR.EMP
2 Result Published 3135 1.132E+09 SELECT /*+ RESULT_CACHE */ department_id, AVG(salary)

FROM emp

GROUP BY department_id

1 Result Invalid 3135 1.132E+09 SELECT /*+ RESULT_CACHE */ department_id, AVG(salary)
FROM emp

GROUP BY department_id

  • (G)V$RESULT_CACHE_DEPENDENCY

该视图显示结果集数据和依赖表的关联关系,例如:

RESULT_ID DEPEND_ID OBJECT_NO
2 0 74569

查询结果显示结果集2(V$RESULT_CACHE_OBJECTS 表的ID =2 )与依赖数据0(V$RESULT_CACHE_OBJECTS 表的ID = 0 )有关联关系,该依赖数据的OBJECT_NO为74569,即HR.EMP表。

 

 Result Cache相关技术点

Result Cache与RAC

RAC支持Result Cache技术。RAC环境中的每个实例都有自己的Result Cache,每个实例的Result Cache不能共享,即保存在Result Cache中的数据只能被本实例的应用进行访问。但是,一旦保存在某个Result Cache中的数据变成INVALID,则整个RAC环境中各Result Cache中的该数据都将变成INVALID。Oracle通过专门的RCBG进程,处理RAC环境下Result Cache之间的数据同步。

Result Cache与并行处理

并行处理也支持Result Cache技术。在并行查询中,整个查询结果集将被保存在Result Cache中,也就是说,整个并行查询语句方可使用Result Cache中的查询结果,单个并行查询子进程无法访问Result Cache。在RAC环境下,并行查询结果保存在查询协调进程(Query Coordinator)所在实例的Result Cache中。

Result Cache的局限

Result Cache技术存在如下一些限制:

  • 系统临时表(Temporary Table)和数据字典表不支持Result Cache技术。
  • 非确定的(Nodeterministic)PL/SQL函数不支持Result Cache技术。
  • 查询语句若出现序列的CURRVAL、NEXTVAL,则不支持Result Cache技术。
  • 查询语句若出现current_date, sysdate, sys_guid等函数, 则不支持Result Cache技术。

Result Cache更多技术限制,请参阅11g联机文档《Oracle® Database Performance Tuning Guide11g Release 2 (11.2)》第7章相关内容,以及其它Oracle文档。

Result Cache的其它技术点

  • Result Cache支持Flashback查询。
  • Result Cache并不会自动释放其内存,Oracle将一直使用该内存到其最大限额值(RESULT_CACHE_MAX_SIZE),然后通过FIFO技术,释放相关内存。另外,通过FLUSH可清空Result Cache内存。
  • Result Cache支持绑定(BIND)变量的使用。针对绑定变量语句,Result Cache不仅保存结果集,而且保存相关变量值。这样,只有相同变量值的查询语句,方可使用其在Result Cache中的结果集。

Result Cache更多技术点,请参阅11g联机文档《Oracle® Database Performance Tuning Guide11g Release 2 (11.2)》第7章相关内容,以及其它Oracle文档。

 

7.5 客户端Result Cache技术

客户端也支持Result Cache

前面介绍的Result Cache技术,主要针对服务器端。实际上,11g在客户端也支持Result Cache技术,即OCI Client Query Cache技术。该技术特点如下:

  • 将服务器端的Result Cache扩展到客户端,将充分利用客户端内存,降低服务器端内存开销,提高了整个系统的扩展性。
  • 运用客户端的Result Cache技术,将降低网络往返传输开销(round-trips),从而显著提高系统整体性能。
  • 当服务器端的数据发生变化时,Oracle将自动刷新客户端的Result Cache数据。
  • 客户端的Result Cache技术主要适合于重复查询、频度较高的SQL语句,而且结果数据较少、数据相对静态的应用。例如,大量代码表的查询等。
  • 服务器端和客户端的Result Cache技术是相互独立的,可以分别进行设置。
  • 通过client_result_cache_stats$、v$client_result_cache_stats视图,可监控客户端的Result Cache的使用。

客户端Result Cache的使用

  • 数据库初始化参数
    • CLIENT_RESULT_CACHE_SIZE参数

该参数定义了单个客户端进程所使用的Result Cache最大值。如果设置为0,则关闭了客户端Result Cache技术。该参数缺省值即为0。

  • CLIENT_RESULT_CACHE_LAG参数

该参数定义客户端与服务端最后一次往返(round-trip)时间阀值,在该时间阀值内,客户端将向服务端查询客户端Result Cache中的数据是否发生变化,该参数缺省值为3000毫秒。即每隔3秒,Oracle将客户端Result Cache中的数据与服务端进行一次同步。

  • 客户端相关配置

通过在客户端的sqlnet.ora配置文件中设置如下参数,可以进行客户端Result Cache的配置。

  • OCI_RESULT_CACHE_MAX_SIZE
  • OCI_RESULT_CACHE_MAX_RSET_SIZE
  • OCI_RESULT_CACHE_MAX_RSET_ROWS

这些参数设置了单个客户端进程可使用的Result Cache最大值(Bytes)或最大记录数。客户端参数的设置将优先于服务器端的参数,例如CLIENT_RESULT_CACHE_SIZE参数。

欲使用客户端Result Cache,应用程序应与11.1以上版本客户端库进行连接,并访问11.1以上数据库服务器。

PL/SQL中Result Cache的使用

  • 原理

PL/SQL支持Result Cache技术的使用。以下就是原理示意图:

 

result_cache4

即当PL/SQL函数Calculate第一次执行时,Oracle将按正常方式执行,并将执行结果存储在Result Cache中。而在后续的执行过程中,当该函数涉及的数据和调用参数没有发生变化时,Oracle将避免重复计算,而是直接将Result Cache中保存的该函数结果返回客户。而当该函数涉及的数据和调用参数发生变化时,Oracle将自动重新计算该函数,并将结果数据再次存储在Result Cache中。

在PL/SQL中运用Result Cache技术,特别适合于大批量复杂计算,并且数据相对静态的应用,而且对应用本身透明,更省去了在应用层面进行结果数据存储的开发和管理工作。

  • 使用过程

以下就是PL/SQL中Result Cache的使用案例:

CREATE OR REPLACE FUNCTION productName
  (prod_id NUMBER, lang_id VARCHAR2)
  RETURN NVARCHAR2
  RESULT_CACHE RELIES_ON (product_descriptions)
IS
  result VARCHAR2(50);
BEGIN
  SELECT translated_name INTO result
    FROM product_descriptions
    WHERE product_id = prod_id AND language_id = lang_id;
  RETURN result;
END;

 

即在函数声明部分增加RESULT_CACHE关键字,并且可增加RELIES_ON短语,表示该函数依赖于product_descriptions表。当product_descriptions表的数据发生变更时,该函数的结果集将变为INVALID。

  • 相关限制

在如下情况下,PL/SQL无法使用Result Cache技术。

  • 当函数定义在一个需要调用者权限的模块中,或者定义在一个匿名块中。
  • 该函数是一个管道表(Pipelined Table)函数。
  • 该函数有OUT或IN OUT参数。
  • 该函数包括BLOB、CLOB、NCLOB、REF CURSOR、collection、object、 record等类型参数。
  • 该函数返回类型包括BLOB,、CLOB、NCLOB、REF CURSOR、object、record,以及包含上述不支持返回类型的collection。

 

适合Result Cache的典型案例

相关背景

  • 系统概述

某运营商总部的集中结算系统共有2套互为HA备份的单机系统,节点1主要承担联机交易,节点2主要承担报表、统计等批处理业务。两套系统主要问题都是运行状态不佳。例如以下是我们在现场调研时发现的节点1的运行状况:

 

result_cache5

 

可见节点1系统的CPU、I/O利用率都几乎达到100%,并经常导致系统宕机和重启。

  • 数据库层面资源消耗情况

以下是节点1数据库的Load Profile:

Per Second Per Transaction
Redo size: 1,023,082.84 13,340.70
Logical reads: 1,838,583.03 23,974.58
Block changes: 5,770.79 75.25
Physical reads: 3,237.45 42.22
Physical writes: 774.41 10.10
User calls: 6,344.54 82.73
Parses: 3,289.28 42.89
Hard parses: 2.72 0.04
Sorts: 1,876.35 24.47
Logons: 42.58 0.56
Executes: 4,098.31 53.44
Transactions: 76.69  

可见内存和I/O开销都非常大。

以下是Top 5 Timed Events

Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class
latch: cache buffers chains 639,561 35,422 55 28.1 Concurrency
CPU time   27,473   21.8  
SQL*Net message from dblink 85,888 1,848 22 1.5 Network
SQL*Net more data from dblink 3,937,144 1,587 0 1.3 Network
latch free 16,422 1,333 81 1.1 Other

最高等待事件是:latch: cache buffers chains,说明带系统存在比较严重的热块数据。

主要问题分析

  • 最高等待事件分析

如上所述,最高等待事件latch: cache buffers chains说明带系统存在比较严重的热块数据。进一步分析如下Segments by Logical Reads数据:

Owner Tablespace Name Object Name Subobject Name Obj. Type Logical Reads %Total
STL_USR COMMDATA T_FILE_INFO_81   TABLE 1,125,308,256 33.98
SETTLE STATDATA T_FILE_INFO_18   TABLE 952,259,776 28.75
STL_USR COMMDATA T_FILE_INFO_13   TABLE 218,271,024 6.59
STL_USR COMMDATA T_FILE_INFO_30   TABLE 145,521,632 4.39
STL_USR COMMDATA T_FILE_INFO_50   TABLE 143,596,320 4.34

可见T_FILE_INFO_81和T_FILE_INFO_18是该系统被集中频繁访问的表。

  • 典型应用分析

进一步分析,在Top-SQL语句中,访问上述两表的语句占了绝大多数。例如:

select count(*)
  from t_file_info_18
 where province_id = :"SYS_B_0"
   and operation_type_grade = :"SYS_B_1"
   and flow_id = :"SYS_B_2"
   and insert_ip = :"SYS_B_3"
   and (state = :"SYS_B_4" or state = :"SYS_B_5")

 

上述语句目前执行计划为全表扫描,该表目前已达到500多万记录,容量1.6GB。

该表虽然已经建立了(PROVINCE_ID,OPERATION_TYPE_GRADE,FLOW_ID,STATE, INSERT_IP)的复合索引,但由于该索引的可选性不高,所以Oracle优化器选择了全表扫描。

  • 解决方式建议

最佳解决方式是11g SQL Query Result Cache技术!经与应用和业务部门沟通,T_FILE_INFO_18表数据的查询频度远高于DML操作频度,而且上述语句是全表扫描,访问结果仅仅是求和一条记录。即便基表T_FILE_INFO_18表数据发生变化,Oracle也会自动将Result Cache中相关内容变为INVALID,而再次访问变化数据,并将变化数据的结果集再次存储在Result Cache中,供后续相同查询语句访问。预计Result Cache技术的运用将极大地解决该系统突出的性能问题。

可惜现在该系统还无法使用Result Cache技术,为什么?因为该系统还运行在10g平台,暂时还没有计划升级到11g。想唱戏的连个舞台都没有,呵呵。

本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database Performance Tuning Guide》 请大家重点看第7章第7.6节“Managing the Server and Client Result Caches”
2. Oracle 11g R2联机文档 《Oracle® Database Administrator’s Guide》 请大家重点看第6章 “Specifying the Result Cache Maximum Size”小节
3. Oracle大学教材 《Oracle® Database 11g New Features》第11章 这是Oracle大学教材。欲看到图文并茂的该文档,只能报名参加该课程的培训了。
4. My Oracle Support 《SQL Query Result Cache. Includes: [Video] (Doc ID 1108133.1)》 系统介绍SQL Query Result Cache的文档,还有视频哦,听听标准的美式英语吧。
5. My Oracle Support 《11g New Feature : SQL Query Result Cache (Doc ID 453567.1)》 一篇介绍SQL Query Result Cache的简洁的文档,以及一个例子。
6. My Oracle Support 《11g New Feature PL/SQL Function Result Cache (Doc ID 430887.1)》 一篇介绍PL/SQL Function Result Cache的简洁的文档,还有一个详细的例子。

 

 

 



Oracle Acs资深顾问罗敏 老罗技术核心感悟:11g的数据压缩技术

 

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

 

以下是各种表压缩算法特性的进一步描述:

 

IT系统数据量与日俱增,对IT系统设计、开发、运维各方面人员都带来了巨大挑战。除在硬件层面不断进行投入和加强之外,在软件层面一个重要的应对策略就是数据压缩技术。但是,以本人的经历,国内Oracle数据库却很少采用数据压缩技术,这是为什么呢?Oracle 11g在数据压缩领域有什么新的发展?各种压缩算法的压缩比如何?压缩对性能到底有什么影响?如何合理运用11g压缩技术和管理压缩数据?

本章就将针对上述问题进行分析和叙述,特别是介绍相关案例和实施细节。

 

为什么Oracle压缩技术运用不普及?

海量数据的增长和挑战

IT系统数据量与日俱增,甚至呈几何级数增长。以下就是国外相关机构在2010年对VLDB数据库数据量变化的统计和预测:

 

compress_1

 

可见,在以往年代最大的数据库为Teradata,而从2003年之后则是Oracle独占鳌头了。该机构并预测在2008年就将出现PB级数据库,可能现在早就有了,至少本人在2004年就见识过国内380TB规模的数据库了。

导致数据量剧增的原因可能包括如下几方面:

  • 数据和应用大集中

数据和应用大集中已成为各行各业IT 系统发展的一大趋势。这种趋势给IT系统带来的挑战是全方位的,首先就是数据规模和访问量的急剧增长,面对海量数据的访问性能、安全性、可管理性、高可用性等需求更是IT系统架构设计、应用开发、运行维护等多方人士共同面对的严峻挑战。

  • 安全审计的需要

面对日益增长的安全性和合规性需求,特别是面对各种行业组织和国家有关部门的安全审计需求,例如国外的萨班斯-奥克斯利法案(Sarbanes-Oxley Act),越来越多企业的IT系统被要求保留交易明细,甚至需要构建专门的安全审计系统。本人2012年下半年就为某国有大型银行的安全审计系统提供一定的技术服务,该系统一年数据量就达到200TB,将成为该行有史以来最大的数据库。

  • 互联网应用的高速增长

互联网应用持续高速增长,不仅导致传统交易数据量的增长,而且由于Web 2.0应用和各种多媒体应用的推广,使得各种内容管理数据也呈蓬勃发展之势。

 

为什么不采用Oracle压缩技术?

面对这种海量数据增长所带来的挑战,除了采用更先进服务器和存储设备技术之外,在数据库设计方面应该考虑的一个重要技术就是数据压缩技术,就象我们都经常在自己机器上通过 Winzip、rar等工具对大文件进行压缩一样。但是,我们发现国内基于Oracle的数据库很少使用到Oracle压缩技术,为什么会出现这种局面呢?本人分析的原因如下:

  • Oracle压缩技术的局限性

首先,Oracle在11g之前的压缩技术的确存在一定的局限性。Oracle 11g之前只有在批量加载数据,并采用direct path load等技术情况下,才能进行数据压缩,也就是说在数据仓库的ETL等典型场景中才可能使用到压缩技术,而在普通OLTP应用中,Oracle没有提供数据压缩技术。这就大大限制了压缩技术的使用范围。

  • 担心性能开销

采用了压缩技术,客户担心在数据写入时需要压缩,在查询数据时又要解压缩,都可能增加额外的CPU开销。这也是导致压缩技术没有普遍使用的重要原因之一。

现在早就是11g时代了,Oracle 11g已经在数据压缩技术方面有了突飞猛进的发展。下面我们就在这个新的平台上与大家共同讨论相关技术和应用前景吧。

11g压缩技术概述

Oracle压缩技术特点和好处

总体而言,Oracle压缩技术具有如下特点和好处:

  • 节省大量存储空间

就象我们自己压缩文件所期待的一样,Oracle数据库压缩技术带来的好处,首先就是节省大量存储空间。以下就是Oracle公司内部ERP系统的各个应用系统,在压缩前后的存储空间变化情况:

compress_2

 

即平均达到3倍的压缩比。大大节省的存储空间带来的效益是全方位的,不仅是存储设备投入的节省,而且对生产、容灾、测试、开发等环境需求都大大降低。

 

  • 性能不降反升

通常地,一旦采用压缩算法,数据写入时需要压缩,在查询数据时又要解压缩,都可能增加额外的CPU开销,这也是广大客户所担忧的。但压缩之后,将带来I/O访问量的大幅度下降,同时也降低了Oracle缓存(Buffer Cache)的开销。这样一正一负,很多测试表明性能是不降反升了。特别是对需要进行大规模数据处理的应用更是收效显著,例如逻辑和物理备份、统计信息采集等。

另外,后面详细描述的11g新OLTP压缩算法并不是在每个DML语句运行时都进行压缩计算,而是采取一种延迟的批处理方式压缩,这也有效保障了DML操作性能不受影响。

  • Oracle可在表空间、表、分区级进行压缩

如果表空间设计缺省压缩算法,则所有存储在该表空间的表都将采用相同的压缩算法,这样将简化表压缩的设计和管理工作。当然,在表一级也可定义更个性化的压缩算法。Oracle还支持在分区级定义不同的压缩算法,以满足不同的数据管理需求。例如针对年代久远、极少访问的历史归档数据,可通过分区方式选择压缩效果更好的算法。

  • Oracle压缩技术对应用透明

就象大多数Oracle技术一样,Oracle压缩技术对应用也是透明的。这不仅意味着采用压缩技术之后,所有应用无需改造,而且由于Oracle是在数据块级实施压缩,从操作特性而言,压缩后的数据块与普通数据块并无太多区别,因此数据库绝大部分特性和技术都适合于压缩表,例如各种索引、各种表连接技术、分区技术等。

 

 

 

Oracle多种压缩技术特点分析

Oracle公司最早在9i R2版本就推出了表压缩技术。但这种技术只适合于批量数据加载的场景,例如Direct path SQL*Laoder等操作。Oracle在11g之前一直没有推出针对OLTP应用的大并发量随机DML操作的压缩技术。如上所述,这也大大限制了Oracle压缩技术的应用。

在11g特别11 R2发布之后,Oracle不仅推出了适合OLTP应用的压缩技术,而且还推出了多种混合列压缩(Hybrid Columnar Compress)技术。以下就是Oracle现在所具有的各种压缩技术的总体概述:

 

表压缩算法 压缩级别 CPU开销 适用场景 备注
         
Basic Compress 数据仓库  
OLTP compression 联机交易,数据仓库  
Warehouse compression (Hybrid Columnar Compression) 更高 更高 数据仓库(Exadata环境) 压缩级别和CPU开销取决于压缩级别为LOW或HIGH
Online archival compression (Hybrid Columnar Compression) 最高 最高 归档系统(Exadata环境) 压缩级别和CPU开销取决于压缩级别为LOW或HIGH

 

以下是各种表压缩算法特性的进一步描述:

表压缩算法 CREATE/ALTER TABLE语法 Direct-Path INSERT 备注
       
Basic Compress COMPRESS[BASIC] 记录通过基本压缩算法进行压缩 COMPRESS与 COMPRESS[BASIC]含义相同

未使用Direct-Path INSERT的记录没有压缩

OLTP compression COMPRESS for OLTP 记录通过OLTP压缩算法进行压缩 未使用Direct-Path INSERT的记录将通过OLTP压缩算法进行压缩
Warehouse compression (Hybrid Columnar Compression) COMPRESS for QUERY[LOW|HIGH] 记录通过Warehouse compression算法进行压缩 该算法将导致较高的CPU负载

未使用Direct-Path INSERT的记录的压缩比较低

Online archival compression (Hybrid Columnar Compression) COMPRESS for ARCHIVE[LOW|HIGH] 记录通过Online archival compression算法进行压缩 该算法将导致较高的CPU负载

未使用Direct-Path INSERT的记录的压缩比较低

 

需要特别说明的是,目前基于混合列压缩的Warehouse compression和Online archival compression 压缩算法只适合于Oracle软硬件一体机Exadata环境。例如,以下就是在普通存储上试图使用这两种压缩算法所出现的错误:

SQL> create table emp(id number, name varchar(20)) compress for query;

create table emp(id number, name varchar(20)) compress for query

*

第 1 行出现错误:

ORA-64307: 只有位于 Exadata 存储上的表空间才支持混合柱状压缩




SQL> create table emp(id number, name varchar(20)) compress for archive;

create table emp(id number, name varchar(20)) compress for archive

*

第 1 行出现错误:

ORA-64307: 只有位于 Exadata 存储上的表空间才支持混合柱状压缩

 

 

  • Basic Compress

该算法就是从9i就推出的最传统压缩算法,其特点是通过Direct path SQL*Laoder、Direct path Insert、并行Insert、CTAS(create table as select…)等操作才能进行压缩,或者通过alter table … move及表在线重定义(Table Redefinination)等操作,将非压缩表以批量方式迁移到压缩表。该算法CPU额外开销较小,主要适合于数据仓库领域。

 

  • OLTP Compress

该算法是11g推出的针对OLTP应用的压缩算法,对各种DML操作都可以进行压缩,由于采用了延迟的批处理方式压缩,因此对CPU开销并不大。该算法既适合于交易系统,也适合于数据仓库系统。

  • Warehouse compression (Hybrid Columnar Compression)

该算法采用了11g新的混合列压缩技术(Hybrid Columnar Compression)。与前面的基于记录行的压缩算法不同,Oracle混合列压缩是基于列进行压缩的,其压缩比更高,但针对DML操作的CPU开销更大,因此适合于数据很少发生变更的数据仓库系统。

  • Warehouse compression (Hybrid Columnar Compression)

该算法采用了11g新的混合列压缩技术(Hybrid Columnar Compression)。与前面的基于记录行的压缩算法不同,Oracle混合列压缩是基于列进行压缩的,其压缩比更高,但针对DML操作的CPU开销更大,因此适合于数据很少发生变更的数据仓库系统。

 

  • Online archival compression (Hybrid Columnar Compression)

该算法也采用了11g新的混合列压缩技术(Hybrid Columnar Compression)。与Warehouse compression不同的是,其压缩比最高,但CPU开销最大,甚至查询操作性能都会有一定影响。因此该算法适合于数据访问很少的数据归档系统。

同样地,虽然该算法对所有操作都可以进行压缩,但Direct path方式进行的压缩效果更好。

该算法的缺省压缩级别为LOW。若设置成HIGH,压缩比将最高,但对CPU开销最大,对访问性能影响也最大。

 

表压缩语句举例

相比上述原理,表压缩语句其实非常简单。以下是表压缩短语的语法:

 

compress_4

 

例如,如下语句将sales_history表创建为普通压缩表:

CREATE TABLE sales_history  …  COMPRESS;

如下语句通过Direct-Path INSERT操作,向sales_history表以压缩形式写数据:

INSERT /*+ APPEND */ INTO sales_history SELECT * FROM sales WHERE cust_id=8890;

COMMIT;

 

如下语句将orders表创建为OLTP压缩表:

CREATE TABLE orders  …  COMPRESS FOR OLTP;

如下语句的第一个分区表设计为普通压缩,第二个分区设计为OLTP压缩分区,第三个为非压缩的:

create table (
  object_id number(10),
  object_name varchar2(120)
  )
  partition by range(object_id)(
  partition p1 values less than (100000) compress basic,
  partition p2 values less than (200000) compress for oltp,
  partition p3 values less than (maxvalue) nocompress
  )

 

 

如下语句将sales_history表设计为Warehouse compression 压缩表:

CREATE TABLE sales_history  …  COMPRESS FOR QUERY;

该表的压缩比将高于普通压缩和OLTP压缩,上述语句缺省级别为HIGH。虽然加载性能略有影响,但对查询性能反而提升。不过,该表的DML操作将受影响。

如下语句将sales_history表设计为Online archival compression压缩表:

CREATE TABLE sales_history  …  COMPRESS FOR ARCHIVE;

该表的压缩比将最高,适合于数据归档目的,甚至查询操作性能都会受影响。

 

深入剖析Oracle 压缩算法

对技术着迷的读者一定希望深入了解Oracle各种压缩算法的内部机制,限于篇幅,以下仅简要介绍OLTP压缩和混合列压缩算法大致含义。

OLTP压缩算法

  • 基本原理

OLTP压缩算法采取的是批量和延迟进行压缩的思路。以下就是示意图:

 

compress_5

 

 

上图从左到右进行理解。该算法是在数据块级进行压缩,当往一个空块写数时,Oracle并不进行任何压缩。直到达到PCTFREE上限时,Oracle开始对该数据块内的记录进行压缩。然后,继续写入的记录仍然是非压缩的,直到再一次达到PCTFREE限制。周而复始,完成一个数据块的写入和压缩。

还记得Oracle日志工作原理吗?在客户提交一个DML语句的COMMIT操作之后,Oracle并不是马上将DML操作结果写入硬盘,而只是将DML操作的日志项写入联机日志文件。当DML操作达到一定量,例如当联机日志文件满,切换至下一组日至文件(Log Switch)时,或checkpoint等事件发生时,Oracle才以批量形式将DML操作结果真正写入硬盘。这种工作原理的目的就是降低I/O次数,确保联机交易操作的性能。

Oracle OLTP算法类似于上述日志工作原理,批量和延迟压缩目的就是降低对日常单个DML操作的性能影响。另外,这种工作原理还能有效降低碎片和行连接、行迁移的发生。

  • 举例

我们再通过一个具体例子,更进一步地了解OLTP算法。

 

compressz1

上图表示当Employee表在最初插入4条记录的情况下,在数据块中是没有压缩的,并顺序存放。当插入第5条记录,假设已经达到了PCTFREE的限制,如PCTFREE设置为10%,则Oracle开始启动OLTP压缩算法,示意图如下:

 

compressz2

 

即在该数据块头部产生一个符号表(Symbol Table),记录重复记录情况。例如,分别以t、u、v、w表示John、Doe、Jane、Smith值,而数据块中记录则通过保存指向该符号表的指针方式,进行压缩存储。如第1条记录“1、John、Doe”表示为“1•t•u”,第2条记录“2、Jane、Doe”表示为“2•v•u”,依此类推。

可见该算法本身其实并不复杂。该算法另外一个特点是,Oracle是在一个数据块内部完成所有压缩和解压缩操作,因此I/O次数并没有发生变化。而其它数据库厂商则可能需要通过另外的表或数据字典来保存压缩数据的符号表(Symbol Table)信息,这样将增加I/O次数,性能会有所下降。

 

混合列压缩算法

我们以如下daily_sales表为例,来简要描述混合列压缩算法的含义。

 

Item_ID Date Num_Sold Shipped_From Restock
1000 01-JUN-11 2 WAREHOUSE1 Y
1001 01-JUN-11 0 WAREHOUSE3 N
1002 01-JUN-11 1 WAREHOUSE3 N
1003 01-JUN-11 0 WAREHOUSE2 N
1004 01-JUN-11 2 WAREHOUSE1 N
1005 01-JUN-11 1 WAREHOUSE2 N

 

可见上表的Date、Shipped_From、Restock等字段存在大量重复值。混合列压缩正是采取列压缩方式进行数据压缩的算法,从而达到更高的压缩效果。同时,该算法是以压缩单元(Compress Unit)格式,将一组记录进行列压缩。因此,该算法就称之为混合列压缩。

以下是上述表的压缩单元示意图:

 

compressz3

 

可见,一个压缩单元可以横跨多个数据块,一个字段的值也可能横跨多个数据块。

事实上,Oracle并没有完全公开该算法细节,仅透露该算法在实现过程中考虑了字段数据类型、字段值分布情况、用户制定的压缩级别等多种要素。

作为用户,我们通过上述原理介绍,已经知道该算法压缩效果的确高于普通压缩和OLTP压缩算法了。另外需要了解到的是,该算法的确不适合并发访问量高的交易系统,因为当某条记录发生变更操作时,Oracle可不是只锁住该记录,而是锁住该记录所在压缩单元中的所有记录!

再次声明,Oracle混合列压缩算法目前只适合于Exadata环境,以及数据变更不多的数据仓库和历史数据归档系统。

 

一个实际案例的分享

项目背景

为满足国家审计部门的需求,某大型国有银行欲建立集中审计数据平台系统,即将该行数十个交易系统的交易明细数据集中到该系统之中,为内外审计、稽核提供数据依据。该系统涉及2000多张表,1年数据就预计达到150TB。针对如此之大的海量数据库,数据的采集、装载、备份和恢复及对外数据服务都面临在巨大压力。幸亏该系统已经决定部署在Oracle 11g RAC平台,也幸亏Oracle服务部门比较早地介入到该项目建设之中,更幸亏Oracle 11g的压缩算法已经日臻成熟。于是,11g压缩算法的充分运用成为该系统降低存储开销、提高系统处理性能的重要技术保障。

测试数据分析

以下我们对该系统测试期间的表压缩测试数据进行分析。

 

  • 测试目的

该测试案例对UDM_AGR_VPAR和UDM_VPAR_BANCS表,采用BASIC和OLTP技术进行压缩测试,并且与生产系统采用的不压缩方式进行对比,比较各种压缩模式的压缩比及各种压缩模式下的加载和查询应用性能。

  • 测试样本数据
表名称 UDM_AGR_VPAR UDM_VPAR_BANCS
数据库中表行数 147246157行 95472972行
数据库中表大小 20024 MB 14664MB
是否分区表
  • 测试结果及分析
表名称 压缩模式 大小 压缩倍率 加载时间 压缩耗时 全表查询耗时
UDM_VPAR_BANCS 非压缩 logging 14664MB (无) 16分钟   1分53秒
UDM_VPAR_BANCS_COMPRESS BASIC nologging 5152MB 2.84 21分钟 加载时直接压缩 1分06秒
UDM_VPAR_BANCS_COMPRESS_OLTP OLTP

nologging

5984MB 2.45 1小时1分4秒 加载时直接压缩 1分35秒

上面表格数据以UDM_VPAR_BANCS表为例,该表样本数据为95472972条记录,在不进行压缩情况下加载到数据库,所占空间为14664MB,花费了16分钟,全表查询为1分53秒。

该表在采用传统的BASIC算法情况下,加载到数据库所占空间为5152MB,压缩比为2.84倍,与Oracle官方宣传的3倍压缩比相当。加载时间为21分钟,比不压缩的16分钟下降了23%,但全表扫描时间为1分06秒,提高了近1倍!客户对此结果非常满意,因为不仅空间节约了近3倍,全表扫描为1分06秒,相比不压缩的1分53秒,提高了近1倍。虽然加载时间下降了23%,但该系统的批量加载毕竟是一次性的,而查询操作却是高频度的。

该表在采用11g OLTP算法情况下,表现不尽如人意。具体数据为:加载到数据库所占空间为5984MB,压缩比为2.45倍,比BASIC 算法的2.84略有下降。更糟糕的是加载时间为1小时1分4秒,比不压缩的16分钟下降了3.8倍,而全表扫描时间为1分35秒,相比不压缩的1分53秒,提高幅度也不大。究其原因,还是因为该测试案例为批量数据加载,更适合于BASIC压缩算法,而不适合于针对OLTP应用的OLTP压缩算法。

 

数据压缩相关技术点

哪些表是压缩表?

欲查询哪些表进行了压缩,可查询如下视图:

 

SQL> SELECT table_name, compression, compress_for FROM user_tables;

TABLE_NAME       COMPRESSION   COMPRESS_FOR
---------------- ------------  -----------------
T1               DISABLED
T2               ENABLED       BASIC
T3               ENABLED       OLTP
T4               ENABLED       QUERY HIGH
T5               ENABLED       ARCHIVE LOW

 

 

欲查询哪些分区表进行了压缩,可查询如下视图:


SQL> SELECT table_name, partition_name, compression, compress_for
  FROM user_tab_partitions;



TABLE_NAME  PARTITION_NAME   COMPRESSION   COMPRESS_FOR
----------- ---------------- -----------   ---------------SALES       Q4_2004          ENABLED       ARCHIVE HIGH
SALES       Q3_2008          ENABLED       QUERY HIGH
SALES       Q4_2008          ENABLED       QUERY HIGH
SALES       Q1_2009          ENABLED       OLTP
SALES       Q2_2009          ENABLED       OLTP
  ...



如何更改压缩算法?

一个表的压缩算法是可以更改的,从而适应于不同数据变化情况。例如,交易明细当前数据可采取OLTP压缩算法,而针对超过6个月极少更改的数据可采取Warehouse压缩算法。

以下语句将表转换为basic压缩表:

 

SQL> alter table emp move compress basic;

以下语句将表转换为OLTP压缩表:

SQL> alter table emp move compress for oltp;

以下语句一个分区转换为basic压缩分区:

SQL>alter table part_objects move partition p3 compress  basic;

 

以下语句修改一个分区的现有压缩算法,但更改之后的压缩算法只对新记录有效,而不影响现有记录。

SQL>alter table part_objects modify partition p1 compress for oltp;

上述move和modify操作均非在线操作,即在进行这些操作时,这些表将不可进行DML操作。欲在线进行压缩算法变更操作,则需要采用表在线重定义技术。限于篇幅,不赘述。请参考Oracle相关联机文档。

哪些记录是压缩记录?

由于表的压缩算法可更改,这样一个表中的记录可以是非压缩或采取不同压缩算法的。欲查询不同记录的压缩情况,可通过记录的ROWID值进行如下查询:


SELECT DECODE(DBMS_COMPRESSION.GET_COMPRESSION_TYPE(
                 ownname => 'HR',
                 tabname => 'EMPLOYEES',
                 row_id  => 'AAAVEIAAGAAAABTAAD'),
   1,  'No Compression',
   2,  'Basic or OLTP Compression',
   4,  'Hybrid Columnar Compression for Query High',
   8,  'Hybrid Columnar Compression for Query Low',
   16, 'Hybrid Columnar Compression for Archive High',
   32, 'Hybrid Columnar Compression for Archive Low',
   'Unknown Compression Type') compression_type
FROM DUAL;

 

其它技术点

  • 压缩表不支持在线shrink操作。
  • 表压缩技术不适合于11g新的大对象技术:SecureFiles。因为SecureFiles采用自己的压缩技术。
  • 当表采用basic压缩算法之后,表的PCTFREE参数自动设置为0。
  • 使用COMPRESS FOR OLTP 或COMPRESS BASIC方式表的字段数量不能超过255个。虽然可以设置成功,但数据实际上是没有压缩的。
  • IOT表不支持压缩。

其它压缩技术

不仅数据库表可以进行数据压缩处理,而且在逻辑备份和物理备份、日志传输、大对象等方面均可进行压缩处理。其中大对象压缩技术将在本书后面章节专题讲述,下面将介绍其它压缩技术:

Data Pump中的压缩技术

Oracle 10g在推出Data Pump技术时,就支持元数据(Metadata)压缩。而在11g之后,Data Pump更支持数据本身的压缩。以下是Data Pump的COMPRESSION参数定义值:

COMPRESSION={ALL | DATA_ONLY | [METADATA_ONLY] | NONE}

其中:

  • ALL:表示数据和元数据均压缩
  • DATA_ONLY:表示只压缩数据
  • METADATA_ONLY:表示只压缩元数据
  • NONE:没有任何压缩

以下是Data Pump在卸载数据时进行数据和元数据压缩的语句:

 

PROMPT> expdp hr DIRECTORY=dpump_dir1 DUMPFILE=hr_comp.dmp COMPRESSION=ALL

 

RMAN中的压缩技术

海量数据库的日益增长对数据库物理备份(RMAN)的挑战也越来越高,除在主机、网络、存储、磁带库等硬件方面加大投入之外,在软件方面需要考虑的一个重要技术就是压缩技术。

以下就是Oracle在RMAN技术中所提供的多种压缩技术的概述和对比:

RMAN压缩级别 推出版本 特点
     
LOW 11.2 l  最快的压缩算法

l  适合于CPU资源紧张的场景

MEDIUM 11.1 l  压缩比中等、CPU资源消耗中等

l  11g之前称之为快速RMAN备份压缩

HIGH 11.2 l  最高的压缩比,CPU资源消耗最高

l  适合于网络或I/O为瓶颈,但CPU资源充足的场景

 

以下是在相关语句:

— 设置RMAN压缩级别为MEDIUM

RMAN> configure compression algorithm ‘MEDIUM’;

— 将备份集进行压缩

RMAN> BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;

 

如下语句将磁盘、磁带设备设置为压缩模式,这样,Backup命令中无需再指定压缩短语:

RMAN> CONFIGURE DEVICE TYPE DISK BACKUP TYPE TO COMPRESSED BACKUPSET;

RMAN> CONFIGURE DEVICE TYPE sbt BACKUP TYPE TO COMPRESSED BACKUPSET;

如下语句关闭压缩功能:

RMAN> CONFIGURE DEVICE TYPE DISK BACKUP TYPE TO BACKUPSET;

RMAN> CONFIGURE DEVICE TYPE sbt BACKUP TYPE TO BACKUPSET;

以下是Oracle公司针对Oracle Application数据库进行压缩备份的测试结果:

 

compressz4

 

可见通过运用10g/11g备份压缩技术,备份数据集被压缩了6倍。

compressz5

 

 

可见通过运用11g备份压缩技术,备份时间不仅比非压缩备份快了不少,而且比10g压缩技术也快了2.5倍。

Data Guard日志传输中的压缩技术

Data Guard作为基于日志传输和同步技术的Oracle容灾技术,日志传输效率将在很大程度上影响Data Guard实施性能和效率。除高带宽、低延迟的网络环境保障之外,通过压缩日志文件,降低网络传输量,也是确保Data Guard性能的重要技术。可惜的是,Oracle 11g之前版本一直没有在日志传输中提供压缩技术,也成了被竞争对手经常被攻击的一个目标。到了11g,Oracle终于在这方面有所作为了。以下就是相关语法,即在相关LOG参数中增加了COMPRESS属性:

 

LOG_ARCHIVE_DEST_3=’SERVICE=denver SYNC COMPRESSION=ENABLE|[DISABLE]

 

以下是Oracle公司进行的相关测试数据:

 

compressz6

 

其中OLTP应用为国外的JPetStore应用,而批处理应用采用了Direct Load Insert技术。可见,OLTP应用的日志被压缩了2倍,而批处理应用日志被压缩了5倍。

但运用日志压缩技术应考虑如下因素:

  • 网络带宽跟不上日志文件产生速度。
  • 足够的CPU资源用于压缩算法的计算。

其实,Oracle的日志压缩算法采用的就是gzip技术,具体而言采用的的是zlib压缩引擎的level -1。因此,通过如下语句可估算一个归档日志的压缩比:

 

— 先压缩一个归档日志

$ gzip -1 <archive redo logfile>.arc

— 显示详细压缩情况,包括压缩比:

$ gzip –list <archive redo logfile.arc>.gz

 

数据压缩技术运用建议

就像Oracle众多技术的运用一样,数据压缩技术看似简单,其实涉及方案设计、测试、上线和运维管理等诸多方面和阶段的内容。以下就是针对某保险客户的压缩技术运用需求而提供的实施建议,供大家参考:

  • 压缩级别设计

首先,确定在tablespace、table,以及partition级实施压缩。

  • 压缩算法确定

根据不同表的访问特点以及Oracle不同压缩算法特点,确定具体压缩算法。例如:Basic Compress, OLTP Compress,Warehouse Compress, Online Archival Compress等。

  • 压缩测试案例设计

结合压力测试,测试不同压缩算法的空间压缩情况,以及对不同应用(批量加载、OLTP应用、统计分析等)的性能变化情况。

  • 压缩算法变更管理

研究和测试表和分区的压缩算法变更技术。例如,move语句和在线重定义等。

  • 压缩数据管理

研究和测试压缩表数据字典信息的查询;如何确定具体行的压缩算法;压缩表的增加和删除字段技术;Exp和Imp压缩表,压缩表的RMAN备份恢复等专题。

  • 其它压缩技术的运用

研究是否存在LOB字段,并确定是否需要采用SecureFiles压缩技术。同时研究RMAN、Data Pump,甚至Data Guard是否需要采用压缩技术。

这就是Oracle作为企业级软件供应商的技术运用方法、经验和特点:全面性、系统性、专业性。

 

6.8本章参考资料及进一步读物

本章参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle Administrator’s Guide》 请大家重点看该文档第20章“Consider Using Table Compression”小节
2. Oracle 11g R2联机文档 《Oracle® Database VLDB and Partitioning Guide》 请大家重点看第三章“Partitioning and Table Compression”小节,第四章“Using Table Compression with Partitioned Tables”、“Using Key Compression with Partitioned Indexes”等小节。
3. Oracle白皮书 《 Advanced Compression with Oracle Database 11g》 Oracle公司介绍11g压缩技术的官方白皮书。链接如下:

http://www.oracle.com/us/products/database/db-advanced-compression-option-1525064.pdf

Basic、OLTP、SecureFiles去重和压缩、RMAN压缩、Data Pump压缩、网络传输压缩等均有介绍。

4. My Oracle Support 《Master Note for OLTP Compression (Doc ID 1223705.1)》 全面了解11g OLTP压缩算法的文档。
5. My Oracle Support 《11g New Features: Advanced Compression Overview and Advantages (Doc ID 785787.1)》 又一篇介绍11g OLTP压缩、SecureFiles压缩、Data Pump压缩、Data Guard网络压缩的文档。
6. My Oracle Support 《All About Advanced Table Compression (Overview, Use, Examples, Restrictions) (Doc ID 882712.1)》 更细致介绍11g高级表压缩算法,也就是OLTP压缩算法原理、适应场景、压缩管理的文档。
7. My Oracle Support 《Performance Issue After Enabling Compression (Doc ID 987049.1)》 采用压缩技术之后,性能下降了,怎么回事?这并不是普遍现象。该文档道出了一个可能性:11.1.0.7版本的一个Bug: 8287680
8. My Oracle Support 《The OLTP Compression Saves No Space As Expected Using A Row Too Big (Doc ID 1149283.1)》 记录太大的情况下,OLTP压缩没起作用,怎么回事?这是正常现象。欲知详情,请看这篇文档。
9. My Oracle Support 《My Data Is Not compressed. (Doc ID 805205.1)》 数据为什么没有压缩?这篇文档给出了一个测试场景,以及判断压缩效果的详细脚本。

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟:11g新技术/新功能使用策略

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

本文地址:https://www.askmac.cn/archives/oracle-acs%E8%B5%84%E6%B7%B1%E9%A1%BE%E9%97%AE%E7%BD%97%E6%95%8F-%E8%80%81%E7%BD%97%E6%8A%80%E6%9C%AF%E6%A0%B8%E5%BF%83%E6%84%9F%E6%82%9F%EF%BC%9A11g%E6%96%B0%E6%8A%80%E6%9C%AF%E6%96%B0%E5%8A%9F.html

 

 

本章首先将以自己一个与11g相关的尴尬经历开始,然后对11g新技术和新特性进行一番总体介绍,再围绕一个具体技术话题,讲述11g新技术使用策略的重要性,最后针对11g新技术/新功能的总体使用策略提供自己的具体建议,希望这些内容对广大读者在11g平台的设计、开发和运维等方面工作有所裨意。

 

5.1 我被客户“打懵”了

故做镇定

2012年2月的某一天,应某国有大型银行的要求,来到了该银行的南方开发基地,为其正在进行的11g升级项目提供技术支持和咨询服务工作。那天上午一踏入会议室,与该行一群新老朋友简短地寒暄之后,便很快进入了正题:

“罗工,你先帮我们梳理一下这张表格,11g这些新特性到底用还是不用?”

我快速扫描了一下大屏幕上投影的表格,以下是片断内容:

维护项 11g对应的功能点 是否使用 使用说明
数据库及补丁安装 联机热补丁 待确认 1、HOT PATCH是否只能联机安装,2、联机安装时对数据库的影响,3、通过OPATCH命令查询补丁是否为HOT PATCH,4、目前同业中HOT PATCH的使用情况
Time Stamp With Time Zone数据的自动补丁安装* 待确认 确认该新特性功能
零停机时间的Clusterware补丁安装* 推荐使用 工程师确认联机安装对RAC的影响
故障管理 自动诊断信息库框架 必须使用 日常维护中要熟悉文件存放结构
命令行故障管理工具adrci 推荐使用 日志信息诊断扩展功能
支持工作台 不使用 由于需要配置外网连接,故部分功能不可用
健康监控工具Health Monitor 待确认 手动启用或者在严重错误时自动触发,在严重故障时运行该功能对数据库的影响需评估,AB类关闭,CD类开启,
意外事件打包服务IPS 推荐使用 相关日志打包提供给ORACLE技术支持
数据恢复向导Data Recovery Advisor 推荐使用 手工触发,提供辅助诊断功能
SQL测试用例构造器SQL Test Case Builder 推荐使用 手工触发,
SQL修复指导SQL Repair Advisor 推荐使用 手工触发,用于处理执行失败的SQL语句
检测数据损坏控制参数DB_ULTRA_SAFE 不使用 DB_ULTRA_SAFE=OFF(默认值),同时显式设置DB_BLOCK_CHECKING=FULL、DB_BLOCK_CHECKSUM=FULL和DB_LOST_WRITE_PROTECT=TYPICAL三个参数
内存管理 自动内存管理 不使用 memory_target不使用,memory_target主要调整sga和pga相互间的大小。若启用sga_target,必须设置各个内存区域的最小值
Database Smart Flash Cache* 不使用 仅适用于EXADATA

这都什么东西啊?我的妈呀,表格里好多新特性我听都没听说过。尽管开发基地位于气候宜人的南海之滨,但分明感觉到后背一股凉气袭人。好歹在IT行业也混了20余年,在Oracle公司也有10多年了,更是奔五的人了,可不能在客户面前表现地惊慌失措。经验告诉我,首先应该故做镇定,先在表格里挑我熟悉的一些新特性进行一番研讨,并通过不断的交流,了解客户的项目背景和进展情况,再寻找合适的对策。知己知彼,百战不殆啊。

尽管如此,后来精明的客户还是发现老罗同志一上来就被他们“打懵”了,呵呵。

经验之谈:引导客户

原来,该行在11g升级项目中,为充分考虑11g新特性如何使用,特别成立了一个由开发、测试、运维等多个部门7、8位技术专家组成的项目组,专题开展11g新特性研究工作。当时已经进行了2、3个月的工作,并写出了厚厚的200多页的《Oracle 11g与10g功能差异分析》研究报告,给我看的表格只是该报告的汇总版。我的天哪,你们这么多人都研究了那么长时间,虽然我是原厂技术人员,但以我个人的时间、精力,研究的深度和广度,绝对无法和他们一个团队相提并论。

如果我一直这么按客户的思路走下去,我不仅很快会被各种技术细节困住,而且也无法发挥我作为原厂商技术人员的真正作用和优势,更对整个项目不利。于是经验又告诉我,在初步了解客户情况,特别是发现相关问题之后,应尽快提出自己的技术思路,去引导客户。

于是,我很快发现客户项目组工作的局限:他们太过于注重细节了,对11g新技术/新特性使用总体策略研究并不够。另外,他们虽然研究很系统、很全面,但更多的是研究文档,其实缺乏实际的11g使用经验。例如,他们只研究11g相关新技术/新特性是否应该使用,而并不知道在11g实际运行过程中,很多新特性是缺省打开的。也就是说,不管你决定用不用,Oracle都是强制你使用某些新特性。殊不知,这就是问题和风险。作为原厂技术人员,我们吃过太多这样的苦头。

接下来,轮到我讲述自己的观点了:“我们先别着急每个细节的讨论,先研究一下11g新技术、新特性使用的总体策略吧。”同时,我马上根据自己在11g的实施经验,给客户提出这样的具体建议:“我们应该在表格上增加两列,一列表示该新特性是否是缺省打开的,另一列是该新特性的关闭方法。”—- 这些内容正是本章要讲述的重要内容。

这就是本人从事Oracle服务工作10余年的经验总结:不要完全被客户牵着走。我们是为客户服务的,尽管在某些技术细节上我们可能不如客户,但我们应该具有更高的视野,更应该将不同行业的案例经验及时与其他客户分享。否则,不仅我们工作上会陷入细节上的被动,更无从发挥自身优势,也最终导致客户项目实施质量大打折扣。

更多的感慨

那天中饭之后,与销售经理同事在风光旖旎的开发基地园区散步,也一同感慨上午的研讨情况。首先感慨的是客户的工作成果不仅让我个人,更让我们Oracle服务部门感到汗颜。11g新特性专题研究工作,本来应该是我们Oracle服务部门展开的工作,并为客户提供相关服务,现在却让客户抢在前面。事实上,当我们后来回到北京,与相关实施团队介绍交流情况时,也的确让他们感到震撼了一把。

其次,感慨的是该银行IT系统建设能力和科研队伍的强大,的确是我们在国内见识过的首屈一指的客户了。该行的IT系统建设不仅指导思想上以自我为主,而且确实锻炼成长了一大批充满锐气的年轻科技人员。上述项目组的7、8个人基本都是80后的,充满朝气和活力,而国内很多客户则缺乏这种强烈的进取和钻研精神。例如,我参与、了解过国内不同行业众多11g升级项目,但只有该银行对11g新特性在进行这么有组织、系统而全面的研究工作。

还想起该行一位部门领导对我们的一席话:你们原厂商不要埋怨我们对你们提出的很多富有挑战、甚至有点苛刻的服务需求,因为这些需求都是来自于我们实际工作的问题,而且正是这些需求,迫使你们自己能力也得到提高了。—– 的确是这样,作为服务人员,应善待、包容客户提出的每个需求。

“向客户学习、与客户共成长”,永远是一句不过时的口号。

 

5.2 11g 新技术/新特性一瞥

11g以其网格集群计算、自动和智能化管理、更好的高可用性和可伸缩性等理念和技术,引领着数据库产业高速向前发展。11g更是为解决IT系统所存在的相关问题,提供了大量新技术和新特性。以下先从总体上对11g若干新特性进行简要介绍,本书其它章节还将就相关技术专题进行深入讨论。

 

 

11g1

 

上图外围一圈可代表IT系统的相关需求或技术专题,而内圈则代表11g相关技术和特性。例如:

  • 高可用性(High Availability)

长期以来,Oracle一直在高可用性技术方面处于领先地位。例如为防范各种意外故障和计划内的停机而提供了多种解决方案,如RAC、Data Guard等技术。

到了11g,Oracle继续在高可用性领域不断发展。例如,Data Guard在11g中得到了很多方面的增强,特别是Active Data Guard能够在物理备库模式下,在日志应用的同时,可以只读方式打开容灾库。这样Active Data Guard不仅具备常规意义上的容灾功能,而且可以提供查询、报表和物理备份等负载分离功能,从而有效降低主业务系统压力和风险,并提高容灾系统的投资回报率。

  • 网格计算和交易系统领域(Grid & OLTP)

该领域的典型技术包括Oracle 11g集群数据库RAC技术。在11g中为适应网格计算和云计算发展需求,RAC增强了很多新技术,例如:RAC中Service技术的增强、基于策略的RAC管理技术(Policy-managed Oracle RAC)、网格即插即用技术(Grid Plug and Play)、实例隔离(Instance Caging)技术等。

另外该领域也包括内存数据库的增强技术(TimesTen In-Memory Database)等。

  • 海量数据管理和信息生命周期管理(VLDB & ILM)

该领域的典型技术包括分区技术的增强和新的压缩技术。在分区方面,11g增加了间隔分区、系统分区、引用分区、虚拟列分区,以及多种组合分区等。Oracle自1996年的8版就开始提供分区技术,但到了11g又提供那么多新功能,可以说是老树发新芽,将分区技术又推向一个新的高峰,为我们开展VLDB数据库设计和开发打下一个非常良好的技术基础。

11g在原有压缩技术基础上,提供了针对OLTP应用的大并发量随机DML操作的压缩技术,以及针对Exadata的混合列压缩技术,大大拓展了压缩技术的应用场景和空间。本书后面将专题介绍11g压缩技术。

  • 数据仓库和商务智能领域(DW & BI)

为用户提供简单集成、强大的数据仓库和商务智能,满足各种数据分析需求,是Oracle公司多年来一直努力追求的目标。例如,11g集成了ETL工具(Oracle Warehouse Builder)并提供多种ETL内置功能,提供了适合数据仓库的自动并行处理功能,统计分析语句和函数也得到了进一步增强,上述各种新的分区技术等。

  • 安全性(Security)

在11g中,数据安全性得到了进一步的增强。例如,针对数据库访问权限控制的Database Vault得到了进一步增强,通过范围域(Realm)划分、要素(Factors)、命令规则(Command Rules)等设计,可以有效加强数据库访问权限控制。

11g中的集中审计产品Audit Vault也得到了显著增强。通过该产品的部署,可以实现一点对多套数据库的集中审计和智能分析,有效保障了审计信息的安全性,提高了审计部署的效率,也加深了审计信息分析层次。

另外,为满足企业长久甚至永久保持和利用历史记录的目的,11g提供了基于新的Flashback Data Archive(FDA)技术的Total Recall产品,通过该产品,企业可加强对历史数据的安全审计,并进行市场和客户行为分析,从而全面提升自身竞争力。本书后面也将专题介绍基于FDA的Total Recall技术。

  • 可管理性和变更管理(Management & Change)

易管理性是Oracle自10g开始发展的一个重要方面。10g/11g将先进的、自动管理特性直接内嵌在数据库内部,并通过完全基于Web风格的GUI图形界面方式以及大量实用工具,为数据库管理的高质量提供了良好的使用环境。例如,Oracle 10g/11g提供了大量A打头的内嵌的、自动化的智能管理产品和特性:自动存储管理(Automatic Storage Management)、自动内存管理(Automatic Memory Management)、优化器统计信息自动采集功能(Automatic Optimizer Statistics Collection)、SQL语句自动优化功能(Automatic SQL Tuning)…

变更管理是11g一个全新的领域。11g的Real Application Testing(RAT)通过捕获实际的生产数据库工作负载,并在变更的测试环境中重演。RAT能够分析和报告所发现的任何差异,例如性能改善或退化、数据差异和错误。与仿真测试软件截然不同的是,RAT不必开发仿真工作负载或脚本,RAT可以提高测试效率和测试真实性,为变更管理提供了良好的技术手段。

换几个角度的一瞥

以下我们再换几个角度对Oracle 11g相关产品特别是新技术进行一番俯瞰。

  • 产品布局角度

以下就是11g相关产品的总体布局:

 

11g2

 

其中RAC和Cluster集群技术作为整个生产环境的数据库核心技术,将为客户IT系统带来高可用性、高性能、可扩展性等功能。

数据库的ASM存储管理技术不仅为海量数据处理带来了更好的性能和可管理性,而且也是未来Oracle数据库存储技术的事实上标准和发展方向。

SecurefFiles作为新一代的大对象(LOB)处理技术,将比传统LOB技术处理更简化,也将带来压缩、去重、加密等新功能。

XML作为统一的数据模型语言,Oracle公司的支持一直不遗余力,例如,Oracle 10g就成为了第一个支持XML Query标准的商业化产品。

数据库高级压缩(Advanced Compression)技术给客户带来的不仅是存储资源开销的下降,而且也将带来性能的提升。

作为数据屏蔽技术产品,Data Masking不仅能为客户关键和敏感业务数据进行漂白,供开发测试之用,而且对应用透明,确保数据之间依赖关系。

Total Recall和Flashback技术为防范各种人为错误和历史数据安全审计提供了良好的技术手段。

Data Guard,特别是Active Data Guard不仅为Oracle数据库提供了健壮、经济的容灾技术,而且为容灾库的利用提供了技术基础。

而作为Oracle集中运行维护管理平台产品,Grid Control在11g中无论在功能,还是在产品的集成性和易用性方面,都有显著提升。

  • 客户回报角度

以下就是从几个客户回报角度俯瞰的Oracle 11g相关产品和技术:

 

11g3

 

首先,在节省软硬件和人工成本方面,高级压缩(Advanced Compression)、ASM、RAT、EM等技术在数据库存储、测试和运行维护等方面都将起到重要作用。

其次,从性能角度看,高级压缩(Advanced Compression)、ASM、Flash Cache、ADDM for RAC、自动并行处理(Automated Degree of Parallism)、新的分区技术等,为11g应用的高性能提供了广阔的技术运用空间。

再者,在提高业务连续性方面,Active Data Guard、ASM、Total Recall等产品和技术也是作用显著。

最后,从简化管理、提高生产率方面,RAT、ADDM for RAC以及更全面的智能工具的使用,也是测试、故障诊断和性能优化等方面的重要手段。

 

 一个纠结的话题

为深入讨论11g相关技术和使用策略,我们先讨论一个纠结的话题:绑定变量的使用,并讨论这个话题在11g的最新技术进展。通过这个话题的讨论,来作为制定11g新技术实施总体策略进行铺垫。

影响性能的一个重要问题

所谓绑定变量的使用,或者说语句共享性问题,是指在应用开发过程中,SQL语句的条件编写方式。例如:

SELECT *
 FROM aueic.T_REAL_TIME_POWER rtp
 WHERE rtp.id=90102601 AND rtp.d_date >= to_date('20111205','yyyymmdd')
 ORDER BY rtp.d_date DESC




SELECT *
 FROM aueic.T_REAL_TIME_POWER rtp
 WHERE rtp.id=90102657 AND rtp.d_date >= to_date('20111205','yyyymmdd')
ORDER BY rtp.d_date DESC
 
… …

 

上述两个语句除了条件不同(rtp.id和rtp.d_date字段条件值不同),其实语句是相同的。但Oracle优化器在执行时,认为是两条不同的语句,不得不进行所谓的硬解析(Hard Parse),也就是进行一次完整的解析操作,消耗了大量CPU和shared pool内存资源。这也是导致系统应用性能差,特别是联机交易系统性能差的一个重要原因。

 

按下葫芦起了瓢

解决上述问题的主要办法有如下两种:

  • 应用级绑定变量的使用:即将SQL语句中的条件值修改为变量。
  • 系统级绑定变量的使用:即通过设置CURSOR_SHARING参数为SIMILAR/FORCE,由Oracle强制将常量条件修改为系统绑定变量,例如:SYS_B0,SYS_B1等。

上述两种策略都可显著降低系统硬解析次数,从而有效降低Oracle在语句解析过程中对CPU和内存的开销。但是新的问题出来了:针对使用绑定变量的语句,Oracle将产生相同的执行计划,而有些SQL语句需要根据绑定变量的不同值产生不同的最优执行计划。例如:

 

SELECT * FROM jobs WHERE min_salary > 12000;

SELECT * FROM jobs WHERE min_salary > 18000;

SELECT * FROM jobs WHERE min_salary > 7500;

 

假设min_salary > 18000的记录很少,而min_salary > 12000和min_salary > 7500的记录很多,则上述第1条和第3条语句的最优执行计划应该是全表扫描,而第2条语句的最优执行计划应该是按索引访问。但是,如果使用了如下方式的绑定变量:

SELECT * FROM jobs WHERE min_salary > :min_sal;

 

则Oracle将采用相同的执行计划,无论是全表扫描还是按索引访问,显然对某些变量值的执行路径不是最优的。

大家知道,一个SQL语句的执行过程通常分为Parse->Bind->Excute->Fetch等阶段,每个阶段都应该考虑优化。使用绑定变量,是为了提高语句共享性,降低语句Parse的次数。而执行计划的最优化是提高语句Execute效率。现在,二者遇到了冲突和矛盾,真纠结啊!

另外,Oracle自9i开始提供了绑定变量窥视功能(Bind Peeking),但该功能只是偷看了绑定变量的第一个真实值来辅助优化器产生执行计划,以后针对不同变量值,均采用相同的执行路径。显然,该功能并不能解决上述纠结的问题。

11g的自适应游标共享功能

11g出来了,很快发现有了个所谓的自适应游标共享功能(Adaptive Cursor Sharing)功能,能有效解决上述问题。例如,针对上述绑定变量语句,Oracle 11g通过该功能,可以为第1条和第3条语句产生全表扫描的执行计划,为第2条语句产生按索引访问的执行计划。太牛了!

下图就是其工作流程示意图:

 

11g4

 

  1. 语句在第一次执行时,按正常情况进行硬解析,并且将两个条件的可选性值域(15,0.0025)记录在该语句的游标之中。
  2. 语句在第二次执行时,分析两个条件的可选性值域(18,0.003),依然位于现有的可选性值域(0.15,0.0025)之中,因此继续采用现有的执行计划。
  3. 语句在第三次执行时,分析两个条件的可选性值域(3,0.009),已经不在现有的可选性值域(0.18,0.003)之中了,因此Oracle重新进行硬解析,产生新的更优化的执行计划了。
  4. 语句在第四次执行时,分析两个条件的可选性值域(28,0.004),又不在现有的任何一个可选性值域了,因此Oracle又重新进行硬解析并产生新的执行计划。假设这次产生的执行计划与第一次相同,于是Oracle将本次可选性值域与第一次可选性值域进行合并(Merge)操作,形成更大的可选性值域。

用户可通过V$SQL、V$SQL_CS_HISTOGRAM、V$SQL_CS_SELECTIVITY、V$SQL_CS_STATISTICS等新老视图去监控该功能的使用情况。

 

如何谨慎使用自适应游标共享功能?

11g自适应游标共享功能(Adaptive Cursor Sharing),似乎非常美妙,但你敢不假思索就用吗?

首先,就象任何新生事物都比较稚嫩一样,11g自适应游标共享功能同样存在这样那样的Bug。例如,以下就是Oracle在11.2.0.3中修复的与Adaptive Cursor Sharing相关的Bug:

 

9532657 Adaptive cursor sharing ignores SELECTs which are not fully fetched
10182051 Extended cursor sharing generates many shareable child cursors
11657468 Excessive mutex waits with adaptive cursor sharing

 

进一步分析Bug 11657468,我们知道受该Bug影响的版本包括11.2.0.2、11.1.0.7,该Bug最终将在11.2.0.3和未来的12.1中被修复。

其次,我们再深入分析一下自己的应用,假设我们的应用语句的绑定变量值不存在畸形变化的情况,也就是说可选性值域比较固定,例如账号、手机号等字段的可选性比较高,Oracle有必要象上述原理图一样,为每个变量值都进行可选性值域的计算吗?这不反而增加了系统负担吗?

总之,是否该使用绑定变量,还是最了解应用和数据的开发人员最有发言权,Oracle你就别费心了。

Oracle也太自信了,居然将该功能设置为自动打开的,而且一般用户无法通过公开参数去关闭。如何关闭?需要设置如下隐含参数:

_optimizer_adaptive_cursor_sharing = false

_optimizer_extended_cursor_sharing_rel = “none”

11g还有多少这样缺省打开但可能存在风险的新特性?如何酌情关闭?如何合理运用11g新特性?这就是后面要继续展开的内容了。

 

11g新技术实施总体策略

如前所述,Oracle 11g的新技术和新特性林林总总不下好几百。在上述银行客户系统研究11g新特性的刺激下,结合其它客户的需求,我们服务团队后来也专门组织人员进行了专题研究工作,涵盖应用开发、高可用性提升、高可用性的整合和简化、性能提升、DB工具、DW和BI、Cluster提升、内容管理服务、诊断和修复、扩展性和集成性、系统管理、安全性等诸多领域。

但就象任何新生事物都有个成长过程一样,这些新东西也难免有这样、那样的问题。如何根据IT系统的实际需要,有针对性地使用11g相关新技术,特别是规避相关问题,的确是考虑IT系统建设者智慧的一个重要话题。

根据在国内相关行业实施11g的经验,我们建议采取这样的总体原则:积极稳妥,分阶段实施。以下就是示意图:

 

11g5

 

 

  • 第一阶段为慎用阶段。即尽量慎用甚至禁止使用11g新特性。例如对11g所有缺省的自动功能进行一次排查,研究这些新特性的适用场景,结合相关系统的实际情况,确定是否需要关闭,并研究如何关闭的技术,以及可能导致的影响。

例如,可先设置compatible参数为原来的10g甚至为9i状态,将优化器运行在原有模式下。针对不同系统,对11g缺省打开的auto optimizer stats collection、auto space advisor、SQL tuning advisor等作业研究是否需要关闭,或采取其它客户化技术方案。对Adaptive Cursor Sharing等隐含特性研究是否存在Bug,如何关闭等。

  • 第二阶段为逐步深入使用阶段。即确定从外围到核心技术,从后台业务到前台业务、从非关键业务系统到关键业务系统等原则,在充分进行需求分析基础上,合理采用相关新技术,并组织全面深入的测试,以及结合版本和补丁管理服务等,逐步投入到生产环境。

例如,先从数据备份、统计信息采集等外围、后台技术的运用开始,逐步深入到诸如SQL Automatic Tuning、空间自动分析、SecureFiles、Flashback等核心技术。

这个阶段的工作均围绕数据库本身已带的新特性的应用,不涉及数据库的各种选项。

  • 第三阶段为全面推广阶段。即结合相关需求,开展围绕数据库选项方面的技术实施。例如:围绕新分区技术、Total-Recall技术、数据压缩、Database Replay、安全性等方面技术,全面推广11g相关新技术/新特性的运用。

下面几个章节,我们将围绕11g中数据压缩、SQL Query Result Cache、SPM、SecureFiles等技术展开专题讨论,希望11g相关技术在大家的实际IT系统中发挥应有作用,也希望给大家的实际设计、开发、测试等工作带来帮助。

 

5.5本章参考资料及进一步读物

本章的参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
1. Oracle 11g R2联机文档 《Oracle® Database New Features Guide》 Oracle每推出一个新版本,都会同步推出一本“New Features”的书,分门别类、全面系统地介绍了新版本中的新技术和新特性。一旦新版本推出,技术高手往往都会第一时间就去找这本书:“看看Oracle又出了什么新东西?”
2. Oracle 11g R2联机文档 《Oracle® Database Upgrade Guide》 这是一本全面介绍Oracle数据库升级方法论和升级过程的文档。除此之外,该书附录A:“Behavior Changes After Upgrading Oracle Database”专门描述了升级到11g之后的一些变更。
3. Oracle大学教材 《Oracle® Database 11g New Features》 每次Oracle推出新版本,Oracle大学都会有这样一门介绍新特性的课程,也的确是系统了解和掌握新版本新特性的良好途径,本人也是每次都参加这门课的培训。欲阅读此教材吗?只好报名参加培训了。
4. Oracle白皮书 《Oracle Database 11g:The Top New Features for DBAs and Developers》 这是Oracle公司针对11g新特性而发布的白皮书。链接如下:

http://www.oracle.com/technetwork/articles/grid/index-099021.html

涵盖了Database Replay、事务管理、SQL执行计划管理(SPM)、SQL Access Advisor等20个领域和主题,值得DBA和开发人员好好学习。

5. My Oracle Support 《11g New Features – Database Core (Doc ID 1226873.1)》 这可是11g若干新特性的集散地。例如:ASM支持4K扇区、临时表空间新特性、外部表新特性、新一代大对象技术SecureFiles……
6. My Oracle Support 《Oracle Database 11g Release 2 Information Center (Doc ID 988222.1)》 又一扇走入11g新特性的大门,去打开这扇大门吧!

 

 

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟: 性能优化:百谈不厌的话题

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

本文永久地址:https://www.askmac.cn/?p=16572

 

本人的第一本书《品悟性能优化》,“洋洋洒洒”近500页,按Oracle性能优化方法论从上往下,即从应用设计开发,到系统层面逐步展开叙述。性能优化的确是IT系统各方人士长期面临的艰难挑战,也是大家百谈不厌的话题。本书虽然没有对性能优化再浓墨重彩,但很多章节内容其实也是围绕性能优化而展开的。

本章我们先对《品悟性能优化》一些重要观点进行回顾,然后再通过若干案例,对这些观点进行总结。同时,由于受篇幅等因素限制,针对《品悟性能优化》书所没有包括的一些优化技术,例如适合于数据仓库的Bitmap索引、Bitmap Join索引等进行介绍。

众所周知,应用性能问题对系统整体性能影响最大,所以本章案例更多地侧重于应用性能问题的解剖。同时,性能问题也涉及IT系统的方方面面,本章最后一个案例就是分析数据库备份恢复中的性能问题。

 

重温《品悟性能优化》一些重要观点

回顾性能优化方法论

Oracle性能优化方法论主要分为如下两种:

  • 自顶向下(Top-Bottom)

该方法论可以如下图表示:

data87

 

即在项目设计、开发、上线的全程都展开性能优化工作,而且优化工作开始地越早,其效益也越高,同时付出的成本也最小。而优化工作开始地越晚,其效益也越低,并且付出的成本也最大。

之所以叫自顶向下,是因为一方面从软件生命周期角度而言,从头开始就关注性能优化工作。另一方面,最初我们在业务逻辑、架构设计等层面关注性能问题,然后再逐步深入到应用设计、开发和测试层面考虑优化,最后才到数据库系统、操作系统、硬件等层面考虑参数设置、存储配置等优化,即从IT系统架构层面而言,也是自顶向下的。

总之,自顶向下更适合于一个新项目的建设。

  • 自底向上(Bottom -Top)

如果针对一个已经投产的系统发生的性能问题,则我们需要采用自底向上方法论了。以下就是自底向上方法论示意图:

data88

 

即我们先从系统层面开始,了解硬件配置,检查系统的CPU、I/O利用率等,然后再逐步了解到数据库的各种等待事件,从而基本确定性能瓶颈所在,最后再重点分析应用问题。即从IT系统架构层面而言,是自底向上的。

另外,从上线后发现性能问题,到逐步分析出某个SQL语句、某个应用问题,最终可能回溯到数据库设计、数据库架构,甚至业务流程设计的问题,因此这种问题分析和解决方式从IT系统时间轴上分析,也是自底向上,自后往前的。

 

性能优化中的20/80规则

  • 数据库体系结构设计和应用设计对系统性能的影响能占到80%,而硬件配置、参数调整、系统软件Bug等系统方面因素,只占到20%。
  • 80%的性能问题是由20%的应用导致的。如少量大表的全表扫描导致的性能瓶颈。并不是应用一有问题,就一定要对现有数据库结构大卸八块,应用推倒重来。
  • 80%的性能问题可以由20%的优化技术所解决。如简单的索引策略,执行路径分析等,能解决绝大部分性能问题。

应用开发指导思想

建议应用系统设计和开发人员在开发过程中,在开发指导思想上进行如下方面的加强:

  • 不仅关注SQL语句功能,而且要关注性能。即用量化手段,进行SQL语句质量控制
  • 开发队伍能有层次性和专业分工。不仅按照业务模块分工,而且有专门的质量控制,尤其是SQL质量控制人员
  • 加强软件开发的规范管理
  • 注重知识共享和传递,减少低级错误的重复性
  • 强调实际测试的重要性。切忌想当然的主观推断,一切以实际应用在尽可能真实数据和环境下的测试数据为准

针对OLTP和OLAP系统,合理运用不同技术

IT系统总体上可以分为OLTP和OLAP系统,数据库系统优化的目标与应用系统的类型是紧密相关的。这两类系统无论在业务特征还是适用的技术方面都迥然不同。例如,针对生产系统,应以系统的响应速度作为首要的优化目标。而对查询统计系统而言,则应该以系统整体吞吐量作为优化目标。

以下是我们总结的两类系统在业务操作特征,以及技术运用方面的主要区别:

比较项目 联机业务 批处理业务
业务特征 操作特点 日常业务操作,尤其是包含大量前台操作 后台操作,例如统计报表、大批量数据加载
响应速度 优先级最高,要求反应速度非常高 要求速度高、吞吐量大
吞吐量
并发访问量 非常高 不高
单笔事务的资源消耗
SQL语句类型 主要是插入和修改操作(DML) 主要是大量查询操作或批量DML操作
技术运用 索引类型 B*索引 Bitmap、Bitmap Join索引
索引量 适量
按索引访问 全表扫描
连接方式 Nested_loop Hash Join
BIND变量 使用或强制使用 不使用
并行技术 使用不多 大量使用
分区技术 使用,但目标不同 使用,但目标不同
物化视图使用 少量使用 大量使用

索引设计规范

无论在联机业务系统,还是在批处理业务系统中,简单的索引策略,能解决绝大部分性能问题。因此,索引设计是开发人员应首要关注的设计规范和策略。合理的索引设计将有效降低不必要的全表扫描,大大降低系统资源消耗,提高整个IT系统的生命周期。

下面将由简及繁,介绍索引设计规范和策略:

  • B*树单字段索引设计规范和策略
  • 分析SQL语句中的约束条件字段
  • 如果约束条件字段不固定,建议创建针对单字段的普通B*树索引
  • 选择可选性最高的字段建立索引
  • 如果是多表连接SQL语句,注意被驱动表(drived table)的连接字段是否需要创建索引
  • 通过多种SQL分析工具,分析执行计划并以量化形式评估效果
  • B*树复合索引设计规范和建议
  • 分析SQL语句中的约束条件字段
  • 如果约束条件字段比较固定,则优先考虑创建针对多字段的普通B*树复合索引。
  • 在复合索引设计中,需首先考虑复合索引第一个设计原则:复合索引的前缀性(prefixing)。即SQL语句中,只有复合索引的第一个字段作为约束条件,该复合索引才会启用。
  • 在复合索引设计中,其次应考虑复合索引的可选性(Selectivity或Cardinality)。即按可选性高低,进行复合索引字段的排序。
  • 如果是多表连接SQL语句,注意是否可以在被驱动表(drived table)的连接字段与该表的其它约束条件字段上,创建复合索引。
  • 通过多种SQL分析工具,分析执行计划并以量化形式评估效果
  • 如何避免索引被抑制问题

导致不必要的全表扫描的一个重要原因是:虽然在相关字段建立了索引,但因如下一些因素导致索引被抑制。

  • 在字段前增加了函数

在字段前增加了函数,将导致索引无法使用,应尽量将字段前的函数进行转换。例如:

 

to_char(c.total_date) between :in_begin_time and :in_end_time

应修改为:

c.total_date between to_date(:in_begin_time,’YYYY.MM.DD’) and to_date(:in_end_time,’YYYY.MM.DD’)

 

  • 字段类型设计问题

如果因字段类型设计不合理,将迫使应用程序使用函数,从而导致索引无法使用。例如日期数据以字符类型进行表达,将被迫导致SQL语句使用substr,trim等函数。错误地使用char字段,也将导致使用trim函数进行空格的截取。

  • 将字段嵌入表达式之中

将字段嵌入表达式之中,也将导致索引无法使用,应尽量将字段从表达式中进行剥离。例如:

and (sysdate – to_date(a.efftt, ‘yyyymmddhh24miss’)) * 24 * 60 <= 15

应修改为:

and a.efftt >= to_char((sysdate – 1/96),’yyyymmddhh24miss’);

  • 函数索引设计规范

如果可能,应尽量避免创建函数索引,因为函数索引将导致DML操作资源消耗增加。例如上述的的to_char字段,应调整为to_date。如果需要创建函数索引,则Oracle优化器要运行在CBO模式下,即应定期进行统计信息的采集和更新。

  • Bitmap索引设计规范

Bitmap位图索引适合于统计分析应用。建议针对可选性(Selectivity或Cardinality)低的字段,创建Bitmap位图索引或Bitmap Join位图索引。Bitmap索引应运行在CBO模式下,即应定期进行统计信息的采集和更新。

 

交易系统中绑定变量使用规范

交易系统具有单笔查询的资源消耗小、并发量高等特征。在交易系统中,大量重复的SQL语句的Parse操作,不仅极大地消耗了CPU资源,而且长远来看,也是影响交易系统扩展性和系统生命周期的重要因素。

针对交易系统,应尽量通过如下两种策略,实现SQL语句的Bind化处理,减少SQL语句的Parse次数,提高SQL语句共享性。

  • 应用级Bind化处理

尽量在SQL语句中使用绑定变量,例如:

  • PL/SQL中使用USING短语
  • JDBC中通过PrepareStatement、SetXXX()的调用,为SQL语句的?变量赋值
  • 系统级Bind化处理

通过将Oracle初始化参数CURSOR_SHARING由缺省的EXACT修改为FORCE,实现系统级Bind化处理。

建议优先考虑应用级Bind化处理规范。

查询统计系统中绑定变量使用规范

查询统计系统具有单笔事务的资源消耗大、并发量不高等特点。这类应用SQL语句的资源消耗主要在Execute和Fetch阶段,而Parse量并不高。因此应该保证这类应用语句执行计划的最优化。

为此,无需通过SQL语句共享性来保证这类应用的性能,而通过保持查询条件的常量化,来保证执行计划的最优化。因此,不需要语句的Bind化处理,也不需要将EXACT修改为FORCE。

交易系统和数据仓库系统的不同表连接技术

在交易系统中,大部分表连接语句虽然访问的表可能很大,但其实只是查询少量数据,因此建议尽量采用Nested_Loop技术,并结合上述索引策略,特别注意被驱动表(drived table)的连接字段是否需要创建单字段索引和复合索引。

在数据仓库系统中,大部分表连接语句是查询大规模数据,建议尽量采用HASH_JOIN技术,并考虑并行处理技术。

 

4.2 深入剖析一个测试题

某次为某公司提供性能优化培训和服务过程中,该公司开发团队负责人提出:“罗老师,能不能增加一些实际操作的测试题,检验我们开发团队人员的实际技术能力和培训效果?”没问题,我在以往多次培训和技术交流中就经常进行这种测试。于是,这次针对该客户具体需求和时间安排,特意设计了理论与实际结合的10道题目。下面就深入剖析其中一个实际操作题。

题目

“针对如下语句:

 

select c.channel_desc, s.quantity_sold, s.amount_sold
  from kj_channels c, kj_sales s, kj_products p
 where c.channel_id = s.channel_id
   and p.prod_id = s.prod_id
   and c.channel_desc = 'Internet'
   and p.prod_name = 'Laptop carrying case';

 

 

请确定最佳索引方案,并进行执行计划和执行效率分析。”

该题目测试目的一方面为了检验大家对索引原理和设计规范的掌握程度,例如如何设计单字段索引和复合索引。另一方面,也是更重要的为了让大家能提升开发设计指导思想,例如不仅关注SQL语句功能,而且要关注性能。即用量化手段,进行SQL语句质量控制;加强软件开发的规范管理等等。

在本书此处介绍该测试题,也是对上述性能优化一些重要观点的验证。

答案

该题目的答案其实很简单,即应设计如下索引:

 

Create index idx_1 on kj_channels(channel_desc);

Create index idx_2 on kj_products(prod_name);

Create index idx_3 on kj_sales(prod_id,channel_id);

 

但为什么?能不能从量化角度给出设计依据?以下的测试结果表格是我希望看到大家解答这个题目的过程:

序号 索引方案 运行时间 执行计划 Cost Consistent Gets physical reads
1. 无索引 00: 00: 01.04 三个表全表扫描 1241 4868 4668
2. kj_channels(channel_desc) 00: 00: 00.98 kj_channels表按索引访问,kj_products、kj_sales表全表扫描 1239 4898 4681
3. kj_channels(channel_desc)

kj_products(prod_name)

00: 00: 01.15 kj_channels、kj_products表按索引访问,kj_sales表全表扫描 1238 4918 4693
4. kj_channels(channel_desc)

kj_products(prod_name)

kj_sales(prod_id)

kj_sales(channel_id)

00: 00: 01.02 三个表全部按索引访问 172 713 451
5. kj_channels(channel_desc)

kj_products(prod_name)

kj_sales(channel_id ,prod_id)

00: 00: 00.93 三个表全部按索引访问 94 658 409
6. kj_channels(channel_desc)

kj_products(prod_name)

kj_sales(prod_id, channel_id )

00: 00: 01.32 三个表全部按索引访问 94 657 406
  1. 方案1:三个表均没有设计索引,执行计划当然为全表扫描,各项指标仅作为基准指标。
  2. 方案2:只设计了kj_channels(channel_desc)索引,执行计划为对kj_channels表按索引访问,但kj_products、kj_sales表依然是全表扫描。各项指标没有明显优化。
  3. 方案3:在方案2基础上增加了kj_products(prod_name) 索引,执行计划为对kj_channels、kj_products表按索引访问,但kj_sales表依然是全表扫描。各项指标依然没有明显优化。
  4. 方案4:在方案3基础上增加了kj_sales(prod_id)、kj_sales(channel_id)两个单字段索引,执行计划为三个表全部按索引访问。各项指标相比前三个方案得到明显优化。
  5. 方案5:在方案3基础上增加了kj_sales(channel_id ,prod_id)一个复合索引,执行计划为三个表全部按索引访问。各项指标相比方案4又得到一定优化,说明复合索引对性能提升的重要性。
  6. 方案6:在方案3基础上增加了kj_sales(prod_id ,channel_id )一个复合索引,执行计划为三个表全部按索引访问。各项指标相比方案5又得到一定优化。这是因为prod_id不同记录值为72,而channel_id不同记录值为4,说明复合索引的可选性对性能提升的作用。即应将不同记录值最多的字段放在复合索引第一个字段,不同记录值次多的字段放在复合索引第二个字段,以此类推。

可见,上述方案6才是该SQL语句的最佳索引方案,以下就是该语句在方案6下的执行计划:

 

data89

需要说明的是:由于该测试题采用的数据是Oracle 11g的 SH用户下的样本数据,数据量有限,有些测试结果仅仅作为参考,例如语句运行时间等。如果在更真实、更大数据量环境下进行测试,上述指标将更具有说服力。

 

又一次救火经历

先了解火情

某天正在东北某城市出差,突然接到了某客户的紧急救援电话:“罗工,能帮助分析一下吗?我们一个社会保险系统的性能很差,机器都满负荷跑了,都快撑不住了!”就象消防队员一样,先了解火情吧。由于还是9i系统,于是向客户提出请求:“能将该系统的statspack报告发过来一份吗?”因此,很快看到了该系统的主要情况:

  • 总体负载指标

 

Load Profile

~~~~~~~~~~~~                            Per Second       Per Transaction

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

                  Redo size:              3,550.96              7,048.70
              Logical reads:            209,462.91            415,786.12
              Block changes:                 14.53                 28.84
             Physical reads:             47,085.54             93,465.31
            Physical writes:                  0.84                  1.67
                 User calls:                 69.18                137.33
                     Parses:                  9.60                 19.06
                Hard parses:                  0.08                  0.16
                      Sorts:                  2.75                  5.45
                     Logons:                  0.06                  0.12
                   Executes:                 10.54                 20.93
                   Transactions:                  0.50

 

 

其中:逻辑读(Logical reads):209,462.91*8K = 1636M/s,物理读(Physical reads:):47,085.54*8K = 367M/s。该系统运行在一台非常老的IBM服务器上,上述硬件指标的确让该设备不堪重负了。

  • 实例有效性指标
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Buffer Nowait %:   99.49       Redo NoWait %:     99.99
            Buffer  Hit   %:   77.52    In-memory Sort %:    100.00
            Library Hit   %:   99.80        Soft Parse %:     99.16
         Execute to Parse %:    8.94         Latch Hit %:     99.44
Parse CPU to Parse Elapsd %:   48.41     % Non-Parse CPU:     99.97

 

其中Buffer Hit仅为77.52%,说明数据访问量太大,Buffer Cache根本放不下了,尽管还未到现场,已经隐约感觉到应用的问题了,特别是大量不合理的全表扫描。

  • 主要等待事件
Top 5 Timed Events

~~~~~~~~~~~~~~~~~~                                                     % Total

Event                                               Waits    Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
CPU time                                                       21,188    39.88
latch free                                        527,508      13,256    24.95
db file scattered read                         15,503,335       8,292    15.61
buffer busy waits                               2,996,271       5,342    10.06
db file sequential read                        58,834,851       4,977     9.37
          -------------------------------------------------------------

其中latch free、db file scattered read等待事件非常高,均与应用程序相关。尤其是db file scattered read等待事件直接表示全表扫描。

总之,上述各类指标均表明由于应用程序存在一定质量问题,导致系统负载非常严重。情况基本摸清楚了,但应用软件性能分析和优化一定要去现场。于是与客户商量,第二天即赶赴了现场。

应用典型问题

在现场分析应用之后,果然发现该系统应用问题较多,但无外乎缺少索引、复合索引次序不对、字段前错误使用函数等典型问题。以下典型语句就是字段前错误使用函数的分析和解决过程。

  • 语句运行现状

语句现状:

 

select count(distinct sfzhm)
  from rsgl.qk61
 where zglbbm = :1
   and (mzfse <> 0 or tdze1 <> 0 or tdze2 <> 0 or tdze3 <> 0)
   and lxylfse = 0
   and (to_char(sj, 'YYYY.MM') = to_char(:2, 'YYYY.MM'))
   and (scbj <> 'T' or scbj is null)
   and substr(dwbm, 1, length(:3)) = :4

 

执行计划如下:

 

data90

 

可见,目前该语句对rsgl.qk61表进行不合理的全表扫描。

  • 分析及优化建议

根据现场分析及与应用开发人员的沟通,该语句主要通过时间(SJ)、单位代码(DWDM)两个字段进行查询,而目前缺乏这两个字段的索引。同时该语句在SJ、DWDM字段前均有函数存在,并且substr(dwbm, 1, length(:3))还带有函数length。因此,优化建议如下:

  1. 创建如下复合索引

 

create index idx_ora_1 on RSGL.qk61(substr(dwbm, 1, 12), to_char(sj, ‘YYYY.MM’)) tablespace RSGL;

 

create index idx_ora_2 on RSGL.qk61(substr(dwbm, 1, 15), to_char(sj, ‘YYYY.MM’)) tablespace RSGL;

 

create index idx_ora_3 on RSGL.qk61(substr(dwbm, 1, 18), to_char(sj, ‘YYYY.MM’)) tablespace RSGL;

 

create index idx_ora_5 on RSGL.qk61(substr(dwbm, 1, 12), to_char(sj, ‘YYYY.MM.DD’)) tablespace RSGL;

 

create index idx_ora_6 on RSGL.qk61(substr(dwbm, 1, 15), to_char(sj, ‘YYYY.MM.DD’)) tablespace RSGL;

 

create index idx_ora_7 on RSGL.qk61(substr(dwbm, 1, 18), to_char(sj, ‘YYYY.MM.DD’)) tablespace RSGL;

 

 

  1. 应用语句进行一定改造

为顺利使用上述新建索引,应用语句需要进行一定改造。具体为去掉substr(dwbm, 1, length(:3))中的length函数,而修改为实际长度。例如:substr(dwbm, 1, 12),substr(dwbm, 1, 15),substr(dwbm, 1, 18)等。

通常而言,针对字段前错误使用函数问题的最有效解决方式是修改程序,但考虑该系统的应用软件开发太久远,甚至开发商都找不到了,现在是客户自己在维护程序。因此,只好采取这种创建函数索引,并请客户对应用程序进行一定修改的措施了。感谢客户,更感谢该客户领导,因为是位白发斑斑的领导亲自修改的程序。呵呵。

优化器和统计信息采集

目前,该系统没有采集统计信息,即优化器运行在RBO模式下。但是,上述优化建议的函数索引只能在CBO模式下启动。因此,需要进行统计信息采集,将优化器切换到CBO模式。

先感叹一下:很多客户都不知道优化器和统计信息采集的概念和重要性,CBO不仅能整体上更好地保证应用软件性能,而且也是基于函数索引、Bitmap索引、物化视图等高级技术使用的前提条件。

该系统数据量不大,另外时间紧张,先采取简单策略,基于整个数据库收集统计信息吧,脚本如下:

 

rq="start time":`date +"%Y-%m-%d %H:%M:%S"`
echo $rq>>/DMCDBS01/oracle/script/stats.log
sqlplus /nolog <<EOF
connect / as sysdba;
exec DBMS_STATS.GATHER_DATABASE_STATS (estimate_percent=>10, Degree=>8, Cascade=>TRUE, Granularity=>'ALL');
EOF
rq="stop time":`date +"%Y-%m-%d %H:%M:%S"`
echo $rq>>/DMCDBS01/oracle/script/stats.log

 

 

该系统业务不太复杂,数据量处于缓慢增长,因此暂时采取每月15日18:00自动收集一次吧。脚本如下:

# crontab –l

00 18 15 * * su – oracle -c /DMCDBS01/oracle/script/stats_ora9.sh > /tmp/stats_ora9.out 2>&1

 

优化效果对比

忙乎半天,一定要让客户,特别是客户领导看到优化效果。而且不仅要看到具体数字,还一定要图文并茂,让领导看到图表。—- 刚加入Oracle的时候,就被老员工教育道:在Oracle工作第一要Work Hard,第二还要Work Smartly。呵呵。

以下就是优化前(3月15日上午)与优化后(3月16日上午)的同期性能数据对比:

 

相关指标 3月15日上午 3月16日上午
     
CPU利用率 99% 19%
逻辑读 209,462.91 64,309.52
物理读 47,085.54 849.51
事务数 0.50 6.24
数据缓冲区命中率 77.52 98.68
全表扫描等待事件 15,503,335 93,447

 

一定要给领导看如下的图,多么漂亮、醒目,领导别提多开心了,性能优化其实也是件痛并快乐着的事情。

 

QQ截图20160516112750

 

 

该案例的启示

之所以描述这个技术上并不太复杂的案例,主要目的是试图诠释如下一些观点:

  • 自底向上性能优化方法论的合理运用

如本章第一节所述,从Oracle公司而言,性能优化方法论主要分为自顶向下和自底向上两种。前者是指在项目设计、开发、测试、上线、运维等全方位展开性能方面工作的一种方法论,更适合于一个新系统的建设过程。而后者是当一个已经运行的生产系统出现严重的性能问题时,从IT系统层次而言,需要从硬件、系统软件、应用软件等方面去逐步分析和解决问题的过程。同时,从时间关系角度,是从生产环境定位关键问题,逐步回溯到开发乃至设计等阶段的问题的过程。

上述案例主要运用了自底向上方法论。即针对一个从未接触过的生产系统出现的性能问题,我们先了解系统硬件环境和配置,以及系统资源消耗情况等,进而分析Oracle层面的相关指标和等待事件,从而基本确定问题范围主要是应用问题。再进一步,我们在现场详细分析最消耗资源的SQL语句情况,从而找出具体原因和解决办法。

  • 应用是影响性能问题的最重要因素

上述案例再次验证一个观点:应用是影响性能问题的最重要因素。实际上,该案例的直接原因还是最基础的索引策略问题,最有效的解决办法无外乎是创建了几个基于函数的索引而已。

国内有太多的系统由于在索引策略存在问题,而导致了太严重的性能问题。

  • 性能问题涉及应用开发和运行维护多个层面

上述案例的直接解决办法是创建了几个基于函数的索引,但为了保证解决办法的有效实施,还必须通过统计信息的采集,将优化器从RBO转换成CBO,而这方面工作应该是DBA所为。可见,性能问题的确涉及应用开发和运行维护多个层面。

尽管Oracle公司从10g开始已经提供自动统计信息采集功能,从而尽量让应用程序运行在更先进的CBO模式下。但作为应用开发人员,特别是DBA,还是应该全面掌握技术原理,这样才能在整体上为应用软件性能最优化提供保证。

以本人的经验,国内大部分企业级客户在优化器和统计信息采集方面已经有了很强的意识,甚至很丰富的实施经验。但大部分中小型客户仍然缺乏这方面知识和经验,也是这些系统整体性能不佳的重要原因之一。

 

4.4 某综合报表平台的优化

系统运行现状

某银行的综合报表平台出现了严重的性能问题,其ETL过程经常运行长达数小时、甚至10余个小时。于是,作为原厂商服务售前人员,提前去客户现场踩点了。

 

 

  • 系统环境

该系统的配置和数据库总体情况:

系统名称 数据库及版本 OS HA软件及版本 数据库架构 数据库服务器型号与配置
综合报表平台 Oracle 10.2.0.4 AIX 5.3 HACMP RAC IBM P595

12Core(4.2GHz/Power6 CPU)

71680M 内存

  Oracle 10.2.0.4 AIX 5.3 HACMP RAC IBM P595

12Core(4.2GHz/Power6 CPU)

71680M 内存

  • 采样分析周期

我们分别对如下时间段的AWR报告进行了分析:

  • 2013年1月4 – 6日交易高峰时段
  • 1月2日的2012年终批处理
  • 1月12、13、15、16日的2013年日终批处理

经初步分析,无论交易高峰时段,还是年终批处理和日终批处理,该系统的性能问题都比较严重。以下我们仅以1月4日上午交易高峰时段的 AWR报告进行深入分析。

  • 操作系统总体状况
Statistic Total 利用率
BUSY_TIME 5,255,620 17%
IDLE_TIME 20,665,708 68%
IOWAIT_TIME 4,331,082 14%
SYS_TIME 1,388,394 5%
USER_TIME 3,867,226 12%

可见,在此期间系统CPU空闲率为68%,使用率为17%,而IOWait达到14%。说明该系统存储系统效率不高,成为该系统一个重要瓶颈。难怪乎客户吵吵嚷嚷说存储系统有问题,要迁移到更高端存储去。也特别要谢谢我的同事前期给客户洗脑比较有成效,因为客户还要把数据从裸设备迁移到Oracle ASM中去,呵呵。

  • 数据库总体负载指标
Per Second Per Transaction
Redo size: 529,584.40 45,824.07
Logical reads: 62,949.86 5,446.95
Block changes: 261.27 22.61
Physical reads: 3,608.92 312.27
Physical writes: 30.28 2.62
User calls: 6,318.57 546.74
Parses: 2,101.75 181.86
Hard parses: 61.70 5.34
Sorts: 131.34 11.36
Logons: 0.08 0.01
Executes: 2,697.05 233.37
Transactions: 11.56  
  • 逻辑读/秒非常高,达到62,949.86*32K = 1967M/秒
  • I/O读也非常高,达到3,608.92*32K = 112M/秒
  • 硬解析比较高,Hard Parses/秒= 61.70,该指标正常值应该低于10次/秒,目前指标说明应用软件存在没有合理使用绑定变量的情况。
  • 命中率指标
Buffer Nowait %: 97.24 Redo NoWait %: 100.00
Buffer Hit %: 94.48 In-memory Sort %: 100.00
Library Hit %: 93.00 Soft Parse %: 97.06
Execute to Parse %: 22.07 Latch Hit %: 98.88
Parse CPU to Parse Elapsd %: 23.19 % Non-Parse CPU: 96.01
  • Buffer Hit %:命中率不高,说明应用方面存在较为严重的问题,例如不合理的全表扫描。
  • Library Hit %:和Execute to Parse %:命中率不高,再次说明应用软件没有合理使用绑定变量。
  • 主要等待事件
Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class
gc buffer busy 18,021,5524 458,799 25 54.1 Cluster
db file sequential read 30,079,633 132,923 4 15.7 User I/O
gc cr multi block request 4,486,393 49,507 11 5.8 Cluster
read by other session 736,260 40,725 55 4.8 User I/O
gc cr block lost 93,394 39,559 424 4.7 Cluster
  • gc buffer busy等待事件最高,说明RAC节点间访问冲突和流量比较大。
  • db file sequential read等待事件比较高,表示系统存在大量因为索引而出现的等待事件。原因无外乎以下几种:
  1. 应用软件质量较高,大量SQL语句均采用了索引。
  2. 可能有一些索引没有用上,DML操作时,导致索引的维护工作量增加,即产生了大量不必要的索引I/O。
  3. 由于频繁的DML操作,可能导致很多索引碎片,增加了索引I/O开销。
  4. 部分索引设计不合理。虽然使用了索引,但实际是索引扫描,类似于全表扫描。
  • RAC统计信息分析
Per Second Per Transaction
Global Cache blocks received: 949.99 82.20
Global Cache blocks served: 924.65 80.01
GCS/GES messages received: 6,476.55 560.41
GCS/GES messages sent: 6,309.31 545.93
DBWR Fusion writes: 3.53 0.31
Estd Interconnect traffic (KB) 62,485.76

RAC节点间流量达到62M/S,说明RAC节点间访问冲突和流量的确比较大。

  • 时间模型指标
Statistic Name Time (s) % of DB Time
sql execute elapsed time 839,987.35 99.00
DB CPU 34,438.88 4.06
parse time elapsed 11,056.69 1.30
hard parse elapsed time 9,959.10 1.1

可见,该系统的sql execute elapsed time达到99%。而DB CPU只有4.06%,说明该系统大量时间消耗在等待I/O。不仅I/O量大,而且存储设备性能不佳。

  • I/O指标

以下是各表空间的I/O性能指标:

Tablespace Reads Av Reads/s Av Rd(ms) Av Blks/Rd Writes Av Writes/s Buffer Waits Av Buf Wt(ms)
TBS_ADBCDW 31,857,511 2,953 8.77 1.18 478 0 18,680,562 27.20
TBS_ADBCBI 849,626 79 4.14 1.00 193,616 18 25,646 57.35
TBS_ADBCIRPT 128,476 12 21.72 1.16 63,766 6 2,086 54.27
TBS_IDX_ADBCDW 174,805 16 15.77 1.42 1,349 0 17,394 14.31
TBS_BDS 13,570 1 6.07 1.00 21,038 2 0 0.00
SYSTEM 17,246 2 16.71 1.94 3,548 0 560 44.21
UNDOTBS1 3,386 0 14.02 1.00 5,796 1 259 0.00
SYSAUX 3,392 0 15.38 1.02 1,416 0 0 0.00
TBS_ADBCTEMP 1,461 0 7.30 3.43 1,159 0 0 0.00
UNDOTBS2 97 0 29.38 1.00 32 0 680 47.18
TEMP 18 0 15.56 1.00 0 0 0 0.00
USERS 5 0 28.00 1.00 2 0 0 0.00

可见,多数表空间的平均读达到10ms以上,再次说明该系统的存储设备I/O读写性能不佳。

总之,通过对上述多方面指标分析,已经总结出该系统的典型问题了:第一,存储系统的确有问题,第二,应用一定有问题。但应用问题具体在哪儿呢?

典型应用问题分析

虽然该系统存储设备效率不高是一个重要问题,但我们认为数据库设计不合理和应用软件方面存在的问题,才是导致该系统性能不佳的最主要原因。

以下我们对该系统一个典型应用问题进行深入分析:

  • 语句现状

以下语句是2013年1月4日上午最消耗资源的语句:

Elapsed Time (s) CPU Time (s) Executions Elap per Exec (s) % Total DB Time SQL Id SQL Module SQL Text
19,578 658 3 6525.84 2.31 0w08q2c6s0dtx   select * from ( select row$_.*…

可见该语句运行了6525.84秒,将近2个小时。该语句非常长,我们仅截取其中一小段核心语句进行深入分析:

select sum(nvl(a.LOAN_BAL, 0)) as O4,

a.DUE_BILL_ID as F4,

SUBSTR(a.ORG_CD, 1, 6) as D4,

SUBSTR(a.ORG_CD, 1, 4) as B4,

SUBSTR(a.ORG_CD, 1, 2) as A4

from ADBCDW.AC_HB_DUE_BILL_NPL_MONTH a

where (SUBSTR(a.RPT_END_DATE, 1, 6) = ‘201112’)

and (a.ORG_CD like ‘3599%’)

and ((1 > 2 OR a.ORG_CD like ‘3599%’) AND

(SUBSTR(a.NPL_FORM_DATE, 1, 4) < ‘2012’))

group by a.DUE_BILL_ID,

SUBSTR(a.ORG_CD, 1, 6),

SUBSTR(a.ORG_CD, 1, 4),

SUBSTR(a.ORG_CD, 1, 2)

 

PLAN_TABLE_OUTPUT

—————————————————————————————————————————————————————-

Plan hash value: 2416238426

 

—————————————————————————————————————–

| Id  | Operation            | Name                     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

—————————————————————————————————————–

|   0 | SELECT STATEMENT     |                          |     3 |   192 | 69364   (2)| 00:20:49 |       |       |

|   1 |  HASH GROUP BY       |                          |     3 |   192 | 69364   (2)| 00:20:49 |       |       |

|   2 |   PARTITION RANGE ALL|                          |     4 |   256 | 69363   (2)| 00:20:49 |     1 |    38 |

|*  3 |    TABLE ACCESS FULL | AC_HB_DUE_BILL_NPL_MONTH |     4 |   256 | 69363   (2)| 00:20:49 |     1 |    38 |

—————————————————————————————————————–

 

Predicate Information (identified by operation id):

—————————————————

 

3 – filter(“A”.”ORG_CD” LIKE ‘3599%’ AND “A”.”ORG_CD” LIKE ‘3599%’ AND

SUBSTR(“A”.”RPT_END_DATE”,1,6)=’201112′ AND SUBSTR(“A”.”NPL_FORM_DATE”,1,4)<‘2012’)

可见,该语句对AC_HB_DUE_BILL_NPL_MONTH进行全表扫描,而该表记录达到7959560条,而满足上述语句条件的记录仅为17条,显然全表扫描非常不合理。这也是该系统I/O量大的重要原因。

  • 原因分析

首先,我们分析该表按RPT_END_DATE字段进行了按月的范围分区,但RPT_END_DATE字段设计为VARCHAR2(8)。如按月查询,语句中将写成SUBSTR(a.RPT_END_DATE, 1, 6) = ‘201112’。这样,将导致Oracle无法采用分区裁剪功能,也无法使用建立在RPT_END_DATE字段之上的索引,最终导致全表扫描。

其次,我们分析该表的现有索引如下:

TABLE_OWNER                    INDEX_NAME                     COLUMN_NAME                    COLUMN_POSITION

—————————— —————————— —————————— —————

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     RPT_END_DATE                                 1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     DUE_BILL_ID                                  2

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     ORG_CD                                       3

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     PROD_CD                                      4

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     CURR_CM_CD                                   5

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     INDUS_TYPE_CD                                6

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     RISK_5_TYPE_CD                               7

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     RISK_12_TYPE_CD                              8

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_0     LOAN_INTO_CD                                 9

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_1     RISK_5_TYPE_CD                               1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_1     RPT_END_DATE                                 2

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_2     RISK_12_TYPE_CD                              1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_2     RPT_END_DATE                                 2

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_3     RISK_5_TYPE_CD                               1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_4     RISK_12_TYPE_CD                              1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_B1    ITEM_CBS_OUT_CD                              1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_B1    RPT_END_DATE                                 2

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_PK    CUST_ID_CM                                   1

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_PK    DUE_BILL_ID                                  2

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_PK    ORG_CD                                       3

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_PK    ORG_CD_CM                                    4

ADBCDW                         AC_HB_DUE_BILL_NPL_MONTH_PK    RPT_END_DATE                                 5

可见,索引设计方面也存在复合索引设计原则性不明确、索引过多等问题。

  • 优化建议
  • 首先,需要将RPT_END_DATE字段修改为Oracle的Date类型。
  • 其次,需要重新调整分区方案
  • 应用软件需要进行必要的调整。例如将SUBSTR(RPT_END_DATE, 1, 6) = ‘201112’修改为RPT_END_DATE between to_date(‘2012.12’,’YYYY.MM’) and to_date(‘2013.01’,’YYYY.MM’)
  • 重新设计和梳理索引。例如,根据上述语句设计(RPT_END_DATE, ORG_CD)索引等。

应用优化措施测试情况

为验证上述应用优化措施效果,我们于2月4日在现场进行了一定的测试工作。以下是相关细节:

  • 优化前情况

SQL> /

 

COUNT(*)

———-

17

Elapsed: 00:04:08.24

Execution Plan

———————————————————-

Plan hash value: 2114726402

 

—————————————————————————————————————–

| Id  | Operation            | Name                     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

—————————————————————————————————————–

|   0 | SELECT STATEMENT     |                          |     1 |    31 | 69363   (2)| 00:20:49 |       |       |

|   1 |  SORT AGGREGATE      |                          |     1 |    31 |            |          |       |       |

|   2 |   PARTITION RANGE ALL|                          |     4 |   124 | 69363   (2)| 00:20:49 |     1 |    38 |

|*  3 |    TABLE ACCESS FULL | AC_HB_DUE_BILL_NPL_MONTH |     4 |   124 | 69363   (2)| 00:20:49 |     1 |    38 |

—————————————————————————————————————–

 

Predicate Information (identified by operation id):

—————————————————

 

3 – filter(“A”.”ORG_CD” LIKE ‘3599%’ AND “A”.”ORG_CD” LIKE ‘3599%’ AND

SUBSTR(“A”.”RPT_END_DATE”,1,6)=’201112′ AND SUBSTR(“A”.”NPL_FORM_DATE”,1,4)<‘2012’)

 

 

Statistics

———————————————————-

0  recursive calls

0  db block gets

153017  consistent gets

109014  physical reads

0  redo size

515  bytes sent via SQL*Net to client

492  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

 

  • 优化后情况

SQL> select sum(nvl(a.LOAN_BAL, 0)) as O4,

2         a.DUE_BILL_ID as F4,

3         SUBSTR(a.ORG_CD, 1, 6) as D4,

4         SUBSTR(a.ORG_CD, 1, 4) as B4,

5         SUBSTR(a.ORG_CD, 1, 2) as A4

6    from “ADBCDW”.”AC_HB_DUE_BILL_NPL_MONTH_ora” a

7   where RPT_END_DATE between to_date(‘2012.12′,’YYYY.MM’) and to_date(‘2013.01′,’YYYY.MM’)

8     and (a.ORG_CD like ‘3599%’)

9     and ((1 > 2 OR a.ORG_CD like ‘3599%’) AND

10         (SUBSTR(a.NPL_FORM_DATE, 1, 4) < ‘2012’))

11   group by a.DUE_BILL_ID,

12            SUBSTR(a.ORG_CD, 1, 6),

13            SUBSTR(a.ORG_CD, 1, 4),

14            SUBSTR(a.ORG_CD, 1, 2)

15  /

 

17 rows selected.

 

Elapsed: 00:00:00.97

 

Execution Plan

———————————————————-

Plan hash value: 1319675372

 

————————————————————————————————————————————

| Id  | Operation                           | Name                         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

————————————————————————————————————————————

|   0 | SELECT STATEMENT                    |                              |     3 |   192 |   293   (1)| 00:00:06 |       |       |

|   1 |  HASH GROUP BY                      |                              |     3 |   192 |   293   (1)| 00:00:06 |       |       |

|   2 |   PARTITION RANGE ITERATOR          |                              |     3 |   192 |   292   (1)| 00:00:06 |    37 |    38 |

|*  3 |    TABLE ACCESS BY LOCAL INDEX ROWID| AC_HB_DUE_BILL_NPL_MONTH_ora |     3 |   192 |   292   (1)| 00:00:06 |    37 |    38 |

|*  4 |     INDEX RANGE SCAN                | ORA_IND_0                    |  1731 |       |   214   (1)| 00:00:04 |    37 |    38 |

————————————————————————————————————————————

 

Predicate Information (identified by operation id):

—————————————————

 

3 – filter(SUBSTR(“A”.”NPL_FORM_DATE”,1,4)<‘2012’)

4 – access(“RPT_END_DATE”>=TO_DATE(‘ 2012-12-01 00:00:00’, ‘syyyy-mm-dd hh24:mi:ss’) AND “A”.”ORG_CD” LIKE ‘3599%’ AND

“RPT_END_DATE”<=TO_DATE(‘ 2013-01-01 00:00:00’, ‘syyyy-mm-dd hh24:mi:ss’))

filter(“A”.”ORG_CD” LIKE ‘3599%’ AND “A”.”ORG_CD” LIKE ‘3599%’)

 

Note

—–

– dynamic sampling used for this statement

 

 

Statistics

———————————————————-

4  recursive calls

0  db block gets

370  consistent gets

242  physical reads

0  redo size

1685  bytes sent via SQL*Net to client

503  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

17  rows processed

  • 优化对比情况
  优化前 优化后
     
响应速度 00:04:08.24 00:00:00.97
内存消耗 153017 *32K = 4,781M 370*32K=11.56M
I/O消耗 109014  *32K= 3,406M 242*32K=7.56M

可见优化效果非常明显,对比图就免了,不臭显摆了,呵呵。

该案例的感悟

读者已经看见,该案例的分析和优化过程同样采取了自底向上方法论,即首先通过分析硬件、操作系统、数据库系统层面指标,准确分析出了存储系统的确存在I/O效率不高的问题。但真正最影响系统处理能力的还是数据库设计和应用问题,包括字段类型设计问题、分区问题、索引设计策略问题等,而且相比存储系统的更新换代,以及从裸设备迁移到ASM,应用优化改造是投入少、见效快的捷径。甚至在该项目上,只要应用优化到位,也许现有存储设备都足以胜任,而不需要进行存储设备的更新换代和迁移到ASM了。

但是,现在该回到我作为服务售前人员的角色,考虑商务问题了。如果我以应用分析和优化为主去提Oracle服务内容,连该银行处长都说这样对你们Oracle公司绝对不利,因为他的领导觉得应用优化是开发商的份内工作,你们Oracle公司必须提开发商不擅长的工作。于是,我只好在服务方案里面大谈现有存储设备的缺陷,以及存储迁移和改造服务方案,诸如:存储迁移需求分析、ASM存储方案设计、存储迁移方案设计、存储迁移测试和正式实施服务… …。

应用性能分析和优化服务反而成了陪衬,一带而过了,真是本末倒置啊。这就是国内IT行业的生态环境,很多事情要拧把着来。而且我也成了国内IT行业动辄通过采购硬件,靠硬件来缓解系统压力的简单、粗暴建设方法的“助纣为虐”者了。为了给Oracle公司赚几个服务钱,良心谴责啊,呵呵。

 

4.5 适合于数据仓库的Bitmap索引

“冲着第11章,买了!”

《品悟性能优化》一书出版之后,本人一直比较关注广大网民和读者的评价。一天发现一名网友写下了这样的评语:“冲着第11章 数据仓库中的性能优化,买了!”该网友一定为数据仓库性能问题所困,但愿该章内容能为他提供一定的帮助,没有让他失望。

其实在《品悟》一书中,第11章已经是内容最丰富、篇幅最大的一章,以至于编辑想让我拆分成两章。但考虑书的整体布局和内容的平衡性,还是只写成了一章。于是,在内容方面只能有所取舍了。

Oracle数据仓库技术的确博大精深,不仅有《品悟》一书中描述的并行处理、外部表、MERGE语句、物化视图、表空间传输等技术,还有更多当时限于篇幅和整体结构没有叙述的技术,例如Bitmap索引、Bitmap Join索引、Star Join、Star Transformation等,只好寄希望于本书进行一定的弥补了。

位图(Bitmap)索引长什么样?

就象《品悟》一书所言,Oracle的索引技术非常丰富,想做个懂Oracle各种索引的专家其实非常不易。Oracle除最经典的B*树索引之外,另外一个典型索引就是位图(Bitmap)索引。

创建Bitmap索引的语法非常简单,例如:

SQL> CREATE BITMAP INDEX prod_supplier_id ON products (supplier_id);

普通B*树索引是采用一个平衡树来组织和存储被索引字段值,并通过该索引进行数据检索。与之不同的是,Bitmap索引是通过一个位图矩阵来表示被索引字段值与实际数据的关系,并进行数据检索。例如,上述语句假设Supplier_ID字段只有4个值:1,2,3,4,则该Bitmap索引的示意图如下:

 

 

data91

 

即每个Supplier_ID字段值都有一个位图(Bitmap),Products表的每条记录根据Supplier_ID字段的具体值,在相应的位图中进行标记,1表示有,0表示无。例如上述第1条记录的Supplier_ID值为‘1’,则在Supplier_ID值为1的位图中标记为1;第2条记录的Supplier_ID值为‘2’,则在Supplier_ID值为2的位图中标记为1;第3条记录的Supplier_ID值为‘3’,则在Supplier_ID值为3的位图中标记为1;第4条记录的Supplier_ID值为‘4’,则在Supplier_ID值为4的位图中标记为1;第5条记录的Supplier_ID值为‘2’,则在Supplier_ID值为2的位图中标记为1…以此类推。

Oracle在每个位图头中保存了属于该位图记录的起始Start ROWID和End ROWID。基于这些ROWID值,Oracle再通过一个内部算法将该位图表示的记录映射成实际的ROWID值。简言之,大家知道Oracle能有效地将位图信息转换成指向实际记录的指针(ROWID),就OK了。

位图(Bitmap)索引的适应场景

  • Bitmap索引适合于低可选性(Cardinality)的字段

如果某个字段的不同值占整个表记录的1%以下,则称之为低可选性(Cardinality)的字段。例如,上述Product表假设有1万条记录,而Supplier_ID只有4个不同的值,则Supplier_ID就是低可选性(Cardinality)的字段,适合于创建Bitmap索引。

  • 运用Bitmap索引进行查询和统计

在很多情况下,运用Bitmap索引进行查询和统计,效率比B*树索引更高。例如上例中,假设客户查询Supplier_ID为‘3’的Products总数:

SQL> select count(*) from Products where supplier_ID=‘3’;

此时,Oracle根本不需要访问Products表,而只是需要在Supplier_ID位图索引的supplier_ID=‘3’的位图中,将标志位为1的记录汇总一遍即可,显然,查询效率将非常高。示意图如下:

 

data92

  • Bitmap索引适合于复杂逻辑条件

以如下语句为例:

SQL> SELECT * FROM products

2  WHERE  supplier_id = 3

3  AND    prod_pack_size = ‘card box’;

假设查询语句涉及多个字段的各种复杂逻辑,例如上述supplier_id和prod_pack_size两个条件进行与运算,假设两个字段均创建了位图索引,则Oracle可利用位图按位与运算,快速完成相关运算,搜索到相关记录。示意图如下:

 

data93

 

正因为Bitmap索引的这种按位逻辑运算能力,使得越复杂的逻辑条件,Bitmap索引的性能优势更为明显。

位图(Bitmap)索引的优缺点

位图索引的优点非常明显。首先,位图索引是按Bit位表示索引,而且Oracle采用了压缩算法,因此相比普通B*树索引空间消耗更小。其次如上所述,位图(Bitmap)索引非常适合于一些统计运算和复杂逻辑运算的场景,包括各种即席(ad hoc)查询场景。因此,总体上位图索引主要适合于数据仓库或大型统计分析系统。

位图索引的缺点也非常明显。由于Oracle进行各种DML操作时,对位图索引加锁的最小单元不是Bit位,即不是行级锁,而是按位图段(Bitmap Segment)进行加锁,而一个位图段可能达到一个数据块的一半,因此,被锁住的记录可能更多。这样,在修改数据并发量较大的交易系统(OLTP)中,不太适合于设计位图索引。

某年在某国税系统,突然发生核心生产交易系统被挂起的现象,正好本人在现场工作。经分析后,发现是有人在最核心的交易表上创建了位图索引,当并发访问量增加之后,把该表锁住了。当删除这些不必要的位图索引之后,系统恢复了正常。之后本人听到了客户的轻声嘀咕:“是不是Oracle罗工建的这个索引啊?因为只有他可能才知道这种索引。”本人当时闻之报之以一笑:“正因为我知道位图索引的优缺点,才不会在生产系统创建这种索引。除非我想搞破坏。呵呵。”

 

4.6 半小时都没听懂的Bitmap Join索引

半小时没听懂一句

N年前与公司几位同事一同去某客户现场,介绍当年炙手可热的9i新技术。一位同事开始宣讲一个叫Bitmap Join索引的新特性,只见他又是PPT,又是在展板上写写画画,滔滔不绝了几乎半个小时,我居然一句也没听懂!

晚上回到酒店,非常沮丧、知耻后勇的我赶紧找出相关资料仔细研究起来。大约也是半个小时,特别是结合例子反复阅读了3遍之后,我终于搞懂了!待仔细回忆白天那位同事的厥词时,才猛然反应过来,他自己根本没搞懂,难怪他讲了半天,我依然如坠云雾之中。

世上就有这样的能人,自己都不知所云,但那个做派俨然象个大专家。Oracle公司也不乏这样挺能装的人。哈哈。

半小时之内让你搞懂Bitmap Join索引

下面我也希望在半小时之内,让你理解Bitmap Join索引,一定不是装的,呵呵。

欲快速、深入了解某个深奥的技术原理,还是从例子说起。假设有销售明细表(Sales)和客户资料表(Customers),二者形成1对多的主、外键关系。即一个客户可能有多个销售记录,一个销售记录只对应一个客户。

 

data94

 

 

前面我们介绍的Bitmap索引是针对单表的,假设我们如上图右上角所示,通过sales表和customers表的连接操作,在Sales表上面创建基于customer表cust_city字段的Bitmap索引,则该索引叫做Bitmap Join索引。该索引如上图下部所示。假设customer表的cust_city字段有Rognes、Aix-en-Provence、Marseille等值,则每个值都创建了对应的位图(bitmap),而位图中的每个bit位表示Sales表的销售记录所对应客户所在的城市信息。例如,假设Sales表中第1条销售记录所对应客户位于Rognes,则在Rognes位图第1个bit位上标识为1;假设第2条销售记录所对应客户位于Marseille,则在Marseille位图第2个bit位上标识为1;以此类推。

这样,当出现如下语句时:

SELECT SUM(s.amount_sold)

FROM   sales s, customers c

WHERE  s.cust_id =  c.cust_id

AND    c.cust_city = ‘Marseille’;

Oracle只要访问该Bitmap Join索引的’Marseille’位图,就知道Sales表哪些销售记录是卖给位于Marseille的客户了,再访问Sales表,就可完成相应的汇总运算。因为根本没有访问customer表,所以执行效率大幅度提升。

事实上,Bitmap Join索引就是先进行两个表的预连接,在以后频繁进行这两个表连接和运算时,就避免了两个表非常消耗资源的连接操作了。

理解了吗?没理解,就象我当年一样,再看两遍。呵呵。

我们再深入研究一下语句的执行计划,帮助大家理解。以下是使用常规技术的执行计划:

 

data95

 

可见,执行计划是简单的两个表全表扫描和HASH_JOIN连接操作。

以下是采用Bitmap Join技术的执行计划:

data96

 

可见,Oracle现在通过Bitmap Join索引CUST_SALES_BJI访问SALE表,而根本没有访问CUST表,执行效率提升可想而知。例如上述测试例子中,原来语句的执行计划成本为1648,而新执行计划成本仅为229。

何时使用Bitmap Join索引?

任何一种技术的使用都应该充分考虑应用需求和技术本身特点,包括技术的局限性。针对Bitmap Join索引的使用,我们认为应考虑如下特点:

  • 首先,从应用特点而言,应是多个大表的连接操作,例如上述 Sales和 Customers表都可能很大。
  • 其次,应用是基于低可选性字段进行统计运算,例如上述Customers表的cust_city字段就是低可选性字段,并且对该字段进行条件运算。
  • 第三,与普通Bitmap索引相似,对这些表的DML操作的并发度应该较低,否则会导致大量记录被锁住,影响系统正常的DML操作。

什么叫精通Oracle?

写完上述Bitmap Join索引,突然想起10多年前的一件往事。作为休闲之作,权当大家在辛苦研究Bitmap Join索引之后的片刻小憩。

话说10多年前在某网站从事专职DBA时,由于业务高速发展需要,网站CTO决定再扩招一名DBA。于是,我接过一大叠简历进行筛选,其中大部分是刚毕业的大学生求职简历。让我惊讶的是,怎么现在的大学生们都是“精通Oracle、DB2、Informix、Sybase”四大数据库的全才啊?当时我心想,我都干了10多年Oracle开发工作了,才刚学会看SQL语句执行计划,现在大学的数据库课程是不是四大数据库都教啊?或者现在的大学生是不是大把时间在外面公司实习啊?

于是,我抽取了两份最“靓丽”的简历,并联系他们来面试了。待我与他们一交流才知道,原来大学生们其实就只懂Select、Insert、Update、Delete四条最基本的语句,由于四大数据库厂商都有这四条基本命令,因此大家都成了精通四大数据库的专家了,真让我啼笑皆非,呵呵。给刚毕业的大学生们一个忠告:千万别把自己包装成什么都精通的通才,如果有这样的人,他肯定来自于另一个星球。你这样写,有经验的面试官其实知道你只懂Select、Insert、Update、Delete四条语句,因为这几大数据库厂商可能只有这四条基本命令是一样的。

事实上,很多开发人员就凭这四条语句在包打天下。本书的很多内容,就是想告诉开发人员,Oracle不仅有这四条经典的SQL语句,还有exchange、merge、multi-insert、direct-path insert等多种适合于企业级数据处理的语句。千万别在Oracle里面只使用这四条语句,这样就相当于把Oracle用成了DB2,呵呵。

 

 

一次典型故障引发的思考

故障的初步了解

2013年夏天的某天,我和服务销售同事一同去某移动公司准备进行数据库云计算和数据库整合的专题技术交流。待我们早晨见面时,发现销售同事眼睛布满血丝。

“老罗啊,昨晚XX移动一个重要系统出现宕机了,害得我一晚都没睡,忙着到处调度资源来现场解决问题”。他苦言道。

“什么原因?解决了吗?”我急切地问道。

“听说是交换机坏了,把数据库写坏了,还没有解决,但工程师已经到现场了,我们也去现场看看吧。”他仍然是语调沉重。

“这故障可能来的太不是时候了,万一数据库都整合了,这一宕机,可是影响一大片业务啊。我们来交流数据库整合,有点火上浇油的味道啊。” 我们一边往客户现场走,我一边与他调侃一下,意在舒缓一下有点紧张的气氛。

待我们赶到现场,发现我们的工程师正在进行紧张的数据库物理备份恢复工作,也才知道问题的初步原因:因为存储交换机故障,导致数据库出现大面积坏块。由于客户系统没有部署容灾系统,于是通过RMAN进行恢复成了主要的恢复手段。

由于仍然需要按照日程安排与客户进行技术交流,于是我和销售也匆匆离开了现场。尽管这次故障的确对这次交流不利,但客户还是对Oracle最新的云计算和数据库整合技术抱以浓厚兴趣,这些内容将在本书后面章节进行介绍。

故障的进一步了解

日后我们在再次拜访该客户时,才知道原来这次故障远不止上述的硬件故障这个天祸那么简单,其实更多的原因还在于人祸,甚至是错上加错、雪上加霜。在问题描述过程中,系统开发和运维人员一直是欲言又止、非常谨慎,不希望我们知道得更多,更担心领导层知道问题的原委而追究相关人员的责任。本人在本章中描述该案例,本意也是在提高数据库备份恢复性能方面。但为了让读者们了解到更真实的故障,并提高相应的防范能力和积累更多经验,本人还是决意在此对该故障进行更全面的描述:

存储交换机硬件故障导致数据库文件被写坏,是该次故障的一个重要原因。但事实上,运维人员的操作失误才是更重要原因:运维人员错误地将一块已经被操作系统使用的盘直接加入到ASM磁盘组中,使得操作系统和Oracle数据库同时对该盘进行操作,从而导致大面积数据库坏块的出现。

为此,建议大家记住ASM的一条最佳实践经验:在添加盘到ASM磁盘组之前,一定要确认该盘是没有被使用的空盘。例如,在AIX平台通过如下命令确认该盘是否为空盘:

# lquery –h /dev/rhdisk2

如果是空盘,上述命令应该返回该盘所有字节为0。

该故障更为雪上加霜的是:运维人员在进行数据库恢复操作时,又对多个设计为nologging方式的表进行了recover操作,进一步导致了大量逻辑坏块的出现,即系统显示大量ORA-1578错误。本书的数据库坏块处理一章,详细描述了该问题的深层次原因。

又一条关于RMAN恢复的最佳实践经验:在进行recover操作之前,一定要检查一下数据库表中是否有设计为nologging方式的表,例如:

SQL> SELECT DISTINCT OWNER , table_name

FROM DBA_TABLES

WHERE LOGGING=’NO’;

请记住,一定不能对设计为nologging方式的表进行recover操作!否则,将导致大量逻辑坏块。

于是,Oracle工程师和客户开发、运维人员一同对这些天灾人祸造成的坏块进行各种手段的恢复:RMAN、DBMS_REPAIR包、设置10231事件、DUL…。在本书数据库坏块处理一章可见相关技术细节。

为什么RMAN恢复那么慢?

在本次故障恢复中,数据库在进行正常recover操作时,出现了恢复效率非常低下的情况,例如为恢复4天数据居然花费了将近2天时间!这才是本节要详细描述的主要内容,即RMAN中的优化策略。

虽然客户强调存储系统为RAID5,I/O处理能力不强,磁带库只有4个Driver等硬件环境因素,但我们认为该系统RMAN方案本身存在的问题,才是导致recover操作效率极低的重要因素。这也是国内大部分Oracle数据库系统的RMAN实施中普遍存在的问题。

  • 备份恢复方案现状及问题

该系统目前采用的RMAN备份策略是:每个月进行一次0级全备份,而每天进行归档日志的备份。这也是国内大多数Oracle系统普遍采取的备份方案。该方案在此次事故中的弊端显露无遗。如下图所示:

 

QQ截图20160516113202

 

 

即该系统在8月9日进行了一次0级全备份(Full Backup),在9月4日发生存储故障时,RMAN恢复操作应该是首先将8月9日的全备份数据加载(Restore)回数据库,该库已经达到将近20TB,由于存储设备和磁带库硬件能力有限,据介绍大约花费了10多个小时。而更可怕的是,接下来的动作是需要对8月9日至9月4日的所有归档日志和联机日志进行恢复(Recover)操作,而该系统每天的日志就达到数百GB,为恢复4天日志数据,居然运行了将近2天时间!如果按照这个恢复速度计算,假设恢复到9月4日的最新数据,可能需要10余天!

事实上,后来因为该系统备份操作也出现了问题,8月中旬之后的归档日志没有备份成功。因此,整个RMAN恢复操作被迫中断了,该系统的恢复后来是采取应用层为主的方式进行的。

  • 为什么不采取“全量 + 增量”结合的备份策略?

虽然硬件能力有限是导致RMAN恢复操作如此之长的一个重要因素,但更重要的原因在于大量日志文件的Recover操作。尽管Recover操作是Oracle在数据块级进行的物理恢复,但毕竟是逐个DML、DLL的恢复操作,相当于把8月9日至9月4日的全部操作再重复执行一遍。

假设采取如下图所示的“全量+增量”结合的备份策略呢?

 

QQ截图20160516113228

 

即依然假设8月9日进行了一次0级全备份(Full Backup),而在其它日子则每天进行一次1级或2级增量备份,并删除过期归档日志。这样,在9月4日发生故障时,首先需要将8月9日的全备份数据加载(Restore)回数据库;然后,如果是1级增量备份,则需要将8月9日至9月3日每天的增量备份数据也加载回数据库。如果是2级增量备份,则只需要将9月3日的累计增量备份数据加载回数据库;最后,只需要将9月4日的归档日志和联机日志进行恢复(Recover)操作即可。

由于restore操作是将数据库操作结果直接加载回数据库,而日志recover操作是重复执行DML、DDL等操作,该方案的恢复操作效率将显著提高。但是为什么客户不采取这种“全量+增量”结合的备份策略呢?一个重要原因在于Oracle 10g之前提供的增量备份中,尽管增量备份集会小于全库备份集,但备份时间却几乎相等。这是因为即便在增量备份情况下,Oracle仍然需要扫描所有数据文件的所有数据块,逐个判断各个数据块是否发生变化,是否需要进行增量备份。因此,会导致几乎同样的物理读操作和备份时间,也最终导致客户放弃了这种费力不讨好的备份方案。

10g的快速增量备份技术

  • 真正的增量备份技术

Oracle 10g开始终于提供了真正的增量备份技术。即快速增量备份技术(Fast Incremnental Backup,简称FIB),将有效提高传统增量备份效率。10g在日常运行时,通过新的CTWR后台进程记录变化数据块,并存储在一个专门的变化跟踪位图文件(Change tracking file,CTF)中。RMAN备份时通过扫描该位图文件,而不是扫描整个数据文件,就可获取变化数据块,因此能大幅度提高增量备份效率。以下就是FIB技术的原理图:

 

data97

 

  • 启动FIB技术

数据库缺省情况下,没有启动FIB技术。通过如下命令可启动FIB技术:

SQL> alter database enable block change tracking using file ‘ +DG_GROUP1’;

上述命令是假设将CTF文件建立在ASM磁盘组中,事实上,Oracle的CTF文件支持普通文件、集群文件、裸设备和ASM文件。启动之后,Oracle将启动新的后台进程CTWR。

  • CTF文件大小的估算

CTF文件仅记录发生改变的数据块信息,因此该文件非常小。对于一个数据库系统,可近似推算CTF文件为数据块容量的三十万分之一。例如对于一个450GB的系统,可近似估算需要450GB × 1/300000 = 15MB。然而有两个因素影响CTF文件的大小:

  • CTF文件默认起始大小为10MB,当需求超过10MB时,将以10MB为增量增长。因此对于300GB以上的系统,建议CTF文件应为20MB,对于600GB以上的系统,建议CTF文件应为30MB,以此类推。
  • 对于每一个数据文件,需要在CTF文件中320K的存储空间。因此,如果系统有很多的小数据文件,例如200个数据文件,则需要200 × 320K = 64MB

总之,一般有个几百兆的CTF文件,就足够管理容量达几十TB的数据库了。

  • FIB技术的确认

执行如下命令可确认FIB技术是否启动:

SQL> select * from  V$BLOCK_CHANGE_TRACKING

STATUS   FILENAME    BYTES

ENABLED  +DG_GROUP1/cnc/changetracking/ctf.486.684753413 116457472

  • 备份恢复脚本的透明

FIB技术对现有备份恢复脚本完全透明,不需要任何修改。

  • FIB使用的监控

通过如下命令可分析FIB的使用情况:

SQL> select file#,avg(datafile_blocks),avg(blocks_read),

avg(blocks_read/datafile_blocks) AS PCT_READ_FOR_BACKUP,

avg(blocks)

from v$backup_datafile

where used_change_tracking = ‘YES’

and   incremental_level > 0

group by file#;

  • FIB使用效果

下面是在某银行一个10TB系统实施 FIB之后的效果对比:

备份时间 备份方式 数据备份时间 日志备份时间 备份管理工作 总时间
           
4月21日 传统增量 01:38:59 00:00:50 00:00:10 01:39:59
4月22日 FIB增量 00:08:59 00:00:47 00:00:10 00:09:56

可见使用FIB技术之后,增量备份时间由1小时40分钟下降为10分钟左右。

小结

XX移动的这次事故虽然涉及硬件、软件、人为操作失误等多个方面,但在本章主要叙述的提高RMAN备份恢复性能方面,值得总结的技术要点如下:

  • “全量+增量”结合的备份恢复方案是保证RMAN快速恢复的重要技术保障。
  • 为确保增量备份的高效,快速增量备份技术(FIB)是重要的技术手段。

最后再感叹一下,Oracle有那么多好技术,FIB就是一个典型的好技术,可是我们DBA们怎么都不去深入研究并加以合理运用呢?

为什么我们一遇到性能问题,包括备份恢复性能问题,怎么总是想到带库应该扩容到多个Driver,存储应该更新换代到更高档设备这样简单粗暴的办法,而不是全面考虑技术方案本身的缺陷呢?

国内那么多重要的海量数据库系统都采用简单的“全量+每天备份归档日志”策略,如果哪天不幸像该移动客户一样出现一次严重故障,您尝试过RMAN恢复吗?需要多长时间,能满足系统高可用性要求吗?我们平时做过演练吗?在国内很多客户那里,数据库备份的确每天都在做,但却从未进行过恢复操作。备份数据几乎成了束之高阁的供物,呵呵。

人是生于忧患,死于安逸的。

 

4.9本章参考资料及进一步读物

本章的参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database Performance Tuning Guide》 这是Oracle联机文档中,有关性能优化最权威的书籍,也是从事Oracle数据库设计、开发、运维各方面人士的必读物。
2. Oracle大学教材 《Oracle9i: SQL Tuning Workshop》 该教材的第11章介绍了Bitmap、Bitmap-Join等高级索引技术。读者可去《Oracle® Database Data Warehousing Guide》等联机文档查询相关资料。
3. My Oracle Support 《Master Note: Database Performance Overview (Doc ID 402983.1)》 数据库性能问题涉及方方面面。从这篇文章入手,可以进入到性能优化的多个领域:性能优化方法、性能问题的诊断、SQL优化问题、数据库挂起… …
4. My Oracle Support 《Master Note: SQL Query Performance Overview (Doc ID 199083.1)》 以SQL优化为重点的资料汇集:SQL性能差的常见原因、缺乏索引、不必要的排序、缺乏统计信息或不准确的统计信息……
5. My Oracle Support 《Best Practices: Proactively Avoiding Database and Query Performance Issues (Doc ID 1482811.1)》 性能优化的最有效措施是主动预防。该文章介绍了AWR、SQL Plan Management、采集统计信息、升级、打补丁、ADDM、实时SQL监控等多种主动性预防技术的运用。
6. My Oracle Support 《Information Center: Sql Performance Tuning: Troubleshoot (Doc ID 1516522.2)》 对性能影响最大的还是SQL语句。这篇文章是有关SQL性能优化的又一个资料集散地!
7. My Oracle Support Document 1542678.2 Troubleshooting Assistant: SQL Performance Issues》 出了性能问题怎么办?请尝试一下访问这篇文章提供的诊断方法,帮助你定位问题,并参考Oracle提供的各种解决方案。

 

 

 

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟: 再谈海量数据库设计、开发和管理

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

本文永久地址:https://www.askmac.cn/?p=16572

 

 

 

 

请允许我重复在《品悟性能优化》中关于分区技术的一段叙述:“Oracle公司历史上第一位华裔高级副总裁(SVP)曾说:随着分区技术的出现,标志着Oracle公司真正成为了名符其实的企业级数据库软件供应商,Oracle数据库也真的具有海量数据处理能力了。”

正因为Oracle分区技术在满足海量数据处理的高性能、扩展性、数据可管理性、数据生命周期管理、数据备份恢复、高可用性等综合需求中,扮演着太重要的作用,分区技术又是那么地丰富多彩。因此,我们还是结合上一章某银行大集中项目,在本章对分区技术进行专题叙述。包括该系统现有分区方案的评估、大集中系统的分区方案,以及全局分区索引、11g分区新技术等专题技术的介绍。本章最后通过一个最新案例,介绍分区技术方案的实施过程和感悟。

现有系统分区方案分析

以下就是该银行系统现有的分区方案情况,以及我们项目组给出的相关评估分析:

现有系统分区状况

目前,现有系统进行了一定的分区工作,具体情况大致如下:

  • 表分区

表分区情况如下:

 

PARTITI SUBPART   COUNT(*)
------- ------- ----------
HASH    NONE            62
RANGE   NONE            46
RANGE   HASH             6

 

  • 即共有62个表进行了HASH分区,46个表进行了RANGE分区,6个表进行了RANGE-HASH复合分区。
  • HASH分区主要按ACC(帐号)、(PAPER_TYPE,PAPER_NO)等字段进行了HASH分区,分区数为16、32个等。
  • RANGE分区主要按TRAN_DATE等时间字段,按月进行分区。
  • RANGE-HASH复合分区基本按TRAN_DATE等时间字段进行第一维分区,按ACC等字段进行HASH第二维分区。
  • RANGE分区和RANGE-HASH分区部署在BIG_DT1、BIG_DT2等表空间。
  • HASH分区均匀部署在HASH_DT01 … HASH_DT10等表空间。
  • 索引分区
  • 全部为Local分区索引。包括Local Prefixed Index和Local non-Prefixed Index。
  • 分区索引部署在BIG_IDX1、BIG_IDX2,HASH_IDX01 … HASH_IDX10等表空间。

现有分区状况评估

现有系统分区状况,在如下方面值得进一步商榷和改进:

  • TRAN_DATE等时间字段由于采取数字表示,分区方案的可读性和维护性不是非常好。
  • 索引分区只考虑Local分区,而没有考虑Global分区索引,不能全面保障SQL语句对分区表的访问性能。
  • 系统已经采用了ASM条带化技术,HASH分区已经部署在多个均匀分布的磁盘之上。目前多个HASH表空间设计(HASH_DT01 … HASH_DT10,HASH_IDX01 … HASH_IDX10),并不能提高性能,反而增加了运行维护和管理难度。
  • 没有充分考虑通过分区技术,降低RAC节点间访问冲突。

写本书时的进一步评估

上述分析和评估是我们提交给客户的正式文档的部分内容,比较严谨,没有过度评述。以下将进行进一步的评估:

首先,该系统的现有表分区方案设计得非常漂亮。例如,账户、卡表等表通常按账号进行查询,但不需要进行大批量数据删除或变动,因此HASH分区能很好地满足这种需求。而大量交易明细表则主要通过(时间, 卡号/帐号)进行访问,而且存在按时间(天或月)进行大批量数据清理的需求,因此RANGE-HASH复合分区也能很好地满足需求。

其次,现有分区方案的问题主要是体现在两个方面:一是设计者可能不太了解Oracle Global分区索引的含义,因此没有设计这种对性能更有好处的索引。另一个是依然采用传统思维,以为表空间越多,数据能更均匀分布,对性能有更好的保障。这两个问题也是很多系统的物理设计所普遍存在的问题。关于全局分区索引,本章后面将专题讲述,而另一个问题在上一章的“表空间设计在性能方面已经不重要了”已经有所描述。

大集中系统分区方案

以下就是该银行新的全国大集中系统在充分借鉴现有分区方案基础上,与客户、开发商充分交流、权衡利弊之后,确定的新的分区方案。

卡/折等表分区方案

  • 按卡号/帐号进行HASH分区
  • 对应的卡号/帐号字段索引建立成Local prefixed Index
  • 其它字段索引建立成Global Hash-Partitioned Index

交易明细、交易日志等表分区方案

  • 按时间 + 卡号/帐号进行Range – HASH分区
  • 对(时间, 卡号/帐号)建立Local Prefix Index
  • 对其它索引也建立成Local partition Index。这样,索引可能为Local non-Prefix Index。

方案评估

  • 卡/折表

对卡/折表的访问主要通过卡号/帐号进行,而卡号/帐号的Local prefixed Index将有效保证访问性能。

如果基于其它字段的访问,通过Global Hash-Partitioned Index进行访问,也将有效保证访问性能。

虽然卡/折表有不动户数据的清理需求,但不会存在按分区进行大批量数据清理的需求,因此,Global Hash-Partitioned Index不会存在索引不可用的情况。

  • 交易明细、交易日志表

对交易明细、交易日志表的访问主要通过(时间, 卡号/帐号)进行,通过(时间, 卡号/帐号)建立的Local Prefix Index,将有效保证访问性能。

由于交易明细、交易日志表均存在按时间(天或月)进行大批量数据清理的需求,因此可通过按时间分区进行分区的Drop、Truncate等操作,能有效保证性能。而且所有索引为Local索引,将保证索引的高可用性。

  • 问题1:索引访问效率问题及解决方式

如果对交易明细、交易日志表的访问不包括分区时间字段,此时Local non-prefixed partition index将会访问所有时间分区,执行计划为Index Full Scan,这样会导致性能问题。因此,需要与应用开发结合,对交易明细、交易日志表的访问一定要强制使用分区时间条件。

  • 问题2:RAC节点间访问冲突问题及解决方式

该方案没有在分区层面充分考虑降低RAC节点间访问冲突。但根据应用开发人员介绍,在应用开发中将通过分析Oracle HASH算法,来选择连接的Oracle实例,这样可以达到数据访问节点分离的目的。

 

3.3深入探讨全局分区索引

根据个人实施经验,在 Oracle分区技术中,分区索引技术比分区表技术更深奥,也是令设计者更容易让犯错误的地方。例如,很多系统的分区方案没有设计全局分区索引。因此,我们首先回顾一下Oracle公司给出的分区索引设计流程图,然后再深入探讨全局分区索引。

分区索引设计宝典

以下就是Oracle公司给出的分区索引设计流程图,也可称之为分区索引设计宝典:

data31

 

该图在《品悟性能优化》的第八章已经有专题描述,在此就不赘述。需要说明的是:通过上述设计流程图就可知道,针对不同的应用需求,Oracle各种分区索引都有一定的适用场景。而现有很多数据库系统全部设计成本地(Local)分区索引,一个全局(Global)分区索引都没有设计,显然是不正常的。

常言道:存在就是合理的。一定是设计者没有深入了解全局(Global)分区索引原理,才导致它的作用没有得到体现。

深入剖析Global分区索引

  • Global分区索引的含义

首先,我们回顾一下Local分区索引的含义:所谓本地(Local)分区索引,是指索引的分区方法与对应表的分区方法一样。而全局(Global)分区索引,则是指索引的分区方法与对应表的分区方法是不一样的。例如:

假设表是按时间年度分区的,而地区字段的索引是按行政区划进行分区的,该全局范围分区索引创建语句如下:

CREATE index idx_txn_current_3 on TXN_CURRENT(area)
global partition by range(area)
(partition p1  values less than ('0572'),  --- 表示杭州
 partition p2  values less than ('0573'),  --- 表示湖州
 partition p3  values less than ('0574'),  --- 表示嘉州
…
 partition p13 values less than (MAXVALUE));

 

physical_design_3

示意图如下:

 

data81

即全局分区索引与分区数据是多对多关系,也就是说每个年度都有各地区数据,每个地区数据都可能分布在各年度。

Oracle提供了两种全局分区索引,10g之前只有全局范围分区索引(Global Range – Partitioned Index),而10g之后又提供了全局哈希分区索引(Global Hash – Partitioned Index),即按索引字段的HASH值进行分区。例如,如下语句将创建一个4个分区的全局哈希分区索引:

CREATE index idx_txn_current_3 on TXN_CURRENT(area)

global partition by HASH(area) partitions 4;

  • 为什么全局分区索引性能可能高于含义本地分区索引?

因为本地分区索引(Local)与表分区是一样的,分区数量也是相同的,而全局分区索引(Global)不依赖于表分区,所以全局分区索引可能比本地分区索引分得更细。例如,上述例子中,表分区可能只有03年,04年…08年等6个分区,本地分区索引也只有6个分区。而全局分区是按浙江省的地市进行分区,分区数量可能达到10余个。这样,全局分区索引比本地分区索引分得更细,每个索引分区所包含的记录数更少,索引树高度更低,因此访问性能更高。

尤其与本地非前缀索引(Local non-Prefixed Partitioned Index)相比,由于该索引可能需要访问所有分区,而全局分区索引利用分区裁剪功能(Partition Pruning)只访问若干分区索引,其性能优势将更为明显。

  • 全局分区索引的不足

当表分区发生分区删除(Drop)、合并(Merge)、分离(Split)等维护操作之后,本地分区索引将自动进行维护,保持本地分区索引的可用性。而全局分区索引将失效,需要在这些分区维护操作完成之后,进行索引的重建。这就是全局分区索引存在可用性不好的问题。

  • 全局分区索引的适用场景

既然全局分区索引存在上述典型的优缺点,那么扬长避短就是全局分区索引的适用场景了。当该表不存在分区维护操作,如分区删除操作,但需要通过指定字段特别是非分区字段进行高效访问,而且访问频度很高时,这就是全局分区索引的典型应用场景。例如,银行的账户表如果按账号进行HASH分区,银行账户信息是永久保存的,不可能按分区进行大批量数据删除,但需要按金融机构、地区等字段进行高效查询,这些字段就可建成全局分区索引。

案例:测试脚本带入生产系统

N年之前,某银行大型系统要进行压力测试了,为确保测试结果优异,特别是彻底打败Oracle的竞争对手,本人在分区索引设计方面做足了文章。也就是说,本人当年作足了“手脚”,呵呵。具体情况如下:

该项目最重要的交易明细表(TRADEINFO)按(CurMonth、PersonID)进行了Range – HASH分区,但应用需要按账号(Account)字段进行访问,为确保压力测试访问性能,本人决意将账号(Account)字段设计为全局分区索引。但当年的9i只有Global Range-Partitioned Index,也就是按Account字段值进行范围分区。为保证索引分区的均匀以及整体性能最佳,我当年把测试环境中某省数据的Account字段值分布进行了精心研究和计算,写出了如下的脚本:

 

 

create index credit.IDX_TRADEINFO_ACCOUNT on TRADEINFO(ACCOUNT)
global partition by range(ACCOUNT)
(partition p1  values less than ('bhw000000500000') tablespace TS_IND_QUERYRECORD_01,
 partition p2  values less than ('bhw000001000000') tablespace TS_IND_QUERYRECORD_01,
 partition p3  values less than ('bhw000010500000') tablespace TS_IND_QUERYRECORD_01,
 partition p4  values less than ('bhw000011000000') tablespace TS_IND_QUERYRECORD_01,
 partition p5  values less than ('bhw000020500000') tablespace TS_IND_QUERYRECORD_01,
 partition p6  values less than ('bhw000021000000') tablespace TS_IND_QUERYRECORD_01,
 partition p7  values less than ('bhw000030500000') tablespace TS_IND_QUERYRECORD_01,
 partition p8  values less than ('bhw000031000000') tablespace TS_IND_QUERYRECORD_01,
 partition p9  values less than ('bhw000040500000') tablespace TS_IND_QUERYRECORD_01,
 partition p10 values less than (MAXVALUE) tablespace TS_IND_QUERYRECORD_01);

 

 

即按照上述分区,使得每个分区索引数据基本均匀。果然,测试结果非常棒。但这是针对某个省数据进行的设计,如果未来投入生产环境,应该全面研究全国范围的Account字段数据分布情况,重新设计该索引。于是在圆满完成测试任务之后,我提醒客户未来正式投产之前,一定要根据Account字段实际记录值分布情况,重新设计该索引。但也许是客户太满意测试结果,也许是客户对该索引原理理解本来就不够,总之,该索引的测试脚本居然直接带入生产环境,而且运行至今!也就是说,现在查询该省的数据会更快,而查询其它省的数据就会慢一些。呵呵。

当年还感慨,怎么Oracle不设计个Global HASH-Partitioned Index呢?Oracle通过HASH算法自动把索引打散不就好了吗?害得我和客户要对 Account字段值这么去费尽脑汁。Oracle 10g出来之后,本人的第一眼就是去看有这个东西没有,有了!太开心了。可惜,快10年过去了,该系统还运行在9i平台,还没有升级和改造,还在使用这个测试脚本。唉!

系统被挂死了

某移动公司在某年9月1日出现了核心业务系统被挂死(Hang)的严重故障。以下就是详细情况:

  • 问题现象

该移动公司为推广业务,针对每年入学的新生推出了学生卡业务。由于9月1日新生开学集中办理业务,核心系统批量开户数急剧增加,导致业务响应慢,数据库出现被挂死(Hang)的严重故障。当时数据库后台表现为:enqueue等待事件非常高。

  • 问题原因

这是由于大量并发Insert操作,导致与Sequence相关的主键等索引单调增长,出现热块和I/O竞争。 例如,用户表的主键为普通索引、其它为Local non-prefixed Partition索引 ,大量Insert操作导致这些索引出现热点块竞争。示意图如下:

 

data82

 

  • 临时解决方式

使用Sequence生成主键,在大批量数据加载情况下出现热块和竞争,这是非常普遍的一类问题。如何解决?当时客户DBA采取了将该表索引重新创建为反转(Reverse key) 方式,缓解了该问题,确保了系统正常运行。所谓反转索引,就是将被索引字段值从右往左进行颠倒,例如1002变成2001,1010变成0101…,这样原来单调增长的主键就被打散、变成无序的了。但反转索引有很多使用上的限制,例如不支持范围查询(Between, like等)。因此,这只能是一种临时解决方式。事实上,在度过9月1日的业务高峰期后,该移动公司DBA又将该索引恢复成普通索引了。

  • 问题的深层次分析

如果排除9.2.0.8版本存在相关Bug的可能性,该问题其实是在现有9i平台无法根本解决的问题。如下图所示:

data83

 

 

即在现有9i平台(图左部),无论索引是否分区,都会存在索引单调增长而带来的竞争问题。而且即便采用了反转索引,也只能在一个分区内将竞争缓解。

有效的解决方式应该是10g以上的Hash–Partitioned Global Index技术(图右部),这样Oracle将索引分布到不同分区,有效降低I/O竞争,消除热点。如果采取Hash–Partitioned Global Reverse Index,将进一步在分区内降低竞争。因此,该问题应该是升级到10g/11g之后,通过新的分区索引技术才能加以有效解决。

总之,全局分区索引在提高访问性能、降低热点数据冲突方面是大有作为的,唯一的缺陷是分区维护操作之后,该类索引将失效。其实建立在分区表上的普通非分区索引在分区维护操作之后,也同样失效。因此,根据应用场景,合理设计全局分区索引将对海量数据处理大有益处。

 

11g分区新技术

黔驴技穷了

某年去国税行业提供分区方案改造的技术支持。在总结以前若干次分区方案经验教训基础上,客户、开发商和我们自己都对此次改造工作提出了更全面的目标。例如通过分区技术满足日常访问性能、提高历史数据清理能力、提高数据高可用性等。

但我们在运用9i、10g的分区技术对最重要的SB_ZSXX(申报_征收信息)表进行分区方案设计时,却遇到了难以克服的技术难题。首先为实现上述多重目标,我们决定按时间(月)- 税务机关进行组合分区。第一维按时间(月)分区,是为了满足按月或年进行历史数据清理的需要,第二维按税务机关进行二级分区,是为了按税务机关进行访问和大批量数据管理的需要。但9i、10g的组合分区只有两种:Range–Hash和Range–List。

显然Range–Hash满足不了需求,因为第二维将税务机关按Oracle HASH算法进行分区,用户无法知晓某个税务机关数据落在哪个具体分区,无法实现按税务机关进行访问和大批量数据管理的需要。

如果采用Range–List呢?由于税务机关代码采用了国家行政区域分层编码,并一直到税务所一级,而客户只希望分区到地市级,但9i又不支持将基于函数的分区,例如substr函数。怎么办?难道再增加一个地市字段?多烦啊。还要通过应用程序或写Trigger维护这个地市字段。

当时我就想,如果Oracle支持基于函数的分区技术多好,而且如果有Range – Range复合分区技术多好。唉,当时的9i都没有,黔驴技穷了,这次只好放弃复合分区,而只采用了按时间进行的一维分区方案,这也意味着客户部分需求没有充分满足。

10g出来了,我便查看有无这些新技术,遗憾,还是没有。11g出来了,新特性课程有一章专门讲解分区技术,我赶紧扫了一眼,我的妈呀,太震撼了!不仅有我期待的基于函数的分区技术(11g称之为基于虚拟列分区技术),更有让我眼晕的若干新复合分区技术,还有未曾想到的间隔分区、引用分区、系统分区技术等等。

复合分区大大增强

在11g中,组合分区技术大大增强,结合新的间隔(Interval)分区,Oracle现在共有9种组合分区技术,如下图所示:

 

data84

 

即:Range – List, Range – Range, Range – HASH,List – List, List – Range, List – HASH, Interval – List, Interval – Range和Interval – HASH。也就是说,只要HASH不是第一维,其它组合都可以。而且还可以与虚拟列分区相结合。

如此丰富的组合分区技术,应该能满足客户对海量数据处理的绝大部分需求。

引用(Reference)分区技术

首先,我们先看如下例子,一个订单表(ORDER)和订单明细表(ORDER_ITEMS),二者通过订单号字段(ORDER_ID)形成主从关系,即一个订单可能包括多个所订产品。

data85

 

如果采取11g之前的分区技术,ORDER表按订单日期(ORDER_DATE)字段进行范围分区,假设也想让ORDER_ITEMS表进行同样的分区,则需要在ORDER_ITEMS表中增加订单日期(ORDER_DATE)字段。显然该字段是冗余的,是不符合规范化设计的。而且两个表独立设计和管理,还可能带来数据的不一致,甚至产生垃圾数据。例如假设ORDER表按ORDER_DATE进行了历史数据清理,而ORDER_ITEMS没有进行相同的操作,则ORDER_ITEMS相关数据将成为垃圾数据,谁也不会去访问这些数据了。

现在到了11g,通过引用(Reference)分区技术,可以有效解决该问题,示意图如下:

data86

 

脚本如下:

CREATE TABLE orders

( order_id     NUMBER(12) , order_date   DATE,
order_mode   VARCHAR2(8), customer_id  NUMBER(6),
order_status NUMBER(2)  , order_total  NUMBER(8,2),
sales_rep_id NUMBER(6)  , promotion_id NUMBER(6),
CONSTRAINT   orders_pk PRIMARY KEY(order_id)

)

PARTITION BY RANGE(order_date)

(PARTITION Q105 VALUES LESS THAN (TO_DATE(‘1-4-2005′,’DD-MM-YYYY’)),

PARTITION Q205 VALUES LESS THAN (TO_DATE(‘1-7-2005′,’DD-MM-YYYY’)),

PARTITION Q305 VALUES LESS THAN (TO_DATE(‘1-10-2005′,’DD-MM-YYYY’)),

PARTITION Q405 VALUES LESS THAN (TO_DATE(‘1-1-2006′,’DD-MM-YYYY’)));

 

CREATE TABLE order_items

( order_id     NUMBER(12) NOT NULL, line_item_id NUMBER(3) NOT NULL,

product_id   NUMBER(6) NOT NULL,  unit_price   NUMBER(8,2),

quantity     NUMBER(8),

CONSTRAINT   order_items_fk

FOREIGN KEY(order_id) REFERENCES orders(order_id)

) PARTITION BY REFERENCE(order_items_fk);

上述ORDER表的分区采用常规技术,按ORDER_DATE进行范围分区。而ORDER_ITMES表首先没有了ORDER_DATE字段,其次,该表采用了REFERENCE分区,即通过外键(order_items_fk)进行分区,使得ORDER_ITMES子表采取与父表ORDER相同的分区方法。这样,主表和子表在分区管理上也是一体的。主表增加一个分区,子表自动增加一个分区。主表删除一个分区,子表也自动删除一个分区。

因此,通过引用(Reference)分区技术,将不仅简化海量数据管理,而且提高了数据一致性。

感慨:很多系统不愿意设计表间外键关系,设计者自称担心性能,甚至自己都无法道出原因。殊不知,这种粗放的设计方式,失去了多少运用好技术的可能性。唉!

再次品味分区的甜与苦

分区实施可不简单

2013年中,我应某客户要求,对其一个非常重要的生产系统设计和实施分区方案。从我1995年第一次听说Oracle将推出分区技术,到1998年第一次接触分区技术,再到2013年,已经与分区技术打了10多年交道了,深深感受到Oracle分区技术博大精深。分区技术可不是只对几个大表进行分区设计,然后把数据一倒,就简单完事了。

为圆满完成此次分区工作,我特别与客户事前商量了如下详细的3天实施计划:

时间 工作项目 详细内容
     
第一天上午 基准数据采集及调研分析 nmon采集现有系统操作系统数据

statspack数据收集

确定分区方案原则

确定分区表

分区表语句行为分析

第一天下午 分区方案设计 表分表方案设计

索引分区方案设计

分区表空间方案设计

分区实施方案设计

分区方案测试

第一天晚上

第       天上午

分区方案实施 分区方案实施
实施后技术支持及基准指标采集 实施后技术支持

nmon数据采集

statspack数据收集

nmon数据对比分析

Statspack报告对比分析

第二天下午 指标对比分析及方案善后工作 实施后技术支持

单个SQL语句性能对比分析

分区维护方案设计

应用改造建议

文档整理

第三天上午 技术支持、对比分析和工作汇报 实施后技术支持

nmon和statspack采集和对比分析

分区技术和实施工作汇报

其它技术交流工作。如11g升级技术等

如上表显示,在分区方案设计和实施中,不仅应进行基准数据的采集,还应有分区原则的设计、分区表方案设计、分区索引方案设计等,更应有测试和实施后效果对比等。可见,在Oracle技术领域,任何技术的实施都应有全面的方案设计和实施计划。

出师不利

第一天白天,在经过调研分析,通过如下语句查询出存储空间最大的前20张表:

Select * from (Select * from dba_segments where segment_type=’TABLE’ order by bytes desc) where rownum <= 20;

按照Oracle公司空间大于1GB、记录数超过1千万的分区标准,先初步确定前8个表为分区表。

再通过如下语句,研究应用SQL语句对这些大表的访问特征:

Select * from (Select * from v$sqlarea

where upper(sql_text) like ‘%PC_PRO_WELL_VOL_DAILY%’ order by buffer_gets desc) where  rownum <= 20;

经过对这些SQL语句的分析,我们发现该系统日常联机查询和大批量数据处理基本都包含时间条件,因此,本次分区我们将以各表的时间字段进行范围分区。

分区索引方面,则考虑该单位技术人员力量不强,应尽量确保索引的可用性,降低运维人员工作量。因此,初步决定采用可维护性更好的Local索引。包括Locl Prefixed分区索引和Locl non-Prefixed分区索引。

在白天与客户确定分区方案之后,下班后我们开始以如下流程进行分区方案实施:

  1. 干净地停止数据库和Listener
  2. 重起数据库实例,并打开数据库
  3. 建分区表,同时导入数据
  4. 删除原表
  5. 将新分区表更名为原表名
  6. 为字段添加注释
  7. 重建分区索引、限制等
  8. 重新采集统计信息

在我按上述流程正常进行了2个表的分区之后,客户DBA要求自己完成第三个表的实施。

一切似乎都很正常,在晚上9:00多完成第一批3个表的分区之后,应用开始功能验证和性能验证了。结果应用人员很快反应:一个前台录入界面出现空白!如何诊断?前台就一个大白屏幕,什么错误信息都没有,数据库日志也没记录什么信息。我也不会看应用服务器的日志,就这么胡折腾了2个多小时,实在没办法,只好进行回退了。

第二天上午在应用人员支持下,在应用服务器日志中终于找到了有价值的错误信息。通过在互联网搜索,发现与此错误信息相关的问题是统计信息不准确,导致语句执行计划出现问题,从而使得语句性能低下。详细检查前晚实施情况,我们发现客户DBA在实施第3张表分区时,的确忘了最后一步:采集该表的统计信息。因此,导致Oracle优化器产生非最优的执行计划,使得语句性能低下,最终导致应用超时,连接中断,界面出现白屏。

解决起来很简单:重新实施第3张表分区操作,并采集和更新该表统计信息之后,确保Oracle优化器产生最优执行计划,问题得到有效解决。

感慨一下:老革命这次遇到老问题了,又是统计信息问题,呵呵。这次难的是不懂应用服务器知识,不能在应用服务器日志中有效找到出错信息,然后去刨根问底。

继续受挫

在第二天下午重新实施第3张表分区操作之后,若干语句性能出现衰减问题。这些语句片断如下:

Where well_id = :B1

And to_char(PROD_DATE,’yyyy-mm-dd’)=to_char(‘2013-06-18′,’yyyy-mm-dd’)

在分区之前,这些语句基于WELL_ID字段的普通索引进行访问。而在分区之后,该索引设计为Local non-prefixed分区索引。而语句中PROD_DATE字段前的to_char函数导致 Oracle无法使用分区裁减功能,最终导致Oracle需要访问该Local non-prefixed分区索引的所有分区字段,从而使得分区之后性能反而低于分区前的性能。

因此,出现性能衰减不是分区方案本身问题,而是应用语句编写错误导致性能出现问题。

如何解决?由于应用一时无法修改,只能取消WELL字段的分区索引,恢复为原来的普通索引,应用性能基本恢复到原来状态。

谁说分区索引一定能提高性能?很多情况下普通索引效率比Local non-prefixed分区索引效率反而更高!

试想,国内有多少Oracle数据库系统的分区方案设计了大量Local non-prefixed分区索引,其实性能可能还不如不分区的普通索引呢!

案例的感慨

世界上有很多这样美好的谎言:“如果你采用了什么什么新技术,你的系统处理能力一定得到极大提高”。还有更具体的:“分区技术对应用是透明的,你的应用不用做任何改造,使用分区技术,处理能力肯定得到大幅度提升。”

错!一句被反复验证的话是:一个原本就很好的系统,运用新的先进技术将达到如虎添翼的效果。而反之,如果应用软件质量不高,匆忙运用新的先进技术,效果往往是适得其反的。

在原理上,分区技术本质是对应用透明的,Oracle公司这种宣传也是没有问题的。但对应用的深入分析,特别是应用本身合理的优化改造,才能真正达到分区的目的,也才能把分区技术的特点和优势发挥得淋漓尽致。

总之,现有系统的优化,特别是应用软件本身的优化将是未来一切新技术和先进技术运用的重要前提和基础。

 

3.6本章参考资料及进一步读物

本章的参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle® Database VLDB and Partitioning Guide》 Oracle 11g之前有关分区的技术散落在联机文档的多本书中,而11g之后专门推出了这本书,可见分区技术的重要性!这可是从事海量数据库设计和分区设计的必读物!
2. My Oracle Support 《Master Note for Partitioning (Doc ID 1312352.1)》 从事海量数据库设计和分区设计的又一必读物!分区技术资料的索引!
3. My Oracle Support 《GUIDELINES FOR PARTITIONING INDEXES IN 8.XX (Doc ID 1056340.6)》 虽然是当年8i时期写出的资料,但的确是讲解分区索引设计指南的经典文章。
4. My Oracle Support 《How to Implement Partitioning in Oracle Versions 8 and 8i (Doc ID 105317.1)》 同样是一篇写于8i时期的文章,但对分区技术而言同样是经典读物!
5. My Oracle Support 《Partitioned Indexes: Global, Local, Prefixed and Non-Prefixed (Doc ID 69374.1)》 就是因为仔仔细细阅读和研究了该文章将近2个小时,让我终于明白了Oracle分区索引技术中最难懂的Local Non-Prefixed索引!
6. My Oracle Support 《Top Partitioned Index Issues (Doc ID 165309.1)》 又一篇介绍分区索引原理、设计和管理的经典文章!

 

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟: 物理设计中的感悟

作者为: 

SHOUG成员 – ORACLE ACS高级顾问罗敏

本文永久地址:https://www.askmac.cn/?p=16572

 

简而言之,数据库物理设计就是为满足海量数据的高性能、可扩展性、高可用性等处理需求,在数据库逻辑设计基础上,结合具体的数据库管理系统平台和硬件平台,特别是运用Oracle相关特色技术,进行的详细物理级设计工作。

事实上,Oracle物理设计的内涵非常丰富,外延也非常广泛。例如Oracle每个被存储的对象(普通表、索引、大对象LOB字段等)几乎都涉及到相关物理属性的设计;还包括数据库实例初始化参数设计、数据库块选择、数据库字符集选择、控制文件规划、日志文件设计等诸多方面;还有数据文件、表空间,特别是分区方案设计;如果采用ASM技术,还有ASM实例设计、ASM磁盘组设计、ASM 文件设计等;以及操作系统参数设计、存储系统配置设计等更多方面。

真是林林总总,目不暇接。本章将以一个银行案例为背景,介绍物理设计一些主要内容,本书后面章节还将涉及物理设计其它方面的相关内容,例如分区、大对象LOB等。

20多年前的物理设计

前面章节对自己20多年前刚工作时,在领导带领下开展的数据库逻辑设计和数据流程图设计工作,不无得意。实际上,在当年技术环境下,露怯的事情太多了。以下以物理设计为例,讲述当年的趣事。

20多年前我们几乎没有物理设计的概念,就知道如何在逻辑上写出建表语句而已,连表空间都不指定,更别提表的pctfree, pctused等一堆物理属性参数了。大家知道当年Oracle 5.1版在不指定表空间的缺省情况下,把表搁哪儿了吗?SYSTEM表空间!

于是,在我们项目组历经半年的应用软件设计和开发之后,开始往数据库里灌数据时,不一会儿,数据库就报SYSTEM表空间满的错误(ORA-1652)了。此时,作为刚毕业的研究生,我被委以重任,研究如何解决该问题。在当年连Oracle联机文档都没有的情况下,抱着一本不知道是科海还是希望出版的,翻译得象天书一样的资料,苦苦研读,终于找到了如何扩表空间的命令。当年的Oracle 5.1版,居然要先通过一个Oracle提供的ccf工具,在操作系统创建一个文件,然后再通过“ alter tablespace <tablespace_name> add datafile <datafile name>”命令将该文件添加到指定表空间,从而完成表空间扩容工作。

就这样,我照猫画虎般地直接把SYSTEM表空间扩充了!也满足数据加载需求了。待任务完成之后,居然得到了领导的口头嘉奖。今天回忆起来,实在是汗颜。— 这就是我们20多年前的数据库物理设计水平。

 

一个项目的物理设计概貌

首先,我们瞥一下该银行大集中项目的物理设计部分章节内容,给大家一个总体感觉:

  • 物理设计需求分析和设计原则
  • 物理设计需求分析
  • 物理设计基本原则
  • 物理设计主要内容
  • 数据库实例初始化参数设计
  • 表设计基本建议
  • 索引设计基本建议
  • 数据库块选择
  • 数据库字符集选择
  • 控制文件规划
  • 日志文件设计
  • 表空间方案设计
  • 10g/11g若干新特性使用建议
  • 现有系统表空间设计思路分析
  • 表空间设计基本思路
  • 表空间详细设计建议
  • 表空间设计总结
  • 分区方案设计
  • Oracle分区表技术简介
  • Oracle 11g分区新特性简介
  • 分区方案基本原则和方法
  • 现有系统分区方案分析
  • 分区方案与RAC实施
  • 卡户及折户分区方案设计
  • 帐户及分户登记簿分区方案设计
  • 交易明细表分区方案设计
  • 交易日志分区方案设计
  • 其它日志分区方案设计

事实上,每个项目涉及的架构、数据对象的不同,将带来物理设计内涵的差异性。以下还是以该银行项目为背景,更翔实地介绍相关设计细节。

 

从总体上考虑物理设计

企业级数据库设计一定要综合平衡

Oracle公司一直标榜自己是最大的企业级软件供应商,更标榜Oracle数据库是真正适合于海量数据管理的企业级数据库管理产品。以自己从事Oracle数据库20余年的经验,的确感觉Oracle的上述标榜不是自封的,也的确感觉到GB级数据库和TB级数据库在设计理念、设计方法、技术运用等方面的迥然不同。部门级的GB级数据库采用大量缺省物理属性即可满足需求,而TB级则需要在各方面更加综合平衡地考虑问题,特别是在物理设计方面的相关技术运用中应更加精雕细琢。

以下就是我们在该银行项目上确定的物理设计原则:

“为充分满足xxxx系统对海量数据的上述高性能、扩展性、数据可管理性、历史数据转换和迁移、数据备份恢复等综合需求,XXXX系统物理设计应遵循如下原则:

  • 充分考虑xxxx银行对xxxx系统的总体规划和建设目标
  • 以业务需求为驱动,以逻辑模型为基础
  • 充分利用硬件平台特性
  • 充分发挥Oracle相关物理特性的作用
  • 确保xxxx系统处理的高性能、高吞吐量和响应速度
  • 确保数据的安全性及可用性
  • 充分考虑xxxx系统数据的可管理性和可维护性
  • 充分考虑xxxx数据库的可扩展性

一般而言,上述目标有时候是相互矛盾的,最佳设计应该是全面考虑这些目标,综合平衡之后的结果。”

大话一定要落地

上述物理设计原则中的高性能、高吞吐量、安全性、可用性、可管理性、可维护性、可扩展性等,也经常出现在大多数项目的方案设计书中,更被某些方案设计者美其名曰:非功能性需求和目标。

但本人发现,虽然在很多系统的设计方案前言部分,充满了上述这个性、那个性的华丽词汇,但在后面的具体设计和实施部分,往往却看不见这些大话如何具体落地的了,甚至仍然采用的是很业余的设计理念和技术,那些华丽词汇早已被设计者抛到九霄云天之外了。呵呵。

事实上,作为企业级数据库,Oracle提供了大量满足这个性、那个性的丰富技术。我们在物理设计的各个层面和各个角度、在各种技术运用过程中,应时刻牢记我们给客户许诺的各种大话,并时刻考虑如何落地,如何加以实施,这才会真正实现一个高质量的数据库系统。

 

 

表和索引设计基本建议

表物理设计基本建议

以下是该项目上,主要从物理设计角度,对表设计提供的基本建议:

  • 除特殊需求,建议采用普通的堆表(Heap table)。
  • 每个表在创建时候,建议指定所在的表空间,不要采用默认表空间以防止表建立在系统表空间上导致性能和安全问题。
  • 建议应用设计开发人员提供每张表的DML操作频度数值,如果update操作频度高,则可将PCTFREE设置为较高(10%,20%…),反之,则可将PCTFREE设置为较高(1%…)。
  • 当表中存在大量delete操作时,PCTUSED值的增大,将提高空间的利用率,并提高insert和update操作的性能。因此,建议将大量进行delete操作的表的PCTUSED设为60,否则设为缺省值40。
  • 对并发访问量比较高的表和索引,将INITRANS设置较大,特别是针对索引,例如设置INITRANS设为10。
  • 对比较小的代码和参数表,可考虑IOT表技术。
  • 如果某几个静态表关系比较密切,则可以采用聚蔟表的方法。

以下就是卡表创建脚本:

 

CREATE TABLE T_CARD_ACCNT
    (
     card_no CHAR (19)  NOT NULL ,
     card_medium CHAR (1)  NOT NULL ,
     card_type CHAR (1)  NOT NULL ,
     card_class CHAR (2)  NOT NULL ,
     cstm_name VARCHAR2 (40 CHAR)  NOT NULL ,
     app_date NUMBER (6)  NOT NULL ,
     open_date NUMBER (6)  NOT NULL ,
     open_inst CHAR (8)  NOT NULL ,
     due_date NUMBER (6)  NOT NULL ,
     Dac CHAR (16)  NOT NULL ,
     Pwd RAW (8)  NOT NULL ,
     b_flag NUMBER (6)  NOT NULL
    )
        PCTFREE 20
        PCTUSED 40
        INITRANS 2
        MAXTRANS 255
        TABLESPACE TS_TAB_ZH-FHDJB
        LOGGING
        STORAGE (
        INITIAL 104857600
        NEXT 10485760
        PCTINCREASE 0
        MINEXTENTS 1
        MAXEXTENTS 2147483645
        FREELISTS 5
        FREELIST GROUPS 5
        BUFFER_POOL DEFAULT
    )
    ENABLE ROW MOVEMENT
    PARTITION BY HASH ( card_no )
    PARTITIONS 64
    STORE IN (TS_TAB_ZH-FHDJB)
;

 

需要说明的是,上述脚本是Oracle Data Modeler工具生成。实际上,如采取手工编写方式,大量物理属性可以采用缺省值,例如storage短语、ENABLE ROW MOVEMENT等均可省略。

索引设计基本建议

以下不仅从物理设计,而且从应用开发角度提供索引设计的基本建议:

  • 通常而言,交易系统建立为B*树索引,对数据仓库系统,则可考虑Bitmap、Bitmap Join等索引
  • 通过分析应用软件对数据访问方式,展开索引设计
  • 索引与数据分别存储在不同的表空间
  • 不要对索引字段进行运算
  • 不要对索引字段进行格式转换
  • 不要对索引字段使用函数
  • 加强索引使用和索引效率的分析

B*树单字段索引设计建议

  • 分析SQL语句中的约束条件字段
  • 如果约束条件字段不固定,建议创建针对单字段的普通B*树索引
  • 选择可选性最高的字段建立索引
  • 如果是多表连接SQL语句,注意被驱动表(drived table)的连接字段是否需要创建索引
  • 通过多种SQL分析工具,分析执行计划并以量化形式评估效果

复合索引设计建议

  • 分析SQL语句中的约束条件字段
  • 如果约束条件字段比较固定,则优先考虑创建针对多字段的普通B*树复合索引。例如同时涉及到月份、帐号、金融机构代码三个字段的条件,则可以考虑建立一个复合索引
  • 如果单个字段是主键或唯一字段,或者可选性非常高的字段,尽管约束条件字段比较固定,也不一定要建成复合索引,可建成单字段索引,降低复合索引开销。
  • 在复合索引设计中,需首先考虑复合索引第一个设计原则:复合索引的前缀性(prefixing)。即SQL语句中,只有复合索引的第一个字段作为约束条件,该复合索引才会启用。
  • 在复合索引设计中,其次应考虑复合索引的可选性(Selectivity或Cardinality)。即按可选性高低,进行复合索引字段的排序。例如上述索引的的字段排列顺序为:帐号、金融机构代码、月份。
  • 如果条件涉及的字段不固定,组合比较灵活,则分别为月份、帐号、金融机构三个字段建立索引
  • 如果是多表连接SQL语句,注意是否可以在被驱动表(drived table)的连接字段与该表的其它约束条件字段上,创建复合索引。

通过多种SQL分析工具,分析执行计划并以量化形式评估效果。

 

表空间设计的新特性

在该银行项目上,为综合满足海量数据的高性能、易管理性等综合需求,我们在表空间设计方面,综合采用了ASM、OMF、大表空间技术。以下先简要介绍这些技术,然后再给出这些技术综合使用的过程。

ASM

自动存储管理(Automatic Storage Management),简称ASM,是Oracle 从10g开始推出,为满足海量数据库管理的需求,简化存储管理操作的一项新技术。简言之,Oracle通过ASM技术,部分代替了硬件存储厂商对磁盘阵列的管理工作,免去了卷组和裸设备的规划工作。只要将磁盘阵列直接交付给Oracle,甚至不用硬件存储厂商进行磁盘阵列的条块化处理,ASM就能高效率地直接管理所有的数据。ASM提供了几种条块化处理技术,并可灵活地增加和减少磁盘,自动进行数据的按比例负载均衡等。

本书后面还将专题介绍ASM,特别是11g ASM相关新技术。

大文件表空间(BFT)技术简介

Oracle 10g推出了大文件表空间(Big File Tablespace)技术。相比传统概念,一个表空间可以对应多个数据文件,而大表空间只包含一个数据文件,并且该文件可以最大扩展到16TB。以下是传统表空间和大表空间的示意图:

 

physical_design_1

使用大表空间的好处如下:

  • 通过少量数据文件,就可以支持更大数据量的存储和处理。
  • 大表空间技术,可以简化掉数据文件的复杂处理。大大提高表空间的可管理性。即通过大表空间新技术,可以打破数据文件的概念,使得数据文件对用户完全透明。

OMF

OMF即Oracle Managed File的简称。通过OMF技术,例如DB_CREATE_FILE_DEST 等参数的设置,Oracle可通过SQL命令进行数据库相关文件的自动创建和管理,将大大简化数据库管理工作。

OMF并非10g/11g新技术,但通过与ASM、大表空间技术的结合,将极大地简化数据库管理工作。

ASM、OMF、大表空间技术综合使用建议

传统数据系统系统,尤其是在Oracle RAC上部署的数据库系统,采用的是经典的卷组和裸设备技术方案,这种方案将导致大量存储空间的设计工作,例如各个表空间、数据文件的大小、名称,以及相对应的卷组和裸设备的设计工作。在投入运行之后,由于裸设备不能自动扩展,而数据规模将不断增长,会给后期运行维护带来很大的负担。

  • 建议

针对该银行数据量庞大、表空间多的海量系统特点,为简化管理,建议将ASM、OMF、BigFile Tablespace技术综合使用。为使用OMF,建议对数据库实例的如下参数进行设置:

 

DB_CREATE_FILE_DEST=‘+DISKGROUP1’

上述一个参数的简单设置,实际上涉及了OMF和ASM两种技术。

  • 使用过程及效果评估

ASM、OMF、BigFile Tablespace技术的结合使用,可得到如下益处:

首先会使表空间的创建和删除脚本简化,不需要指定具体的data file。例如:

create bigfile tablespace TS_TAB_CREDIT_CARDS_TRANSACTIONS datafile size 1024M;

在删除表空间时,对应的ASM数据文件会自动被删除掉。

drop tablespace TS_TAB_CREDIT_CARDS_TRANSACTIONS_200801 including contents;

可直接对表空间进行自动扩充时,也不需要指定数据文件。例如:

alter tablespace TS_TAB_CREDIT_CARDS_TRANSACTIONS_200801 resize 2048M;

这样,将为海量系统的存储空间设计和管理工作,带来极大的便利。

简言之:根本不用设计卷组、裸设备,更不用关心每个裸设备应该设计多大了。

 

2.6 表空间设计原则和详细设计

表空间设计基本原则

以下就是该银行系统的表空间设计基本思路和原则:

“为满足XXXX系统对数据易管理性、历史数据迁移、提高备份恢复性能和灵活性、高性能、可扩展性等需求,并参考现有表空间设计思路,建议表空间设计遵循如下设计原则:

  • 系统数据与应用数据必须存储于不同的表空间
  • 按应用划分数据,不同应用的数据应存储于不同的表空间。例如不同产品表(卡、折等)应存储于不同表空间,提高数据管理灵活性,减小单个表空间故障的影响范围。
  • 表和索引分离,需存储在不同的表空间,以便分布到不同的数据文件、硬盘上,并分别进行不同的物理存储参数优化。同时方便对表和索引进行不同的管理工作,例如数据备份恢复、数据迁移等。
  • 相对静态的表和频繁变动的表分开存放在不同的表空间,以便分别进行不同的物理参数优化。
  • 为中间表单独设计表空间。这样不仅便于管理,而且在备份中可不考虑此类数据的备份,提高备份效率、降低备份开销。
  • 采用临时表空间组技术,提高大批量数据处理效率。”

表空间详细设计

以下是该系统部分表空间的详细设计。

  • 系统级表空间设计
序号 表空间名 用途 大小(M) 分配方式 Uniform Size(M) 段空间管理 备注
               
1. SYSTEM 系统表空间 1,024 SYSTEM N/A MANUAL  
2. TS_UNDO_01 UNDO表空间1 20,480 SYSTEM N/A MANUAL 实例1
3. TS_UNDO_02 UNDO表空间2 20,480 SYSTEM N/A MANUAL 实例2
4. TS_TEMP_01 临时表空间 20,480 UNIFORM 64 MANUAL 临时表空间组
5. TS_TEMP_02 临时表空间 20,480 UNIFORM 64 MANUAL
6. TS_TEMP_03 临时表空间 20,480 UNIFORM 64 MANUAL
7. TS_TEMP_04 临时表空间 20,480 UNIFORM 64 MANUAL
8. SYSAUX 工具表空间 20,480 UNIFORM 64 AUTO
  • 暂时假设XXXX系统采用2节点11g R2 RAC架构。
  • 系统表空间(SYSTEM)为ORACLE系统运行时所必须的表空间,包括所有数据字典、系统审计信息等。一般设计为1G,足以满足XXXX系统运行需要。
  • 分别为RAC的两个实例设计UNDO表空间。该表空间为数据库进行未提交事务的恢复操作的表空间。作为OLTP/OLAP的混合系统,XXXX系统存在大量大批量数据操作,即存在大量大事务操作,对UNDO表空间的需求会较大。初始各分别设计为20G。
  • 为提高临时表空间的使用效率,设计四个大小分别为20G的临时表空间(TS_TEMP_01, TS_TEMP_02, TS_TEMP_03, TS_TEMP_04),组成临时表空间组。
  • SYSAUX为Oracle 10g/11g的辅助表空间。该表空间将存储所有Oracle后台监控和管理数据。例如AWR、ADDM、Statspack等数据。初试容量设计为20G。
  • 帐户及分户登记簿表空间设计
序号 表空间名 用途 大小(M) 分配方式 Uniform Size(M) 段空间管理 备注
               
1. TS_TAB_ZH-FHDJB 帐户及分户登记簿数据 102,400 UNIFORM 64 AUTO  
2. TS_IND_ZH-FHDJB 帐户及分户登记簿索引 102,400 UNIFORM 64 AUTO  
  • 将帐户及分户登记簿表数据存储在单独的表空间
  • 数据和索引相分离
  • 帐户及分户登记簿表数据和索引初始均分配100G空间
  • 由于采用ASM技术,上述空间均可自动扩展

例如,TS_TAB_ZH-FHDJB表空间的创建脚本如下:

 

create bigfile tablespace TS_TAB_ZH-FHDJB datafile size 102400M

AUTOEXTEND ON NEXT 512M

EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64M

SEGMENT SPACE MANAGEMENT AUTO

ONLINE

PERMANENT;

 

数据库初始化参数设计

数据库初始化参数,特别是与内存管理相关的参数设置,直接影响到系统运行性能。再者,数据库初始化参数的确与硬件配置、数据库架构设计等紧密相关。因此,数据库初始化参数应该是物理设计的重要内容。

Oracle纷繁多彩的初始化参数非常眩人,也的确在故障处理、性能优化方面扮演着重要角色,所以也是很多技术发烧友所热衷钻研的东西。但是,Oracle在参数管理方面却是一种越来越自动化、智能化,简化甚至淡化的发展趋势。因此,下面将首先介绍这种趋势,然后再介绍在该银行项目上的设置原则和实施建议。

10g/11g初始化参数若干新特性介绍

提高IT系统可管理性,甚至实现完全自动化、智能化管理,是Oracle公司正追求的目标。例如,Oracle从9i开始,10g、11g,逐个版本在内存参数设置方面,越来越简化、自动化、智能化了。

如下是自动内存管理的示意图:

 

physical_design_2

 

图中表示当夜间在进行RMAN备份、并行卸载数据等批处理业务中,如果需要更大的Large Pool时,10g和11g可在SGA范围内自动扩大Large Pool。

在11g情况下,不仅可在SGA内部对相关内存进行自我调整,甚至可以在SGA与PGA之间也进行调整。例如夜间若进行大量统计运算、排序等大批量数据处理时,对PGA的需要很大,Oracle则可以在不停机调整PGA_AGGREGATE_TARGET参数情况下,自动扩大PGA区域,在白天交易处理开始后,又可自动降低PGA区域,扩大SGA区域。

初始化参数设计原则建议

  • 采取自动和传统技术相结合策略

即同时设置MEMORY_TARGET、SGA_TARGET、DB_CACHE_SIZE等自动和手工混合的内存管理参数。Oracle原则是:每个内存部件至少分配指定的内存,例如DB_CACHE_SIZE 设置成512M,则Buffer Cache永远不会低于512M,但是可以根据需要,自动调整到超过指定值的内存。

  • 借鉴Oracle最佳实践经验

借鉴Oracle最佳实践经验,例如:

MEMOERY_TARGET = 物理内存*80%

MEMORY_MAX_SIZE = 物理内存*80%

 

对于OLTP系统:

SGA_TARGET = (物理内存*80%)*80%

SGA_MAX_SIZE = (物理内存*80%)*80%

PGA_AGGREGATE_TARGET=(物理内存*80%)*20%

 

对于DSS系统:

SGA_TARGET = (物理内存*80%)*50%

SGA_MAX_SIZE = (物理内存*80%)*50%

PGA_AGGREGATE_TARGET=(物理内存*80%)*50%

上述公式在《品悟》一书中已经出现,并受到一位读者的质疑。借新书写作之际进行一番解释:首先上述公式并非老罗自创,而是来源于Oracle官方文档,即是Oracle官方总结出来的最佳实践经验。其次,从原理本身分析,上述公式不无道理。例如,OLTP系统特点是大并发量的小事务处理,对Buffer Cache、Shared Pool等内存需求更高,所以 SGA应该大一些。而DSS系统则是并发量不高的大批量数据处理,特别是大量统计运算、排序、HASH_JOIN操作较多,对PGA区域要求更高,因此PGA可能占到50%甚至更高的物理内存。

  • 掌握相关评估方法

建议经常访问对自动内存管理内部过程进行监控的若干视图:

V$MEMORY_DYNAMIC_COMPONENTS: 显示自动内存管理的各内存真实大小,包括SGA和PGA等。

V$MEMORY_RESIZE_OPS:显示最新的800个自动和手工进行内存调整操作,不包括正在进行调整的操作。

V$MEMORY_CURRENT_RESIZE_OPS:显示正在进行的内存调整操作,包括自动和手工进行的。

 

V$SGA_DYNAMIC_COMPONENTS:显示自动共享内存管理方式下SGA各内存真实大小。

V$SGA_RESIZE_OPS:显示最新的800个自动和手工进行SGA内存调整操作,不包括正在进行调整的操作。

V$SGA_CURRENT_RESIZE_OPS: 显示正在进行的SGA内存调整操作,包括自动和手工进行的。

V$SGA_DYNAMIC_FREE_MEMORY:显示系统可用的SGA动态调整内存空间

作为DBA,时常查询和分析这些视图的目的之一是监控Oracle自动内存管理的有效性,目的之二是及时发现问题,特别是Oracle在自动内存管理方面可能存在的Bug,并采取安装补丁、升级或关闭某些自动内存管理功能的策略。

 

2.8 物理设计中的感和悟

物理设计的变化趋势

在我从Oracle 5.1到11g的20余年使用经历中,在物理设计方面感觉到Oracle在发生如下的变化:

  • 物理设计技术日益简化了

20多年来,Oracle在物理设计方面不断推出新的技术,给广大客户带来的好处首先是性能和处理能力越来越强,另外一个好处就是越来越多自动化技术的采用,使得物理设计日益简化了。例如,本地化管理表空间(locally managed tablespaces)代替了字典管理表空间(Dictionary-Managed Tablespaces);段空间管理(Segment Space Management)由手工(MANUAL)转为自动(AUTO),这样STORAGE短语就取消了,大家不用再苦心钻研PCTUSED, FREELISTS,  FREELISTS GROUPS等一大堆物理参数了。类似的还有11g新的大对象处理技术SecureFiles取代了传统LOB技术,大家也不用操心CHUNK、LOGGING/NOLOGGING、PCTVERSION、CACHE/NOCACHE/CACHE READS、ENABLE/DISABLE STORAGE IN ROW等传统LOB的大量物理属性了。

在本章开篇描述20多年前进行数据库设计时,我们曾经为根本不知道这些物理属性而汗颜,后来又曾经津津乐道这些诡异的参数。但世界变化就是这么快,当我们刚刚为弄懂这些东西而有点沾沾自喜时,这些东西又被淘汰了。其实仔细想想,世界本来就不应该有这么多的繁文缛节,一个清澈明亮的世界应该更加美好。

  • 物理设计技术在不断推陈出新

虽然物理设计的一大趋势是日益简化,但不断推陈出新的物理设计新技术,也带来了一些新的需要斟酌和研究的细节。例如,11g针对ASM磁盘组推出了物理属性的概念,这样我们在11g中开展ASM磁盘组设计时,就需要研究AU_SIZE、DISK_REPARE_TIME、SECTOR_SIZE、COMPATIBLE.RDBMS、COMPATIBLE.RDBMS.ASM等参数的含义和如何正确设置了,切莫又回到20多年前的水平,对Oracle 的各种物理属性不管不顾,全部采用缺省属性。这绝对不是设计开发企业级TB级数据库的眼界和水平。

表空间设计的感和悟

  • 表空间设计在性能方面已经不重要了

在Oracle传统的设计理念中,表空间设计的一个重要目标是为了提高性能。例如强调将数据和索引分别存在不同的表空间,进一步存储在不同的数据文件,特别是存储在不同的磁盘上,从而降低I/O访问冲突。这是当年使用普通物理磁盘存储数据的设计理念。

现在存储系统广泛使用条带化和磁盘镜像技术,一个数据文件实际上被条带化技术均匀打散在多块物理磁盘之上了,也就是说现在即便所有数据和文件都存储在一个表空间或数据文件上,理论上也不会有明显的性能问题。

总之,表空间设计在性能方面其实已经不那么重要了。

  • 表空间设计目标的综合考虑

既然如此,是否未来就可以简化设计,甚至忽略表空间设计,简单将所有数据、索引存储在一个或少数几个表空间呢?我还真见过一个银行报表系统达到了数十TB容量了,所有数据存储在一个表空间、所有索引存储在另一个表空间,吓死我了。我当时就跟该系统DBA说:“你不害怕吗?如果这个大表空间中出现一个数据坏快,你的系统就完全不可访问了,RMAN恢复也是几乎不可能的。”

表空间设计目标除了性能,其实现在更应关注表空间在数据安全性、系统可用性 、数据可管理性和可操作性方面的作用了。把所有数据存储在一个表空间,就相当于把所有鸡蛋放在一个篮子里一样不安全。因此,合理划分和设计表空间粒度,可以有效隔离和降低数据故障风险。

通过表空间设计如何实现数据可管理性和可操作性呢?首先,针对大批量数据处理,Oracle提供了大量针对性技术。例如在表空间层面快速进行数据迁移的经典技术:表空间传输技术(Transportable Tablespace,简称TTS技术)。其次,这些技术的运用是与应用需求,包括表空间设计紧密相关的。如果设计者不考虑应用需求,简单、甚至杂乱无章地放置数据,TTS技术就无用武之地了。例如客户真有按月、按业务进行历史数据迁移和清理的需求了,而且想通过TTS实现,我们可能真需要按月、按业务进行数据组织和表空间设计了。

某种意义上,表空间设计就相当于一个大楼的结构设计图。如果设计的目的性不强,不仅带来的是数据安全性、可用性的下降,更将导致技术运用的简单化,使得Oracle众多高级技术无法运用。

说到这儿,请大家再回头看一遍前面我们项目组为某银行客户确定的表空间设计原则,体味一下我们在表空间设计方面的良苦用心。

Oracle到底能存多少数据?

10多年前在刚加入Oracle公司时,有幸参加一次中国移动举办的经营分析系统研讨会。该研讨会宗旨是为指导各省运营商的经营分析系统建设,在业务和技术层面制定相关规范和标准。于是,除移动公司内部相关业务和技术人员之外,研讨会还云集了各应用开发商,以及IBM、Oracle、NCR等各路精英。

可想而知,表面上大家似乎都在为一个同一个客户的同一个目标协同工作,实则是暗流涌动、明枪暗箭。不仅是各应用开发商之间互相掐,原厂商之间更是刀光剑影,天昏地暗。应用开发商和原厂商之间也是一会儿同盟关系,一会儿又成了陌路。—- 太佩服现在客户的精明了,让你们这些竞争对手面对面互相掐,然后再坐收渔翁之利。呵呵。

就在这次研讨会的某一天,另一个原厂商的代表突然向我射来一箭:“你们Oracle 9i到底能存多少数据啊?”面对大家齐刷刷的眼光,我摆出一副大义凛然的样子:“Oracle对数据库容量没有限制,有多少存多少!”什么叫无知者无畏,这就是典型写照!呵呵。

若干年后,在另外一个银行项目上,当客户提出如何进行超大型表空间的管理问题时,这次我才静下心来进行了一番深入研究。特别是仔细查阅了Oracle一篇官方文档:《Note:217143.1 Oracle 9i Database Limits》,才知道在9i下Oracle原来有那么多限制:一个数据库最多有64K个文件;一个数据文件最多有4M 个数据块;数据块最大为32K… …。 如此推算,Oracle 9i存储数据量是有上限的:64K*4M*32K = 8PB!可不是我当年的豪言壮语:有多少存多少。

为什么在物理设计一章说这段往事?是因为到了Oracle 10g推出大表空间技术之后,Oracle寻址空间更大了,可以存储到8EB了(1EB=1024PB,1PB=1024TB,1TB=1024GB……)。再则,随着大表空间、ASM、快速增量备份等众多新技术的推出,Oracle在物理设计方面有新的理念和目标了。

到了11g,Oracle有了更大的存储能力了,特别是采用ASM技术之后。例如:在一个ASM存储系统最多有63个磁盘组;一个ASM存储系统最多有1000个ASM磁盘;一个ASM存储系统最多存储40EB;等等。

听说这个世界上已经出现了PB级数据库,但还未听说过EB级数据库。还真无法想像EB级数据库的存储设备需要占多少机房空间,也许存储厂商还未制造出来这种产品,但Oracle在软件方面的确已经具备了这种处理能力,真快实现本人当年的豪言了。

在某些场合讲些气壮山河的话,营造一种气场有时候只是一种市场或商务策略而已,但科学本身还是严谨的。不过另一方面,过于追求技术的及至又显得太过天真、偏执了。世界上都没有这么大的存储需求,你管它的上限呢?凡事都要讲个度。

如果现在客户再问我同样问题,我可能会这样心平气和、更成熟稳健,也更聪明、更太极、更圆滑地回答了:“Oracle数据库每个版本的确都有不同的存储上限,但请大家放心,你现有系统的需求肯定达不到这种上限。”呵呵。

 

2.9本章参考资料及进一步读物

本章的参考资料及进一步读物:

序号 资料类别 资料名称 资料概述
       
1. Oracle 11g R2联机文档 《Oracle Database Concept》 该书若干章节,特别是Part II的第2章至第6章,讲述了数据库表、索引、分区、视图、物化视图、数据库一致性、数据字典等相关技术原理和设计工作的方方面面。这些内容是普通数据库物理设计的重要内容。
2. Oracle 11g R2联机文档 《Oracle Administrator’s Guide》 该书若干章节,特别是Part II Oracle Database Structure and Storage和Part III Schema Objects,也是数据库系统物理设计的重要内容,例如控制文件、联机日志文件、归档日志文件、表空间、UNDO等专题技术的设计等。
3. Oracle 11g R2联机文档 《Oracle Data Warehousing Guide》 该书若干章节,特别是Part III Physical Design等是数据仓库系统物理设计的重要内容,例如表空间、分区、硬件和存储系统、并行处理、索引等技术的设计等。
4. My Oracle Support 《Master Note: Overview of Oracle Tablespace Management (Doc ID 1493350.1)》 这可是Oracle有关表空间设计的大全!不仅有表空间设计和管理的基本知识,更有很多最佳实践经验的文章。
5. My Oracle Support 《Master Note: Overview of Oracle Database Initialization Parameters (Doc ID 1496915.1)》 这是有关数据库初始化参数设置的导读文章,既有基础知识,也有如何查询Oracle隐含参数,以及如何在12c中进行初始化参数设置等技术高手感兴趣的话题。
6. My Oracle Support 《Master Note: Troubleshooting Oracle Database Initialization Parameters (Doc ID 1515259.1)》 数据库初始化参数设置出了问题,怎么办?就看这篇文章吧!
7. My Oracle Support 《Master Note for Automatic Storage Management (ASM) (Doc ID 1187723.1)》 欲深入了解ASM技术吗?这可是ASM技术海洋的入口,该文档包括了ASM林林总总的数百篇文章!

 

沪ICP备14014813号-2

沪公网安备 31010802001379号