PRM-DUL ORACLE 数据恢复软件总贴

PRM-DUL ORACLE 数据恢复软件总贴PRM-DUL 是一个基于JAVA语言编写的DUL类软件,其引入了图形化界面GUI和DataBridge特性。 全程GUI使得用户无需大量时间去学习命令行操作,直接可操作PRM-DUL从受损的ORACLE数据库中抽取数据。 DataBridge特性让抽取到的受损数据库的数据可以直接导入到目标库中,像DBLINK一样简单,而不需要使用sqlldr 或者 exp/imp来操作。PRM-DUL目前有2个版本:
社区版:
在完全免费的社区版中,数据抽取和数据搭桥的行数限制是一万行。ASM文件克隆功能在社区版中全面可用。企业版:
购买企业版意味在一套数据库(一个license对应一套数据库)内完全使用PRM的所有功能,没有任何限制

buying online viagra 购买PRM-DUL,请联系我们:

国内热线号码: 400-690-3643      备用电话:18501767907
ORACLE技术专家服务邮箱: service@parnassusdata.com

PRM-DUL 最新版本 3206下载地址:
http://parnassusdata.com/sites/d … MForOracle_3206.zip

PRM-DUL 中文版用户手册:
http://www.parnassusdata.com/sites/default/files/ParnassusData%20Recovery%20Manager%20For%20Oracle%20Database用户手册%20v0.3.pdf

PRM-DUL For Oracle Database中文介绍:

http://www.parnassusdata.com/sites/default/files/PRM%20–%20PARNASSUSDATA%20RECOVERY%20MANAGER%20For%20Oracle%20Database介绍手册.pdf

PRM-DUL FOr Oracle Database 英文版使用手册:
http://www.askmaclean.com/archiv … ser-guide-v0-3.html

PRM-DUL成功案例:

 

PRM ORACLE数据恢复视频教学:

 

PRM拯救损坏的oracle asm diskgroup数据恢复 http://v.youku.com/v_show/id_XNzgwMzY5OTIw.html
prm DUL for oracle恢复被truncate截断掉的表 http://v.youku.com/v_show/id_XNzU0NTQ1ODE2.html
Oracle DBA神器:PRM灾难恢复工具,Schema级别数据恢复 http://v.youku.com/v_show/id_XNzMwMTc2Njg4.html
如何在Oracle中恢复被truncate截断掉而无备份的数据表   http://v.youku.com/v_show/id_XNzIzMzU4OTgw.html
PRM网络发布会    http://v.youku.com/v_show/id_XNjkzMDc3MDQ4.html

w58w4-prm-dul-for-oracle

Oracle 用户组年轻专家项目

Oracle 用户组汇聚了最活跃的 Oracle 忠实用户。为了更紧密和 Oracle 用户组合作,Oracle 认证团队将支持 Oracle 用户组年轻专家项目。

Oracle 用户组年轻专家项目旨在鼓励用户组成员学习和分享 Oracle 技术,并成为 Oracle 认证的技术专家。为此,Oracle 认证团队将在中国发放数量有限的免费考试券给符合条件的用户组候选人。这些考试券将可以用于 Oracle 认证考试包括 Beta 考试。

了解更多关于 Oracle 认证的信息,请参考 Oracle 认证网站

本次活动面向 ACOUGSHOUG 的用户组成员开放。有意参加者请联系 ACOUG 的仇实 (marshall@acoug.org) 和 SHOUG 的胡章扬 (hzy@shoug.info)。

如何获取免费优惠券

 

用户组成员参与本项目并获取免费考试券必须满足以下条件:

1. 是 ACOUG 或 SHOUG 的活跃会员

2. 符合下列条件之一:

  • 发布博客或撰写关于 Oracle 数据库技术的文章(需要提供文章主题和链接)。
  • 在社交媒体发布的有关 Oracle 公司数据库技术的信息,被甲骨文中国的新浪微博或微信引用或转发(需要提供截图或链接)。
  • 在各种技术活动中发表 Oracle 数据库技术的演讲(需要提供演讲主题和幻灯片的链接)。

请注意:

  • 发放的免费考试券总数是 60 张。免费考试券发放完毕则项目结束。
  • 考试券不可转让,仅限获得批准的年轻专家本人使用。
  • 候选人在博客、微博或微信上发布内容或发表演讲的时间须在以下时间段:2014 年 12 月至 2015 年 5 月 31 日。
  • 鼓励发表数据库选件 (DBO) 相关的内容。
  • 候选人可以用于除了 Oracle Database Administrator Master 考试之外的任何考试。
  • 关于如何向 OTN 投稿,请参见在 Oracle 技术网上发表技术文章

用户组年轻专家列表

 

详细信息,敬请期待。

非常感谢您抽出宝贵时间来参与本项目。如有任何问题,请联系蒋健 (jim.jiang@oracle.com)。

Oracle Acs资深顾问罗敏 老罗技术核心感悟:失去了一次露脸机会

作者为: 

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

 

 

某日与Oracle同事一同在某移动公司进行技术交流,涵盖12c、云技术、数据库整合、容灾、OEM等多个专题领域。临近中午时分,一直喷到了Oracle最适合于人工错误恢复的FLASHBACK技术。正在唾沫四溅之际,突然接到客户DBA电话:“罗工,能不能暂停一下技术交流,我们正好有三张表刚被人意外删除了,能不能过来帮忙用你刚刚介绍的FLASHBACK技术把这三张表抢救回来?”

世界上怎么还有这么巧合的事情?已经由不得我有半分迟疑,特别是任何私心杂念了。诸如:“罗工,这不正好让你展现Oracle技术特点,给你次露脸机会了。”。“罗工,你不挺能吹的吗?看你能不能展示真才实学了”… …。于是,我端起笔记本电脑,直奔现场,一边下楼,一边赶紧看FLASHBACK相关资料。俗话说:临阵磨枪,不快也光。呵呵。

销售同事也看出了情形的紧迫和老罗的“窘”态,想尽一切可能在帮忙:帮我拆笔记本电源线,帮我提着矿泉水,更恨不得搀扶着正阅读文档,步履有点蹒跚的老罗同志一同下楼,哈哈!

待我赶到机器旁边时,资料也已经看完了,心中也有底了。于是,在简单询问了问题现象之后,赶脚让第三方公司DBA输入如下命令:

SELECT original_name, object_name,

type, ts_name, droptime, related, space

FROM user_recyclebin

WHERE can_undrop = ‘YES';

咦,怎么是空?再在sys用户下输入:

Select * from dba_recyclebin;

还是空!怎么回事?难道删除这三张表的客户不是意外操作,而是诚心搞破坏,用了“drop table … purge”命令,或者清空了回收站(Recycle Bin),从而彻底删除了这三张表?与客户进一步确认:这三张表的确是误删除的,没有使用上述命令。

既然如此,为什么回收站没有这三表表的数据呢?稍一思忖,想起来了!Oracle还有个初始化参数(RECYCLEBIN),可控制是否使用FLASHBACK DROP。一检查,果然如此!原来DBA把RECYCLEBIN设置成OFF,从而关闭了FLASHBACK DROP功能。唉!遗憾啊,老罗同志失去了一次露脸的机会,Oracle更失去一次展现技术特点的机会!

本来可以通过“flashback table <table_name> to before drop”一条简单命令,在数秒钟之内就能恢复被误删除表,结果害得客户从生产系统去重新抓取数据,同时恢复被删除的索引、Constraint等数据,整整折腾了一个多小时。客户庆幸的是:幸亏生产系统还有数据,否则叫天不应,喊地不灵。

 

