dbms_space.create_table_cost的unwrap解密和原理解析

Oracle提供了一系列PL/SQL package,包含了函数、存储过程,方便用户的使用,可以参考《Oracle Database PL/SQL Packages and Types Reference》手册,但其中一些存储过程的实现细节,Oracle并未透露,且对其进行了加密wrap。俗话说的话,“高手在民间”,从Oracle 9i开始,就有牛人前辈,找出了解密unwrap的一些方法,便于我们学习Oracle的一些实现,对此我是佩服的五体投地。

但究竟我们是否可以找出,所有存储过程的实现细节?

接下来就以之前介绍表容量预估,曾用过一个DBMS_SPACE包中的create_table_cost存储过程为例,探究下如何知道其实现。

说unwrap就要提到大名鼎鼎的FyUnWrap工具,他的开发者是黄玮,可能有些人对这个名字陌生,但要说起HelloDBA,就比较出名了。这位ACE是相当的低调,可能由于目前国外定居,基本没有听过他的演讲,他曾经出过一本《oracle 高性能sql引擎剖析:sql优化与调优机制详解》,写的是非常深,法力无边,反正我是没看完,并且没看懂所有内容。。。

如下链接,http://www.hellodba.com/reader.php?ID=121&lang=CN,“为尊重PLSQL开发者的劳动成果,目前暂不提供下载。如有需要,请发邮件(fuyuncat@gmail.com)。“

打开工具,输入数据库用户名、密码、tnsname(需要数据库监听启动)、是否sysdba身份登录,即可连接至目标数据库,接下来就可以选择schema以及对象类型,有FUNCTION、PACKAGE、PACKAGE BODY、PROCEDURE、TYPE、TYPE BODY、VIEW这几种类型。

此处我们首先选择SYS,对象类型为PACKAGE,不选Wrapped,可以找出DBMS_SPACE包的定义,

从Wrapped Text中,可以找出create_table_cost的两个版本,

我们看每个存储过程,定义下面有一个

pragma restrict_references(create_table_cost,WNDS);

这是什么玩意?

这篇MOS文章给出了解释,WHAT IS THE PRAGMA RESTRICT_REFERENCES STATEMENT (Doc ID 1037020.6)

pragma restrict_references是一个编译器指令,用来限制拒绝,他所定义的函数,对数据库表或者包变量,是否有读写权限,这用的是WNDS,表示不能写入数据状态,不能对数据库表进行修改,相当于一个只读用法。

接着,此处我们选择SYS,对象类型为PACKAGE BODY,选中Wrapped,可以找出DBMS_SPACE包,右侧显示的是Oracle wrap加密的信息,

其实上方Wrapped Text的内容来自于$ORACLE_HOME/rdbms/admin/prvtspcu.plb文件,点击Unwrap,下方显示的就是这个package解密内容,

我们之前介绍,create_table_cost有两个版本,一个是接受AVG_ROW_SIZE平均行长为参数,一个是接受CREATE_TABLE_COST_COLUMNS类型变量为参数,针对这两种类型,unwrap显示的信息,有一些区别。

(1) 接受CREATE_TABLE_COST_COLUMNS类型变量为参数的版本。

注:测试库是11.2.0.4,字符集是UTF-8,

首先是一系列变量定义,

实现非常funny,比较容易理解,

(a) 首先获取CHAR_CS和NCHAR_CS在字符集中的ID值,分别是873和2000,这是NLS_CHARSET_ID函数的解释,

(b) 根据(a)得到的ID值,调用NLS_CHARSET_DECL_LEN函数,得到这两种类型的定义长度,分别为840和420,至于其中为何NICE_MULTIPLE的值是8 * 3 * 5 * 7,我不是很清楚,哪位朋友了解,可以告诉我们,这是NLS_CHARSET_DECL_LEN函数的解释,

(c) 计算得出每个CHAR和NCHAR占用的字节,

BYTES_PER_CHAR = NICE_MULTIPLE / CHAR_CNT = 8 * 3 * 5 * 7 / 840 = 1

BYTES_PER_NCHAR := NICE_MULTIPLE / NCHAR_CNT = 8 * 3 * 5 * 7 / 420 = 2

(d) create_table_cost_colinfo类型变量有两个属性,COL_TYPE和COL_SIZE,

接下来会遍历这个变量,将COL_TYPE变为小写,针对不同类型,计算其COLSIZE(此处为存储过程的变量,不是create_table_cost_colinfo属性),其中,

(i) date类型,COLSIZE设置7。

(ii) long类型,COLSIZE设置65536

(iii) number类型,COLSIZE设置CEIL(COLINFOS(I).COL_SIZE / 2),即取>=(NUMBER类型自定义长度/2)的最小整数。

(iv) timestamp类型,COLSIZE设置7+>=(TIMESTAMP类型自定义长度/2)的最小整数。

(v) varchar或varchar2类型,COLSIZE设置>=(COLINFOS(I).COL_SIZE)的最小整数 * BYTES_PER_CHAR(本测试为1bytes)。

(vi) nvarchar或nvarchar2类型,COLSIZE设置>=(COLINFOS(I).COL_SIZE / 2) * BYTES_PER_NCHAR(本测试为2bytes)。