待一切恢复正常了,我还是询问DBA了:“为什么要关闭FLASHBACK DROP功能呢?”回答是:“你们Oracle Flashback太消耗资源了,影响性能,我们不敢打开。”

哦,原来如此。这也是本文的主题:从技术上言,Flashback不是单一技术,而是一个技术家簇。以下就是各种Flashback技术的综合对比:

Flashback技术 主要目的 级别 配置方式 技术原理 恢复期限 适应场景
Flashback Database 快速恢复数据库 数据库级 基于存储在Flashback Recovery Area中的 Flashback log 取决于Flashback Recovery Area容量和db_flashback_retention_target参数
  • 大规模数据误操作
  • 应用测试
  • 与Data Guard综合使用
Flashback Table 整表恢复到指定时间 表级 缺省 基于Undo技术 取决于UNDO表空间大小,UNDO_retention参数
  • 各种DML错误的表级恢复

 

Flashback Query/ DBMS_FLASHBACK包 查询过去时间点的记录 记录级 缺省 基于Undo技术 取决于UNDO表空间大小,UNDO_retention参数
  • 恢复错误记录
  • 对历史记录进行分析、统计
Flashback Drop 快速恢复Drop Table操作 表级 缺省 Recyclebin(该表所在的表空间) 自动管理(FIFO算法)。由表空间的空闲空间确定
  • 错误Drop 表操作
Flashback Versions Query 访问事务历史情况 记录级 缺省 基于Undo技术 取决于UNDO表空间大小,UNDO_retention参数
  • 访问事务历史情况
  • 安全审计
Flashback Transaction Query 查询UNDO语句 记录级 缺省 基于Undo技术 取决于UNDO表空间大小,UNDO_retention参数
  • 查询事务详细情况
  • 查询UNDO_SQL语句
11g Total-Recall(Flashback Data Archive) 历史数据存储和利用 表级 需要配置 基于FDA区域 取决于FDA区域表空间大小
  • 历史数据长久存储
  • 对历史数据的分析、统计
  • 安全审计

各位看见了吗?上述表格中每种Flashback技术原理、目的、是否是缺省配置、适应场景等都是不一样的。没错,某些Flashback技术,特别是Flashback Database是需要进行专门配置的,例如创建Flashback Recovery Area,还会产生大量Flashback log,也的确对性能有一定影响的。但是,很多Flashback技术一方面是缺省配置的,另一方面是基于Undo技术的,并不额外产生资源开销的,对性能的影响也非常有限。例如Flashback Drop技术仅仅在删除表时才会有一定操作,难道我们的系统成天都有Drop Table操作?大家没事天天删表玩儿?不可能吧,呵呵。

唉,这就是国内IT行业的常态之一:不分青红皂白;技术运用简单化;动辄一刀切;缺乏对相关技术的深入研究;什么新特性都不敢用;想当然地自己吓自己……

我们时候才能真正做到严谨、科学、务实、专业、积极、进取,充分评估、大胆运用各种IT新技术、新特性啊?

唉…………………

 

Oracle Acs资深顾问罗敏 老罗技术核心感悟:又一次臭显摆之后的感悟

作者为: 

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

 

 

  1. 现场直播救火过程

2014年8月初的某一天,突然接到东区服务销售经理电话:“老罗,你明天到上海出差,能否先到XX航空公司去一趟,他们一个重要系统宕机了。”据了解,该客户没有采购Oracle现场ACS服务,按Oracle公司先有鸡后有蛋的政策,我们是不能去现场做任何实质性的服务工作的。但从国情出发,更考虑客户感受和客户关系,作为ACS服务售前顾问去现场协助分析和解决问题,并进一步了解客户现状和需求,也是合情合理的,并不是趁火打劫哦,呵呵。于是,我决定调整行程,改签第二天头个航班,中午就飞到了上海。

在虹桥机场上了出租车之后,一个劲儿给师傅说抱歉的话,因为师傅可能等了几个小时,碰上我这个倒霉鬼,去机场附近的客户现场只需要起步价。师傅还是非常敬业,顶着中午火热的太阳,10分钟就把我拉到了该航空公司的信息中心大楼。

待我到达现场时,客户运维部门领导早已是翘首以待,把我热情引到会议室,更是把整个运维部门和开发单位的几十号人都召集到会议室,而且还有负责应用开发的印度专家。于是,在客户简短地介绍了系统概况和故障情况之后,就让我直接连入该系统,并把我电脑连接到大屏幕上,几十双眼睛开始齐刷刷地现场观摩Oracle顾问如何救火了,老罗同志又要开始一次臭显摆了,呵呵。

 

  1. 现场号脉

说实在的,尽管已经身经百战,但IT系统如此复杂,应用更是如此变化多端,IT新技术也是层出不穷,没有一个专家敢牛烘烘地说手到病除的。但是,分析诊断问题的思路和方式还是相通的,那就是先了解系统概况,然后再了解故障情况,特别是收集故障相关数据,再询问故障前是否有应用或环境的重大变更,再逐步分析和定位问题,并给出最终解决问题方式。以下就是与该系统和故障相关的上述几方面具体情况:

  • 平台及架构情况

运行在2节点的SUN Solaris平台;数据库版本为11.2.0.4 RAC;数据库容量达到1.6TB。

  • 故障现象分析

2014-08-01 14:14左右, 实例1重启;2014-08-01 14:28 实例2重启;2014-08-01 15:15:44 节点一被驱逐。故障发生之前,节点1的内存消耗非常高,达到了100%,并产生了大量SWAP操作。节点2的内存消耗也达到了90%。但客户没有安装OSWatcher,也就是没有采集到故障前后的操作系统数据。同时,RAC、GI的alert.log、crsd.log等日志文件也没有记录下明显的错误数据。

  • 故障前变更情况

经客户介绍,该系统在8月1日之前应用软件安装了新补丁,即新部署了一些应用软件。通过对宕机之前的13:00 – 14:00 AWR报告分析,这些新应用软件中的3条SQL语句非常消耗资源。RAC重启之后,新部署的应用软件进行了回退,目前RAC系统运行平稳。

可见,新应用软件问题可能是导致RAC宕机的重要因素!

  • 应用深入分析

由于新应用很可能是导致RAC宕机的重要原因,而且负责该应用模块开发的印度专家也在现场,于是我们首先对其中一条SQL语句共同进行了深入分析。限于篇幅,我们只摘取如下的主要部分:

首先,该语句非常消耗资源,Buffer Gets和Disk Reads都非常之高,运行时间更是长达555秒。通过对该语句执行计划的分析,我们发现该语句对三个大表进行全表扫描。而导致全表扫描的直接原因是语句中如下部分的UPPER函数的使用:

AND ((CUSDOCINF.DOCTYP = :2 AND UPPER(CUSDOCINF.DOCNUM) = UPPER(:3)) OR

(CUSDOCINF.DOCTYP = :4 AND UPPER(CUSDOCINF.DOCNUM) = UPPER(:5)))

事实上,当我们去掉UPPER函数,或者将OR操作修改为in操作之后,Oracle执行计划非常合理,语句效率非常之高。

可是,待我仔细观察,发现开发人员其实已经设计了UPPER函数索引,而且也采集了统计信息,但为什么Oracle不走函数索引呢?正纳闷之际,印度工程师主动告诉我Oracle Bug 14630247会导致Oracle优化器不选择函数索引,而是采用全表扫描。于是,我马上通过Oracle相关网站分析了Bug 14630247及相关的Bug 14828235 ,特别是阅读了《Bug 14828235 ORA-7445 [evaopn3] from query with Function based index and ORDER BY clause》之后,发现该Bug已经在11.2.0.4中修复,并且该Bug若爆发,应该有ORA-7445错误。但是,上述语句并没有导致ORA-7445错误,而且该系统已经是11.2.0.4版本,因此是否由于是Bug 14630247或Bug 14828235导致,我在现场尚无法判断。于是建议针对该问题,请客户再创建一个SR,由 Oracle GCS和研发部门确认这些Bug是否已经在11.2.0.4 for Solaris平台修复,或者是Bug再次爆发。但作为ACS现场服务团队,我建议在应用层面采取一些Workaround措施来规避该问题,例如是否取消upper函数,或者取消or运算。

好了,与应用相关的问题在现场只能暂时分析到此了。但这是否是导致上述故障的唯一因素呢?即是不是因为这些语句消耗了太多资源,而导致宕机呢?由于客户没有安装OSWatcher,也就是无法获取系统宕机时的操作系统数据,特别是内存和进程数据,因此,尚无法做出准确判断。

 

  1. 发现了更严重问题

除了上述不良应用可能导致内存消耗殆尽的问题之外,RAC环境本身是否有问题呢?于是,我接下来通过Oracle的cluvfy工具对RAC环境进行检查,很快就发现更严重问题了!部分细节如下:

grid@ffpdb01:-bash:~$cluvfy comp sys -n all -p crs -verbose

 

Verifying system requirement

 

Check: Total memory

Node Name     Available                 Required                  Status

————  ————————  ————————  ———-

ffpdb02       96GB (1.00663296E8KB)     2GB (2097152.0KB)         passed

ffpdb01       96GB (1.00663296E8KB)     2GB (2097152.0KB)         passed

Result: Total memory check passed

 

… …

Check: Hard limits for “maximum open file descriptors”

Node Name         Type          Available     Required      Status

—————-  ————  ————  ————  —————-

ffpdb02           hard          8192          65536         failed

ffpdb01           hard          8192          65536         failed

Result: Hard limits check failed for “maximum open file descriptors”

 

… …

Check: Kernel parameter for “tcp_smallest_anon_port”

Node Name     Current                   Required                  Status

————  ————————  ————————  ———-

ffpdb02       32768                     9000                      failed (ignorable)

ffpdb01       32768                     9000                      failed (ignorable)

Result: Kernel parameter check failed for “tcp_smallest_anon_port”

 

Check: Kernel parameter for “tcp_largest_anon_port”

Node Name     Current                   Required                  Status

————  ————————  ————————  ———-

ffpdb02       65535                     65500                     failed (ignorable)

ffpdb01       65535                     65500                     failed (ignorable)

Result: Kernel parameter check failed for “tcp_largest_anon_port”

 

Check: Kernel parameter for “udp_smallest_anon_port”

Node Name     Current                   Required                  Status

————  ————————  ————————  ———-

ffpdb02       32768                     9000                      failed (ignorable)

ffpdb01       32768                     9000                      failed (ignorable)

Result: Kernel parameter check failed for “udp_smallest_anon_port”

 

Check: Kernel parameter for “udp_largest_anon_port”

Node Name     Current                   Required                  Status

————  ————————  ————————  ———-

ffpdb02       65535                     65500                     failed (ignorable)

ffpdb01       65535                     65500                     failed (ignorable)

Result: Kernel parameter check failed for “udp_largest_anon_port”

 

… …

 

Verification of system requirement was unsuccessful on all the specified nodes.

grid@ffpdb01:-bash:~$

 

我的妈呀,原来这个系统的操作系统核心参数和网络参数都没有满足Oracle RAC安装需求,这将严重导致Oracle GI和RAC运行不正常!这很可能是导致RAC宕机的更重要原因。当然,准确而言,应该是外部应用压力陡增,与RAC环境的上述内部存在问题共同导致了宕机故障。

 

  1. 客户的纠结和痛苦

连环境参数都没有配置好,就强行把11g RAC给安装上去了,并带病开始工作了。真牛啊,谁做的?客户领导的回答有点支支吾吾,一会儿说是Oracle公司产品售前部门做的,一会儿又说是Oracle公司硬件部门做的。好了,别深究了,别让领导难堪了。我猜想很可能是找一个第三方本地公司做的安装,而该公司技术人员很可能连Oracle安装文档都没有仔细阅读,具体就是《Oracle® Grid Infrastructure Installation Guide11g Release 2 (11.2) for Oracle Solaris》,更具体就是该文档中的“2.10 Verifying UDP and TCP Kernel Parameters”、“2.11 Checking Resource Limits for Solaris”等小节。唉,很可能是第三方公司技术人员在百度、Google中随便找了篇简洁版的RAC安装短文,就在航空公司这么重要的系统上开练了。

这就是非专业服务团队和原厂专业服务团队的差别,原厂技术人员起码会仔细阅读Oracle官方安装文档,更会以Oracle RAC实施方法论为指导,结合Oracle若干最佳实践经验,在RAC软件和补丁安装、高可用性配置、应用部署等方面展开全面深入的实施,确保数据库RAC实施的高质量。

现在怎么办?是否直接修改几个内存unlimited参数和TCP、UDP参数就能解决问题,确保RAC不宕机了吗?作为现场工程师,毕竟不是产品直接研发者,我无法给出这种承诺。于是,建议客户通过SR进一步寻求Oracle后台服务团队和产品研发部门的确认。但是基于个人以往类似经验,最好的办法是把环境参数重新配置好之后,把RAC系统重新安装一遍。

于是,一方面我提出了重新安装的建议,另一方面为降低对生产系统停机的影响,进一步提出了先安装一个Data Guard 环境,将现有生产系统数据切换到Data Guard环境,再重新安装现有生产系统的11g RAC,并切换回11g RAC的建议。但我这些重新安装建议一出口,立马引来客户领导一阵叹息和苦衷:“系统刚上线还不到一个月,重新安装如何给领导解释?”“唉,你们要是早来一个月,上线前就发现环境问题就好了,那时候重新安装没问题。”

还有更纠结、更痛苦的问题:“罗工,你们Oracle公司能提供这种证据吗?证明我们这次RAC宕机,就是因为环境参数配置不合理导致的?”。这如何证明啊?OSWatcher也没有安装,其它日志文件也没有捕获到有价值的信息。更重要的是,根据以往经验,若发现Oracle软件安装都有问题,Oracle后台根本不会继续进行进一步的分析和诊断,一定会建议客户重新安装软件之后再说。是啊,若A本身就错了,基于A的B也跟着出错了。那Oracle停止分析B,要求先纠正A,再看B的运行情况,太符合逻辑了。

 

  1. 更多的感和悟