(vii) char类型,COLSIZE设置COLINFOS(I).COL_SIZE * BYTES_PER_CHAR(本测试为1bytes)。

(viii) nchar类型,COLSIZE设置COLINFOS(I).COL_SIZE * BYTES_PER_NCHAR(本测试为2bytes)。

如果不属于以上任何类型,则COLSIZE设置COLINFOS(I).COL_SIZE。

(e) 循环计算ROWSIZE := ROWSIZE + COLSIZE + 1,ROWSIZE默认为3,设置每一个新的ROWSIZE值为(3+修正的COLSIZE+1),得出的是表中所有字段,不同数据类型,接近平均的一个近似值。

(f) 调用CREATE_TABLE_COST(TABLESPACE_NAME, ROWSIZE, ROW_COUNT, PCT_FREE, USED_BYTES,ALLOC_BYTES)存储过程,其中ROWSIZE是用上面(a)-(e)计算得出的。

可以粗略看出,对于varchar/nvarchar/varchar2/nvarchar2这种变长类型,行长平均值为其自定义一半,char/nchar这种定长类型,行长平均值为其自定义。因此这种方法计算出的值,只能说是预估值。

(2) 接受AVG_ROW_SIZE平均行长为参数

从(1)可以看出,create_table_cost接受CREATE_TABLE_COST_COLUMNS类型变量为参数,实际调用的就是接受AVG_ROW_SIZE平均行长为参数的版本,我们看下这个版本定义,

看出其实际调用的是另一个KTSAP_CREATE_TABLE_COST,再看这一个存储过程定义,

只有这一段PRAGMA INTERFACE(C, KTSAP_CREATE_TABLE_COST);,这是什么东东?

检索MOS,发现和这个词沾边的,只有这么一个,

从这个错误描述中推断,大致是此处调用了一段C程序,将KTSAP_CREATE_TABLE_COST包括变量值,作为参数传给这段代码,他完成空间预估的计算,将计算结果赋予USED_BYTES和ALLOC_BYTES。

推测就是推测,需要搜一下,是否有什么资料说明了此问题。尝试使用了各种搜索引擎,未能找出,直到借用了同事的手机,翻墙Google,找到了这么几篇文章,

http://www.petefinnigan.com/weblog/archives/00000835.htm

http://awads.net/wp/2006/05/24/about-the-builtin-fipsflag-and-interface-pragmas-in-oracle/

才进一步能支持之前的推测。

首先这种pragma叫做undocumented pragma,即未记录的,我理解就和10046这种event一样,Oracle官方发布的资料中不会记载,使用了出错了,Oracle不会负责任,但是学习他,可以让我们了解Oracle一些INTERNAL知识,就像有人说的,

I like undocumented features, we should not use them of course in production databases but they give clues to the internal workings of the database and for people like they also give clues as to how you can break Oracle.

“生产系统不应该使用这些undocumented特性,但是这些undocumented特性给了我们一些可以了解数据库的线索提示,进一步的可以break“破坏”Oracle”。

既然知道了,调用的是一段C程序,接下来可以做什么呢?答案就是nothing,

Now that you know about these undocumented pragma directives, what next? nothing. It’s just interesting to know that they exist and to see how Oracle implements calls to its built-in functions behind the scenes. There is however some mystery surrounding the use of PRAGMA FIPSFLAG. If you have any additional information, please share with the rest of us. Thanks.

前两天建荣的文章中,引用了JL大神的一段话,

学习Oracle时要懂得权衡。大部分时候,只要大体知道引擎是如何工作的就足够了,偶尔才需要知道一些世界上只有一小部分人才会知道的精确资料。注意,不要浪费时间去研究不必要的细节,而是要找到折中的办法,使你所掌握的知识足以预判Oracle在你没见过的场景中会怎样做。

概括来讲,就是点到为止,到这里我们知道了create_table_cost接受CREATE_TABLE_COST_COLUMNS类型变量为参数的版本,实际调用的就是接受AVG_ROW_SIZE平均行长为参数版本,还知道其调用的是KTSAP_CREATE_TABLE_COST存储过程,而KTSAP_CREATE_TABLE_COST调用了PRAGMA INTERFACE(C, KTSAP_CREATE_TABLE_COST)一段C程序,至于C程序中是如何实现的,我们无从得知,但并不影响我们理解和使用这个存储过程,反而对其实现可能有了,更深一层次的认识了。

这个过程中另一个发现,就是oracle.exe文件中有ktsaps_create_table_cost声明,说明create_table_cost存储过程其实屏蔽了ktsaps_create_table_cost,就像v$视图屏蔽了v_$视图,不仅动态性能视图用这种方法来保护底层实现,存储过程也可以用类似的方法保护底层实现,

[oracle@BISAL bin]$ strings oracle | grep create_table

_create_table_in_any_cluster

ktsaps_create_table_cost

kpomem_create_table

总结:

1. 通过本文可以基本掌握unwrap一些Oracle加密的包、存储过程等的方法,其实就是使用fyunwrap工具,但如果知道其实际引用的原理(例如$ORACLE_HOME/rdbms/admin),可能更有助于我们的理解。