除了上述对原厂和第三方厂商在RAC安装和实施方面的专业性和非专业性感慨之外,更多的感悟还有:

  • 千万别小看Oracle软件安装,特别是集群和RAC安装,这的确是一项非常专业化的工作。一个环境参数配置不合理,很可能给系统埋下深深的隐患。
  • 遇到问题和故障的时候,还是应该求真务实,尊重客观规律。不应该过多考虑面子,尤其是领导的评价。把一个事情做得扎扎实实、完完美美,虽然可能付出很大的代价,但最终还是很有面子,领导也会满意的,呵呵。
  • 为Oracle服务部门再做个推销,呵呵。Oracle各种专业化的服务部门,无论是后台提供标准服务的PS部门,还是前台提供现场服务的ACS部门,都是专业化的团队,既相互合作,又相互补充,对客户都是有价值的,都是不可或缺的。以该案例为例,后台PS部门可以充分发挥产品实施分析和与研发部门沟通的优势,而前台ACS部门则通过现场与客户沟通,了解更多系统和应用背景,并帮助客户与PS部门沟通,共同推进问题的分析和解决。
  • 更多的感和悟留给大家… …

 

 

2014年10月6日

Oracle Acs资深顾问罗敏 老罗技术核心感悟:Clusterware是成熟产品吗?

作者为: 

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

 

Oracle公司自10g版本开始就推出了集群管理软件CRS,以后又升级改造成Clusterware,到11g版本之后更是大动干戈,内部架构进行了大幅度改造,并与ASM技术整合在一起,称之为GI(Grid Infrastructure)。Clusterware替代了硬件厂商和第三方厂商的集群软件功能,也使得Oracle RAC与Clusterware集成为一体,在产品的整体性、服务支持一体化等方面具有显著优势。

作为新产品、新技术,稳定性、成熟性略差,情有可原。但到了11g仍然如此,则让人难以理解了。

本人最近在Windows 2012平台实施了2节点11.2.0.4 RAC,并通过增加节点方式扩展到了4节点RAC,在国内实属罕见案例。期间一些波折,表明 Clusterware产品仍然不成熟。

话说那天我在实施节点扩展操作之前,先花费了半天时间进行了新节点的环境准备之后,并通过如下命令进行了环境检查:

cluvfy stage -pre nodeadd -n hsedb3 –verbose

 

… …

节点 “hsedb3″ 上的共享存储检查成功

 

硬件和操作系统设置 的后期检查成功。

哟,一切都“成功”,开练了!于是,我按照Oracle文档标准流程在节点1开始运行AddNode.bat脚本了,一切“正常”!我继续在节点3运行了gridconfig.bat等脚本。

待所有脚本顺利运行完之后检查环境时,却发现节点3根本没有加入到集群环境中,节点3上的Clusterware服务也根本没有启动。—– 这就是产品的严重不成熟,明明出问题了,所有脚本却不显示任何一条返回错误,显示一切正常!更可气的是,AddNode.bat脚本的日志文件(addNodeActions2014-09-07_04-52-22PM.log)也居然显示一切正常,最后还来一句:

*** 安装 结束 页***

C:\app\11.2.0\grid 的 添加集群节点 已成功。

我知道Oracle支持在Windows平台进行RAC加节点操作,但现在没有成功,一定是我犯什么错误了,也肯定知道有什么错误信息藏在什么鸟日志文件里了。无奈天色已晚,忙乎一天了,于是先打道回府了。

隔日,待我回到现场仔细分析各类Clusterware日志文件信息时,首先在alerthsedb3.log文件中大海捞针般地发现了出错信息:

[cssd(4484)]CRS-1649:表决文件出现 I/O 错误: \\.\ORCLDISKORADG0; 详细信息见 (:CSSNM00059:) (位于 C:\app\11.2.0\grid\log\hsedb3\cssd\ocssd.log)。

于是,按图索骥继续去查询ocssd.log文件中的信息。又像侦探一样,在ocssd.log文件8千多行的日志信息中发现了如下错误信息:

2014-09-07 17:00:06.192: [   SKGFD][4484]ERROR: -9(Error 27070, OS Error (OSD-04016: 异步 I/O 请求排队时出错。

O/S-Error: (OS 19) 介质受写入保护。)

此时,其实本人已经觉察出问题了:可能是节点3对存储设备只有读权限,连表决盘(Voting Disk)都没有写入功能,从而导致失败了。为保险期间,还是根据上述出错信息在Metalink中进行了一番搜索,果然如此!《Tablespace (Datafile) Creation On ASM Diskgroup Fails With “[ORA-15081: Failed To Submit An I/O Operation To A Disk] : [ O/S-Error: (OS 19) The media Is Write Protected]” On Windows. ( Doc ID 1551766.1 )》详细描述了原委和解决方案。于是,按照该文档的建议,我将节点3对所有共享存储设备的权限从只读状态修改为可读、可写的联机状态。也明白一个细节:新节点对共享存储设备的权限缺省为只读状态。无论如何,安装之前没有仔细检查共享存储设备的权限是我犯的一个错误。

接下来该是重新进行节点增加操作了。且慢!因为前面已经错误地进行了节点增加操作,而且居然显示成功了,那么运行AddNode.bat脚本的节点1肯定已经在OCR、Voting Disk等集群文件中写入节点3不正确的信息了。因此,需要先实施从集群中删除节点3的操作,但是发现Oracle标准文档中的删除节点操作的如下第一条命令有错误!

C:\>Grid_home\perl\bin\perl -I$Grid_home\perl\lib -I$Grid_home\crs\install

Grid_home\crs\install\rootcrs.pl -deconfig -force

 

又是一番折腾,将上述命令修改如下:

cd \app\11.2.0\grid

 

C:\>perl\bin\perl -I perl\lib -I crs\install crs\install\rootcrs.pl -deconfig –force

终于顺利删除了节点3!

现在可以重新来一遍了。这次一马平川地成功增加了节点3的Clusterware以及RAC,还有节点4的Clusterware和RAC。

 

感悟之一:明明节点3对共享存储只有读权限,而cluvfy却说:节点 “hsedb3″ 上的共享存储检查成功!一定是cluvfy只检查了读权限,而没有检查写权限。很可能是cluvfy的Bug!

感悟之二:明明增加节点3的操作失败了。但不仅AddNode.bat没有在命令行及时显示错误,而且对应的日志文件还显示“添加集群节点已成功”。极大地误导客户!罪不可恕!

感悟之三:诊断Clusterware问题太难了!Oracle公司没有告诉客户Clusterware问题的诊断思路,特别是日志文件太多了,不知道先看哪个日志文件,后看哪个日志文件。此次本人完全是凭经验,先看了alerthsedb3.log文件,才找到问题的蛛丝马迹,进而逐步确认问题并加以解决。

… …

总之,Clusterware仍然是一个非常不成熟的产品!

Oracle Acs资深顾问罗敏 老罗技术核心感悟:自动扫描SQL语句工具?

作者为: 

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

 

 

  1. 问题和需求

“你们Oracle公司有这样的自动扫描SQL语句工具吗?通过这个工具,把我们的应用软件输进去,就能扫出SQL语句的大部分问题。这样就可以减少我们测试和性能优化工作量,更能避免投产之后才暴露性能问题。” — 来自某移动客户的需求。

“老罗,XX移动公司希望我们Oracle公司提供自动扫描SQL工具,我们有吗?听说第三方公司有这样的产品,已经在客户那儿试用了。” — 来自Oracle服务销售同事的担忧。

是啊,客户的需求再合理不过。但据我所知,Oracle公司好像没有这样包治百病的神奇工具。第三方公司居然有这样的工具,太吸引客户眼球了,一方面让人感到质疑,另一方面也令人感到一种竞争压力。

 

  1. 初识庐山真面目

于是,我和销售同事趁去该客户现场拜访、调研的机会,对该客户的上述需求和第三方公司的自动化工具一探究竟了。客户的需求不必多言了,我们关键是对所谓自动化工具充满好奇。因商务因素,客户并没有给我们直接展示该工具的使用过程和界面,但告诉我们大致原理:原来该工具首先通过定义一组评分规则,例如:SQL语句是否使用绑定变量;条件字段前是否有函数;多表连接是否超过4个表… …,然后将输入的SQL语句进行评判,若违反这些规则,扣分!最后给该SQL语句和整个应用模块打分。

原来如此!这些规则在大部分情况下不无道理,例如,条件字段加函数,特别是在日期字段前加to_char函数:

to_char(DJ_SZ.JDRQ, ‘YYYY.MM.DD’) BETWEEN ‘2014.04.01’ AND ‘2014.04.17’

就是一种非常初级、业余、错误的编程方式。正确方式应该是:

DJ_SZ.JDRQ BETWEEN to_date(‘2014.04.01’,’YYYY.MM.DD’) AND to_date(‘2014.04.17’,’YYYY.MM.DD’)

但是,更多的规则值得商榷。例如,在Oracle公司推荐的编程规范中,并不是所有SQL语句都应该使用绑定变量的,而只是针对并发量大的小事务SQL语句才应该使用绑定变量,而针对并发量小的大事务SQL语句,特别是非常复杂SQL语句,Oracle公司建议是不要使用绑定变量。第三方的自动工具能分析出SQL语句是高并发量还是低并发量访问,以及大事务和小事务吗?值得怀疑。

更为典型的例子是,其实Oracle公司从来没有官方正式建议:一个SQL语句不能超过4个表的连接。的确,多表连接可能导致性能不佳,但问题不在于连接表的多和少,而在于编程人员是否理解了Oracle的Nested Loop、Hash Join等多种表连接技术原理和适应场景,以及在表连接中索引的设计原理。以下就是一个国内著名财务软件的典型SQL语句:

select *

from (select rownum num, temp.*

from (select a.fid,

… …

a.playdeptname as playdeptNameCode

from t_claim_remittancerecord a

left join t_pay_remittype b on a.remittype = b.fid

left join t_pay_fundtype c on c.fid = a.amountscategory

left join t_org_department d on a.remitdepart =

d.finasyscode

left join t_org_department y on a.playdeptname =

y.finasyscode

and y.status = 1

left join t_org_employee f on f.empcode = a.addperson

left join t_org_department k on f.deptid = k.id

left join t_org_employee g on g.empcode = a.updateperson

left join t_org_employee h on h.empcode = a.claimman

left join t_bd_customer cus on cus.fnumber = a.customer

left join V_LMS_SUPPLIER s on s.snumber = a.supplier

left join t_deposit_printer i on i.codenum = a.codenum

left join t_org_employee j on i.createuser = j.empcode

WHERE 1 = 1

and a.accountName like ‘%’ || :1 || ‘%’

and a.claimState like ‘%’ || :2 || ‘%’

and a.writeOffState like ‘%’ || :3 || ‘%’

and a.reachAmountDate between :4 and :5

and a.repealstate != 1

order by addTime desc, codeNum) temp) t

WHERE t.num <= :6

and t.num > :7

 

哇!该语句好复杂哦,连接的表多达10多个。若采用第三方公司的SQL自动扫描工具。该语句一定被扣分甚至彻底枪毙了。可是,该语句实际运行情况如何呢?以下就是该语句的执行计划:

———————————————————————————————| Id  | Operation                                     | Name                      | Cost (%CPU)|

———————————————————————————————|   0 | SELECT STATEMENT                              |                           |    14 (100)|

|   1 |  FILTER                                       |                           |            |

|   2 |   VIEW                                        |                           |    14   (8)|

|   3 |    COUNT                                      |                           |            |

|   4 |     VIEW                                      |                           |    14   (8)|

|   5 |      SORT ORDER BY                            |                           |    14   (8)|

|   6 |       FILTER                                  |                           |            |

|   7 |        NESTED LOOPS OUTER                     |                           |    13   (0)|

|   8 |         NESTED LOOPS OUTER                    |                           |    12   (0)|

|   9 |          NESTED LOOPS OUTER                   |                           |    11   (0)|

|  10 |           NESTED LOOPS OUTER                  |                           |    10   (0)|

|  11 |            NESTED LOOPS OUTER                 |                           |     9   (0)|

|  12 |             NESTED LOOPS OUTER                |                           |     8   (0)|

|  13 |              NESTED LOOPS OUTER               |                           |     7   (0)|

|  14 |               NESTED LOOPS OUTER              |                           |     6   (0)|

|  15 |                NESTED LOOPS OUTER             |                           |     5   (0)|

|  16 |                 NESTED LOOPS OUTER            |                           |     4   (0)|

|  17 |                  NESTED LOOPS OUTER           |                           |     3   (0)|

|  18 |                   NESTED LOOPS OUTER          |                           |     2   (0)|

|  19 |                    TABLE ACCESS BY INDEX ROWID| T_CLAIM_REMITTANCERECORD  |     1   (0)|

|  20 |                     INDEX RANGE SCAN          | IDX_TCR                   |     1   (0)|

|  21 |                    TABLE ACCESS BY INDEX ROWID| T_PAY_REMITTYPE           |     1   (0)|

|  22 |                     INDEX UNIQUE SCAN         | PK_REMITTYPE_FID          |     1   (0)|

|  23 |                   TABLE ACCESS BY INDEX ROWID | T_PAY_FUNDTYPE            |     1   (0)|

|  24 |                    INDEX UNIQUE SCAN          | PK_FUNDTYPE_FID           |     1   (0)|

|  25 |                  TABLE ACCESS BY INDEX ROWID  | T_DEPOSIT_PRINTER         |     1   (0)|

|  26 |                   INDEX UNIQUE SCAN           | PK_T_DEPOSIT_PRINTER      |     1   (0)|

|  27 |                 TABLE ACCESS BY INDEX ROWID   | T_BD_SUPPLIER             |     1   (0)|

|  28 |                  INDEX RANGE SCAN             | IDX_BD_SUPPLIER_NUM       |     1   (0)|

|  29 |                TABLE ACCESS BY INDEX ROWID    | T_ORG_DEPARTMENT          |     1   (0)|

|  30 |                 INDEX RANGE SCAN              | IDX_T_ORG_DPT_FINASYSCODE |     1   (0)|

|  31 |               TABLE ACCESS BY INDEX ROWID     | T_ORG_DEPARTMENT          |     1   (0)|

|  32 |                INDEX RANGE SCAN               | IDX_T_ORG_DPT_FINASYSCODE |     1   (0)|

|  33 |              TABLE ACCESS BY INDEX ROWID      | T_BD_CUSTOMER             |     1   (0)|

|  34 |               INDEX RANGE SCAN                | IDX_BD_CUSTOMER_NUM       |     1   (0)|

|  35 |             TABLE ACCESS BY INDEX ROWID       | T_ORG_EMPLOYEE            |     1   (0)|

|  36 |              INDEX UNIQUE SCAN                | UK_EMPLOYEE_EMPCODE       |     1   (0)|

|  37 |            TABLE ACCESS BY INDEX ROWID        | T_ORG_DEPARTMENT          |     1   (0)|

|  38 |             INDEX UNIQUE SCAN                 | SYS_C00797036             |     1   (0)|

|  39 |           TABLE ACCESS BY INDEX ROWID         | T_ORG_EMPLOYEE            |     1   (0)|

|  40 |            INDEX UNIQUE SCAN                  | UK_EMPLOYEE_EMPCODE       |     1   (0)|

|  41 |          TABLE ACCESS BY INDEX ROWID          | T_ORG_EMPLOYEE            |     1   (0)|

|  42 |           INDEX UNIQUE SCAN                   | UK_EMPLOYEE_EMPCODE       |     1   (0)|

|  43 |         TABLE ACCESS BY INDEX ROWID           | T_ORG_EMPLOYEE            |     1   (0)|

|  44 |          INDEX UNIQUE SCAN                    | UK_EMPLOYEE_EMPCODE       |     1   (0)|

 

 

大家看到上述执行计划,首先不应感到畏惧,而应该从外观上感慨一下,那就是数据库的美感!大家看这个执行计划的形状多么对称和富有韵律感,也多像一把打开的美丽扇子。其次,大家一定要相信,外观充满美感的东西,本质上也应该不错,呵呵。的确,回到技术本质,我们发现虽然该语句涉及10多张表的连接,但实际运行效率效果非常高,例如Cost才14,当然Cost有不准确的时候。更重要的是,该语句每次表连接都非常漂亮地采用了Nested Loop连接技术,并且都合理地采用了被连接字段的索引。正是因为设计开发人员非常了解Oracle表连接原理以及索引设计规范,所以才设计出了这样“又好吃、又好看”的SQL语句。

可是,第三方公司的SQL自动扫描工具却很可能滥杀无辜了。大家一定能相信一个原理:世界上一件事物的好坏不在于多和少,而在于其本身的对和错。若将此原理运用在多表连接技术方面,那就是:多表连接的好坏不在于连接表的多和少,而在于每次表连接的对和错。因为Oracle表连接每次都是两个表进行连接,然后再进行第三个、第四个表的连接。若充分理解了Oracle各种表连接技术、索引设计规范等,每次表连接都是高效的,再多的表连接也是合理的。反过来,若不了解Oracle表连接技术和适应场景,即便是两个表的连接都会出问题。

 

  1. 少一点噱头,多一点务实

此标题有点刺耳,甚至刻薄,但的确是本人有感而发。国内IT市场也的确存在这种不太正常现象:面对客户某些看似合理,实则很难实现的需求,某些公司不是去合理引导客户,反而是一味迎合客户,甚至是推波助澜,更实质的目的还是出于商业考虑。但是,大家不知这是一种非常短视的行为吗?难道客户不会很快就验证出这种所谓SQL自动扫描工具的有效性,甚至真伪性吗?既然如此,大家何必去费尽心机,去讨客户这种“好”?实际上很可能是既让客户失望,也毁自己声誉的事情。

性能分析和优化,特别是SQL语句性能分析和优化,怎么可能只做静态的形式分析?而不做与实际系统和数据相关联的动态神式分析?记得有一年参加一个数据库技术大会,一位国外性能优化大师的演讲曾经让我非常震撼,他的演讲主题是性能优化与应用数据的关联性,整个演讲中,他未展现一个SQL语句优化技术,而是大谈数据分布对SQL语句访问性能的重要性,诸如按字段分析最大值、最小值、分组统计等,以及何时需要按Bucket方式收集统计信息等。所谓的SQL语句自动扫描工具,可能连客户实际系统都不连接,执行计划也不分析,客户数据更不了解,就能扫描出SQL语句质量?的确有点像个乌托邦的东西。

再回到本文开头一个问题:“你们Oracle公司有这样的自动扫描SQL语句工具吗?”准确地回答是:Oracle的确没有这种不看数据、不看执行计划的所谓自动扫描SQL语句工具,但Oracle公司自10g开始就提供了大量内置的SQL优化工具,例如:ADDM、SQL Access Advisor、SQL Tuning Advisor、Automatic SQL Tuning、SQL Profile、SPA(SQL Performance Analyzer)、SPM(SQL Plan Management)… …这些工具一个共同特点是不仅分析SQL语句执行计划,而且分析统计信息,分析数据分布情况,分析索引设计情况等,综合各方面情况,给出一些更合理的SQL语句优化建议。例如,11g的Automatic SQL Tuning就是分析SQL语句所访问表的统计信息是否过期、是否缺乏索引、是否可产生有效的SQL Profile信息、语句编写是否合理等。

再者,虽然Oracle自动优化工具能有效分析和解决很多SQL性能问题,但更多基础性,特别是与应用数据紧密相关的问题,还是需要应用设计开发人员从数据库模型规范化设计、 基础技术掌握、SQL设计开发规范、应用软件质量控制、加强设计开发管理等层面和角度去加以解决。

总之,性能优化工作,特别是应用性能分析和优化工作,还是需要大家踏踏实实、一点一滴地做起,即便需要所谓自动化的工具,也建议大家优先考虑Oracle公司本身自带的工具,毕竟这些工具是Oracle产品的一部分,经过了严格测试,也为全球广大客户的大量实践所验证,是具有普遍适用性的东西。

还是以本节标题作为本文结尾:

少一点噱头,多一点务实!

Oracle Acs资深顾问罗敏 老罗技术核心感悟:牛! 11g的自动调优和SQL Profile

作者为: 

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

 

 

 

  1. 多年前的一段往事

记得多年以前在一个10g平台的数据仓库项目上遇到一个非常难优化的SQL语句,当时即便我采集了统计信息、甚至在语句中增加了HINT,Oracle产生的执行计划都不如人意。最后,不得不通过SR寻求老外高手的指点,他建议我采用10g刚出炉的一个新技术,即让我为该语句生成SQL Profile信息,然后再执行该语句。一切OK了,太神了!

也记得当时我问老外,以后是不是遇到非常复杂的、优化难度很大的SQL语句,就扔给Oracle,特别是产生一遍SQL Profile来辅助优化器时?鬼子不无得意地回答:“That’s right!”

 

  1. 再次感叹SQL Profile的牛!

若干年之后的2014年,在面对一条将近200行的SQL语句进行优化时,发现该语句执行计划已经基本找不出明显问题,例如既没有全表扫描,也没有全索引扫描,甚至语句的Cost也非常低(当然Cost并不十分准确)。但是语句执行效率并不高,达到30秒,资源消耗也非常高,例如Buffer Gets达到1,246,155次。客户当然不满意,如何进一步优化?

山穷水尽之际,想起了上述多年前的往事,更想起了神奇的SQL Profile技术。于是,在搜索到最新的11g文档《Automatic SQL Tuning and SQL Profiles (Doc ID 271196.1)》之后,照猫画虎般地开练了。效果如何?以下就是优化前后的对比:

这是优化之前的各项指标:

Stat Name Statement Total Per Execution % Snap Total
Elapsed Time (ms) 30,273 30,272.96 17.76
CPU Time (ms) 29,968 29,968.19 17.79
Executions 1
Buffer Gets 1,246,155 1,246,155.00 14.68
Disk Reads 5,437 5,437.00 0.80

这是优化之后的各项指标:

Stat Name Statement Total Per Execution % Snap Total
Elapsed Time (ms) 4,653 4,652.71 3.00
CPU Time (ms) 4,470 4,470.23 2.90
Executions 1
Buffer Gets 303,480 303,480.00 2.32
Disk Reads 9,740 9,740.00 1.39

可见,语句响应速度从30秒下降到4秒多,Buffer Gets从1,246,155下降到303,480!我对语句没做任何改动,也没创建新的索引,执行计划就更好了,实际效果更是如此的好!SQL Profile牛啊!

 

  1. 实施细节

下面就是11g自动优化工具和SQL Profile技术综合运用的详细过程:

  • 生成自动优化任务

declare

my_task_name VARCHAR2(30);

my_sqltext CLOB;

begin

my_sqltext := ‘<欲调优的SQL语句文本>';

my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(

sql_text => my_sqltext,

user_name => ‘<用户名>’,

scope => ‘COMPREHENSIVE’,

time_limit => 60,

task_name => ‘test1′,

description => ‘Task to tune a query on a specified table’);

end;

/

  • 执行自动优化任务

begin

DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => ‘test1′);