2. 了解了create_table_cost存储过程两个版本的实现,终极调用就是ktsaps_create_table_cost作为参数的一个C程序。

3. 对我来说,体验了整个unwrap的过程以及create_table_cost的实现原理,重要的不是结论,而是亲身经历,受益匪浅。

如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)

时间: 2024-10-12 20:26:11

dbms_space.create_table_cost的unwrap解密和原理解析的相关文章

Skinned Mesh原理解析和一个最简单的实现示例

Skinned Mesh原理解析和一个最简单的实现示例   作者:n5 Email: happyfirecn@yahoo.com.cn Blog: http://blog.csdn.net/n5 2008-10月   Histroy: Version:1.01  Date:2008-11-01        修改了一些不精确的用语 Version:1.00 Date:2008-10-19     讲述骨骼动画的资料很多,但大部分都是针对DX8或DX9的SkinnedMesh进行讲解.我觉得对于骨

[IT]JSONP跨域的原理解析

JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为"Same-Origin Policy"(同源策略).这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript 只能访问与包含它的文档在同一域下的内容. JavaScript这个安全策略在进行多iframe或多窗口编程.以及Ajax编程时显得尤为重要.根据这个策略,在baidu.com下的页面中包含的JavaScript代码

Android中微信抢红包插件原理解析及开发思路_Android

一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了.或许是网络的原因,而且这个也是最大的原因.但是其他的不可忽略的因素也是要考虑到进去的,比如在手机充电锁屏的时候,我们并不知道有人已经开始发红包了,那么这时候也是让我们丧失了一大批红包的原因.那么关于网络的问题,我们开发者可能用相关技术无法解决(当然在Google和Facebook看来的话,他们

Android代码入侵原理解析(一)

Android代码入侵原理解析(一)           1.代码入侵原理 代码入侵,或者叫代码注入,指的是让目标应用/进程执行指定的代码.代码入侵,可以在应用进行运行过程中进行动态分析,也是对应用进行攻击的一种常见方式.我把代码入侵分为两种类型:静态和动态.静态代码入侵是直接修改相关代码,在应用启动和运行之前,指定代码就已经和应用代码关联起来.动态代码入侵是应用启动之后,控制应用运行进程,动态加载和运行指定代码. 2.静态代码入侵 静态代码入侵,有直接和间接的手段. 直接手段是修改应用本身代码

秋色园QBlog技术原理解析:性能优化篇:字节、缓存、并发(十二)

文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色园QBlog技术原理解析:UrlRewrite之无后缀URL原理(三) --介绍如何实现无后缀URL 4: 秋色园QBlog技术原理解析:UrlRewrite之URL重定向体系(四) --介绍URL如何定位到处理程序 5: 秋色园QBlog技术原理解析:Module之页面基类设计(五) --介绍创建

秋色园QBlog技术原理解析:性能优化篇:access的并发极限及超级分库分散并发方案(十六)

上节回顾:   上节 秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五) 中, 介绍了 秋色园QBlog 在性能优化方面,从技术的优化手段,开始步入数据库设计优化,并从数据的使用情况上进行了分析,从而将文章内容进行分离,得到新的分表,由于内容比较大,进而分了库,达到一种基础减压.   本节内容:   本节将介绍秋色园 QBlog 的Super分库方案,以及何以如此Super分库的原因.   描述说明:   在进行上了上节的分库方案后,虽然感觉一度秋色园QBlog的访

SQL Server 内存数据库原理解析

原文:SQL Server 内存数据库原理解析 前言 关系型数据库发展至今,细节上以做足文章,在寻求自身突破发展的过程中,内存与分布式数据库是当下最流行的主题,这与性能及扩展性在大数据时代的需求交相辉映.SQL Server作为传统的数据库也在最新发布版本SQL Server 2014中提供了新利器 SQL Server In-Memory OLTP(Hekaton),使得其在OLTP系统中的性能有了几十倍甚至上百倍的性能提升,本篇文章为大家探究一二.         大数据时代的数据如何组织应

秋色园QBlog技术原理解析:性能优化篇:用户和文章计数器方案(十七)

上节概要:   上节 秋色园QBlog技术原理解析:性能优化篇:access的并发极限及分库分散并发方案(十六) 中, 介绍了 Access的并发上限,及从某种程度上 秋色园QBlog 针对并发上限进行了多个数据的划分,从而最大并发上限从64提升到64*N(个数据库),虽然总和的最大并发值是上升了,但是单个库的最大值并没有变化,或者说单个表的最大并发值没有发生变化,上限仍是64. 于是,对于频繁产生更新操作的访问计数器(用户表及文章表),是该进入优化的方案了.   本节概要:   本节将介绍秋色

秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五)

文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色园QBlog技术原理解析:UrlRewrite之无后缀URL原理(三) --介绍如何实现无后缀URL 4: 秋色园QBlog技术原理解析:UrlRewrite之URL重定向体系(四) --介绍URL如何定位到处理程序 5: 秋色园QBlog技术原理解析:Module之页面基类设计(五) --介绍创建