end;

/

  • 查询Oracle产生的自动优化报告

set long 10000

set longchunksize 1000

set linesize 100

set heading off

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( ‘test1′) from DUAL;

set heading on

  • 接受Oracle自动优化任务产生的SQL Profile

DECLARE

my_sqlprofile_name VARCHAR2(30);

begin

my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (

task_name => ‘test1′,

name => ‘test1′);

end;

/

OK了,可以运行需要调优的语句,并观察优化效果了。效果就是上面显示的那组令人激动不已的数据,而且在Oracle产生的新执行计划中,明白无误地显示采用SQL Profile了:

“SQL profile “test1″ used for this statement ”

 

各位读者现在只需将你需要优化的语句和所属用户名填入上述脚本之中,也可以照葫芦画瓢开练了。

 

  1. SQL Profile到底是什么东西?

SQL Profile信息存储在Oracle数据字典之中,除了dba_sql_profiles视图显示的有限信息之外,的确有种看不见、摸不着的讳莫如深的感觉。SQL Profile到底是什么东西?其实SQL Profiling可以与表和统计信息的关系相类比,SQL Profile就是一条SQL语句的统计信息。例如:当我们遇到一个复杂且资源消耗非常大SQL语句时,Oracle可通过一些取样的数据,或者可以执行该语句一个片段,以及分析该语句的历史执行情况,来评估整体执行计划是否最优化。而这些辅助信息,就是SQL Profile信息,并保存在数据字典之中。

SQL Profiling工作原理如下图:

sql profile

即上图上半部分显示11g自动优化工具SQL Tuning Advisor在针对某条SQL语句产生SQL Profile信息之后,在上图的下半部分,当Oracle正式需要执行该SQL语句时,优化器不仅利用该语句所访问对象的统计信息,而且利用SQL Profile信息,来产生整体上更优的执行计划。

 

  1. 什么时候该使用自动调优工具和SQL Profile?

Oracle 11g的自动调优工具和SQL Profile的确像潘多拉盒子一样充满魔力。继续上述优化案例,尽管该语句被Oracle优化了,但我仔细对照了优化前后50多步的执行计划,怎么也没找出到底是哪些步骤被Oracle优化得效果如此之好,真是太神奇了!

是否一遇到复杂语句就依靠自动调优工具和SQL Profile进行优化呢?且慢,首先,尽管应用性能问题很多,但最主要的问题还是一些传统的、基础性问题。例如:缺乏合适的索引;复合索引设计不合理,特别是索引顺序不对,导致索引效率不高;SQL语句中错误地使用函数,导致索引无法使用;等等。针对这些问题,合理运用20%的基础技术,特别是索引技术,其实能解决80%的问题。这些技术也是DBA和应用开发人员的基本功和基本设计开发规范,过度依赖自动化工具反而会让我们自己的基本技能退化的。其次,自动调优工具和SQL Profile也非包治百病的灵丹妙药,也有看走眼的时候。Oracle自动工具怎么可能比你更了解你的数据模型和数据分布情况,进而给出更准确的优化策略呢?第三,Oracle自动工具使用起来也并不简单,而且需要DBA与开发人员紧密配合,针对大部分基础性问题,有经验的DBA和开发人员其实一眼就能看出问题,何必杀鸡用牛刀呢?

那何时使用自动调优工具和SQL Profile进行优化呢?本人的经验:当针对一些复杂SQL语句,运用传统的、人工分析方法难以奏效时,建议尝试使用这些新技术。

 

无论如何,Oracle 11g的自动调优工具和SQL Profile还是牛!不得不服!

Oracle Acs资深顾问罗敏 老罗技术核心感悟:分表还是分区?

作者为: 

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

 

 

  1. 分表 + 分区”

多年来,某移动行业开发商在针对海量数据库进行设计时,一直在采用“分表 + 分区”策略。在正在进行的新一代移动业务支撑系统设计开发中,也仍然沿用这种策略。以下就是相关细节及本人的评估:

  • 按用户id头两位建表分区
  • cs_scoreuse_rd积分消费记录表
  • cs_userdetail_info用户详细信息表
  • cs_userdetaildead_info用户详细信息拨备表
  • CS_UserAdd_info_$X 用户附加信息表
  • CS_UserAdddead_info用户附加信息拨备表
  • CS_UserState_info_$X用户状态变更轨迹表

详细含义是:由于用户id字段的前两位代表地市,实际上这类表是按地市进行范围分区。这样分区的目的是什么呢?通过与设计人员沟通,其实就是为了将这些大表划分成更小的物理表。但是,每个地市的数据量是不均匀的,因此每个分区的数据也是不均匀的,每个分区访问性能良莠不齐,并不能保证数据访问整体性能的最佳。

  • 按用户id最后一位分十张分表
  • CS_UserAdd_info_$X用户附加信息表
  • CS_UserState_info_$X用户状态变更轨迹表

实际上这两张表分别代表10张表,例如CS_UserAdd_info_$X表是代表CS_UserAdd_info_0、CS_UserAdd_info_1… …CS_UserAdd_info_9。然后再按用户id头两位对这10张表进行上述范围分区。这就是典型的“分表 + 分区”策略。为什么要这么设计呢?设计人员的回答是如果不分表,由于CS_UserAdd_info记录非常多,直接按用户id头两位按地市分区,分区表记录仍然很多。大家看出问题了吗?下面我再详细分析,先留个伏笔。

  • 所有历史表均为年月分表

在该系统设计中,上述表均有历史表,设计人员将这类历史表均按年月分表。例如:用户详细信息表(cs_userdetail_info)的历史表包括:cs_userdetail_info_201401、cs_userdetail_info_201402、cs_userdetail_info_201403、cs_userdetail_info_201404、… …。

大家首先可以想像一下,随着运行时间的增长,该系统将有多少表?

 

  1. 分表”的弊端

在Oracle公司推出分区技术之前,针对大表的访问,我们只能采取分表的策略,这种策略弊端重重,而Oracle早在1996年的Oracle 8版就推出了分区技术,并且将近20年了,Oracle仍然在不懈努力地发展这一技术领域。可惜啊,该开发商仍然在沿用分表策略这一落后理念。分表到底有什么弊端呢?我们结合该系统具体情况,剖析如下:

  • 首先,设计的表和索引太多,导致运行维护工作量浩大,数据库字典内容也太多,影响整个运行效率。举个简单例子,假设业务需要增加一个字段,我们将在所有分表上面都增加这个字段,多么愚昧呀!
  • 其次,导致应用开发逻辑不灵活、复杂化。不仅每个语句都要采取拼接方式,根据客户输入的年月等信息拼出需要访问的相关表,而且如果需要查询统计业务跨月份,都需要编写大量SQL语句,并进行UNION操作以及设计大量VIEW等。应用开发人员就不嫌麻烦?
  • 分表设计导致表名动态变化,使得Oracle 11g之后自动优化工具(Automatic Tuning)和SQL Profile功能难以实施,极大地影响了SQL语句优化效果。
  • 在应用级人为进行多表设计,无法保证数据的完整性。例如我们发现在现有CRM系统中,DCUSTPAYOWEDET200703表就包含了非200703的数据。

 

  1. 深层次原因分析

本人早在2006年就曾为该移动客户提供过服务,当时针对这种“分表 + 分区”策略非常不理解。一直到2014年该开发商开发新一代核心系统了,我们终于有了与设计人员面对面的机会,才了解了更深层次的原因。

首先,我们感觉设计人员并不一味拒绝Oracle分区技术。否则,他们将全面抛弃Oracle分区技术,而全部采用分表策略。

其次,也是最根本的,通过交流我们发现,原来是设计人员不太了解Oracle分区技术。更具体的,原来他们只知道Oracle有范围分区,对HASH分区,尤其是Oracle组合分区等是一脸茫然。

现在解释前面的伏笔:设计人员为什么要将用户附加信息表(CS_UserAdd_info)既分表又分区?重复前面叙述:设计人员认为CS_UserAdd_info记录非常多,直接按用户id头两位按地市分区,分区表记录仍然很多,因此先按用户id最后一位先分成10张表,再分区。哎哟唉,你可以直接根据用户id字段进行HASH分区呀,例如4份、8份、16份、32份… …,这样不仅每个分区数据均匀,而且可以灵活地分成你想需要的份数,与地市无关!HASH分区的缺陷呢?不能按分区进行大批量数据管理。但这是用户附加信息表,我们不会存在大批量删除用户数据等管理操作的,因此这种担心是多余的。

至于历史表为什么要分表呢?同样地,设计人员不知道我们可以先按时间字段进行一维分区,再按用户id进行HASH分区。更准确地讲,设计人员可能根本不知道Oracle还有Range -List、Range -Hash、Range –Range、Interval – List、Interval – Hash、Interval–Range等9种组合分区技术。

如果我们是习武之人,假设连自己到底有多少种兵器都不知道,仅凭手中一杠红缨枪,你就敢包打天下?

 

  1. 摈弃“分表”,全面采取“分区”策略

毋庸置疑,分区相比分表有全面优势,因此,摈弃“分表”,全面采取“分区”策略是毫无疑问的。这就是我们结合上述案例的分区改造方案:

  • 以用户id进行HASH分区的表

现有设计中按用户id头两位(表示地市)进行范围分区,其目的就是均匀打散该表。为此,我们建议直接对用户id进行HASH分区。这样的好处是分区方法更简单,而且数据分布更均匀。具体的表如下:

  • cs_userdetail_info用户详细信息表。例如按用户 id字段进行16份HASH分区。
  • cs_userdetaildead_info用户详细信息拨备表。例如按用户 id字段进行16份HASH分区。
  • CS_UserAdd_info 用户附加信息表。例如按用户 id字段进行64份HASH分区。同时取消该表的分表设计,即取消CS_UserAdd_info_$X表。
  • CS_UserAdddead_info用户附加信息拨备表。例如按用户 id字段进行16份HASH分区。
  • 以Range-HASH或Interval-Hash进行组合分区的表

以下表均以Range-HASH或Interval-Hash进行组合分区,其中第一维为时间分区,第二维为用户id字段。

  • cs_scoreuse_rd积分消费记录表。例如第一维按时间字段的月或年分区,第二维按用户 id字段进行16份HASH分区。
  • CS_UserState_info用户状态变更轨迹表。例如第一维按时间字段的月或年分区,第二维按用户 id字段进行16份HASH分区。
  • 所有历史表。例如第一维按时间字段的月或年分区,第二维按用户 id字段进行16份HASH分区。

将时间字段作为第一维分区字段,主要考虑历史数据成批清除需要。若数据量不是非常大,例如一维分区之后每个分区数据不超过1千万,也可以考虑只实施时间字段的一维分区,取消用户id字段的第二维分区,简化设计。

  • 索引分区建议
  • 以用户id进行HASH分区的表

由于这类表主要按用户id进行访问,因此建议将用户id建立成Local Prefixed索引。这样,性能能得到保障。

  • 以Range-HASH或Interval-Hash进行组合分区的表

若查询条件包含第一维分区时间字段,则建议将此类查询条件建立成Local Prefixed索引。这样,不仅性能能得到保障,这类分区索引的高可用性也得到保障。

若查询条件不包含第一维分区时间字段,则建议将此类查询条件建立成Global Hash Partition索引。例如,若只按用户id进行查询,则将用户id建立成16份的Global Hash Partition索引。此类索引性能将得到保障,缺陷是当进行按分区操作(drop等)进行历史数据清理时,此类索引将失效。但只要历史数据清理频度不高,应该是可以接受的方案。建议不要将此类索引设计为local non-prefix索引,这类索引将导致日常查询性能低下。

 

  1. 罗马不是一日建成的

尽管无论是设计开发人员,还是移动用户都对分区优势有目共睹。但真要实施浩大的改造工程时,开发商部分人员又是顾虑重重,他们最担心的应用改造工作量,以各种名义进行抵触,例如强调现有系统已经比较稳定,不宜进行大规模改造。恕本人直言,他们不是以设计和开发质量为目标,而是以应用改造工作量为目标了。

唉,开发商的这部分人员太本位主义,也太缺乏长远眼光了,只考虑自己的工作量,而忽略了设计和开发本身的质量。的确,将分表改为分区将导致应用软件大幅度改造,但这种改造是对现有应用软件的大幅度简化,而且是一劳永逸的,是正能量的。趁新一代核心系统正在设计开发之际,立即着手这种改造,将会为该系统的长治久安打下良好基础。

大家重温一下伟人一句诗吧:“风物长宜放远量”。

 

  1. 与MySQL相关的话题

该移动客户的新一带核心系统还有一个特点,即交易系统采用Oracle数据库,而报表、历史数据管理等采用MySQL数据库。于是,保持两个不同平台应用兼容性,降低应用开发和管理难度,成了开发商又一个关注重点。

是否完全摈弃分表,而全面采用分区策略?不得不考虑MySQL是否支持分区了,另外开发尚还担心MySQL单表记录数有限制。为此,我们专门咨询了Oracle公司在MySQL方面的专家,得到的答复是:

  • 理论上,MySQL的表记录没有明确限制。主要取决于操作系统的文件限制。
  • MySQL已经支持分区技术。具体而言,在partition一级支持range/list/hash和其它等方式,在subpartition一级支持hash/ key等方式

既然如此,我们就如此大胆谏言了:采用Oracle和MySQL都支持的分区技术,简化数据库设计和应用开发,提高可管理性和扩展性。

 

2014.10.18于北京

如何理解Oracle中的incarnation概念?

如何理解Oracle中的incarnation概念?

 

小明 活到了90岁 这是incarnation A , 这个matrix 矩阵世界里的 root (or oracle)管理员 将 小明世界的时间节点回退到了小明20岁时(同时resetlogs),由于神的能力还不足以让这个宇宙里的一切量子变化都保证和之前的那一次完全一样,所以这次回退节点里的小明 是incarnation B,最后incarnation B的小明也会活到90岁。

虽然最后2个小明都90岁了,但这2个小明并不是一样的 ,他们都叫小明,但需要区别他们 所以一个叫incarnation A 另一个叫incarnation B。 在其他平行世界里可能还有其他 incarnation的小明,这取决于 root (or oracle)管理员的需求。