在 DB2 9.7 for Linux, UNIX, and Windows 上运行 Oracle 应用程序(转)

转自:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0907oracleappsondb2/

DB2 9.7 添加了 Oracle 兼容性特性

要使为某个 RDBMS 编写的应用程序运行在另一个上并且基本上没有变化,很多部分要依序出现。不同的锁机制、数据类型、SQL、服务器上的过程语言、甚至应用程序自身使用的客户机接口都需要保持一致,不仅在语法上而且在语义上。

DB2 中已经采取了所有这些步骤。变化是例外,而不是规则(IBM 可以迅速访问需要的应用程序变更)。表 1 提供了对常用特性的快速概览:


表 1. 常用特性

Oracle --> DB2
并发性控制 --> 本机支持
SQL 专用语言 --> 本机支持
PL/SQL --> 本机支持
PL/SQL 包 --> 本机支持
内置包 --> 本机支持
带有扩展的 JDBC 客户机 --> 本机支持
SQL*Plus 脚本 --> 本机支持

通过 DB2 9.7,就不再需要为应用程序确定端口了。只要启用 应用程序即可。在使用打包应用程序的时候,甚至可能为 DB2 和 Oracle 共享一个源

换句话说,在 DB2 中支持 Oracle 应用程序不比使为 HP-UX 编写的 C 程序运行在 AIX 上复杂多少。

 

 

并发性控制

过去,Oracle 与 DB2 之间最突出的不同一直是并发性控制方法不同。比较易记的说法是:“读取器不会阻止编写器且编写器不会阻止读取器”。


表 2. Oracle 并发性行为

挂起事务 行为 新事务
读取器 不会阻止 读取器
读取器 不会阻止 编写器
编写器 不会阻止 读取器
编写器 阻止 编写器

不用深入到隔离级别,现在足以说明使用 Oracle 默认的语句级隔离 的绝大多数应用程序在使用 DB2 默认的游标稳定性(Cursor Stability,CS)时也能很好的工作。

但是,传统上,CS 已经实现了,所以编写器组织读取器并且,在某些情况下,读取器可以组织编写器。原因是传统上,在 CS 隔离级别下的事务将 “等待挂起的并发事务的变更的结果”。


表 3. 传统 DB2 的 CS 并发性行为

挂起事务 行为 新事务
读取器 不会阻止 读取器
读取器 很少阻止 编写器
编写器 阻止 读取器
编写器 阻止 编写器

最终发现在 CS 隔离下运行的事务在遇到变更的行时等待结果 不是出于语义原因。另一个比较满意的行为是读取变更行的当前提交版本。

此行为已经在 DB2 9.7 中实现。具体方法是 DB2 只需从日志中获取锁定行的当前提交版本。在大部分一般情况下,该行仍位于日志缓冲区,因为尚未提交变更。但是只要该行已经编写出来并且 也已经在日志缓冲区中重写,DB2 就能准确知道在哪里找到它,因此单次 IO 就可以将需要的版本带入缓冲区。

假设(请参见图 2),一个用户更新员工表中的名字。在该用户提交变更之前,另一个用户在浏览这个表。过去,第二个用户不得不等待第一个用户提交或回滚。借助于读取当前提交数据 特性,第二个用户的浏览操作只需从不包含第一个用户变更的日志缓冲区获取该行的版本即可。


图 2. 编写器不阻止读取器
编写器不阻止读取器 

注意一下这个行为:

  • 没有引入新对象,比如回滚段
  • 编写日志之后,编写器就没有性能开销了
  • 不会引起任何类似 “快照过旧” 的情况,因为几乎不可能出现所需的日志文件已经被归档(而事务仍然打开!)在这种情况下,DB2 将会后退并等待锁消失

除了这些变更,其他避免锁定技术也已经被引入 DB2 了,以便清除在 CS 隔离下持有锁读取器。


表 4. 新 DB2 的 CS 并发性行为

挂起事务 行为 新事务
读取器 不会阻止 读取器
读取器 不会阻止 编写器
编写器 不会阻止 读取器
编写器 阻止 编写器

如您所见,DB2 的并发性行为现在与 Oracle 的一样了。事实上,新创建的 DB2 数据库会默认表现出这种行为。

 

 

新数据类型

每个数据库的核心都是其数据。错配的类型或这些类型错配的语义可能会严重影响在另一个 RDBMS 中支持一个应用程序的能力。因此,要允许 Oracle 应用程序在 DB2 上运行,很重要的一点是要支持其非标准的基本类型,比如字符串、日期和数字。除了调整这些基本类型之外,Oracle PL/SQL 中常用的其他一些更复杂的类型也已经添加到了 DB2 9.7 中。


表 5. 新 DB2 数据类型

数据类型 说明
NUMBER 在 DECFLOAT(通过 Power6 硬件加速)和 DECIMAL 基础上添加了对 NUMBER 和 NUMBER(p [, s]) 的支持。
VARCHAR2 VARCHAR2-类型的行为包括被解释为 NULL 的空字符串和对结尾空白敏感的纠正。
Oracle DATE Oracle 中数据库的 DATE 模式除了日历日期还包括 TIME 组件
TIMESTAMP(n) 秒的小数部分的范围可以在 0(日期 + 时间)到 12(微微妙)之间选择。
BOOLEAN 此类型可以用在过程逻辑、变量和例程的参数中。
VARRAY 过程中的 ARRAY 支持已经扩展到支持 VARRAY 风格的方法和语法。
INDEX BY 除了常规数组,DB2 还支持联合数组。
ROW TYPE 此复合类型可以用在变量和参数中,并且作为元素用在数组和联合数组中。
Ref Cursor TYPE 游标可以指定给变量或者使用参数到处传递。

 

隐式的类型转换和类型解析

“如果走路像鸭子,讲话像鸭子,那么它一定是鸭子。”

这是很多新兴语言,比如 PHP 和 Ruby,的原则。每个字面值都是一个字符串,然后根据上下文用作另一个类型。过去,秉承了 SQL 标准并遵循了类型错配很可能预示着编码错误的原则,DB2 一直遵守着强硬的类型规则,其中字符串和数字不能比较,除非某一个经过显式地类型转换,转换成另一个。

不幸地是,Oracle 应用程序在其 SQL 中使用了较弱的类型规则,过去该应用程序可能不能在 DB2 上编译。在 DB2 9.7 中,添加了隐式的类型转换(较弱的类型规则)。也就是,可以以非常灵活的方式比较、赋值和操作字符串和数字。

此外,可以在很多地方使用无类型的 NULL,而且几乎可以在任何地方使用无类型的参数标记,这要多亏了递延准备 功能。也就是说,在发现其第一个实际值之前,DB2 不用再解析参数标记类型。

为了完成隐式类型转换,DB2 还支持默认的过程参数以及通过名称关联 argument 和 parameter。

 

 

DB2 中扩展的内置函数库

所有 RDBMs 都提供了函数库来操作数据。问题时没有哪两个数据库对这些函数使用同样的名称,尽管最终其功能都非常类似。

除了其自己传统的函数集,DB2 现在支持与 Oracle 兼容的库。以下列表提供了快速概览,当然不可能是全部的:

  • 转换和类型转换函数
    • TO_DATE
    • TO_CHAR
    • TO_CLOB
    • TO_NUMBER
    • TO_TIMESTAMP
    这些函数中的每一个都支持丰富的兼容格式字符串集。
  • 日期算法
    • EXTRACT
    • ADD_MONTHS
    • MONTHS_BETWEEN
    • NEXT_DAY
    • 加号 (+) 添加天的分数
  • 字符串操作
    • LPAD
    • RPAD
    • INSTR
    • INITCAP
    • 扩展到 SUBSTR
  • 其他
    • NVL
    • DECODE
    • LEAST
    • GREATEST
    • BITAND

两种产品间支持函数的重合部分不断增加表明在 DB2 上对 Oracle 应用程序开箱即用的支持得到了极大改进。

 

 

Oracle SQL 专用语言支持

到目前为止,本文介绍了并发性、数据类型、类型规则和函数。但是 Oracle 和 DB2 之间的不同不止于此。SQL 专用语言的框架、其关键字和语义在某些方面是不同的。而且每个产品都会有一些特性是另一个不支持的。在这些特性流行时,它们限制了为两种产品提供通用 SQL 的能力。在大大小小的语言不同中,表 6 列举了一些重点:


表 6. 新的 SQL 支持

特性 说明
CONNECT BY 递归 到目前为止,DB2 已经支持 ANSI SQL 递归了。现在,已经可以添加 Oracle-样式的 CONNECT BY 了,包括各种函数和伪列,比如 LEVEL  CONNECT_BY_PATH
(+) 连接语法 这种语法实际上甚至连 Oracle 都不提倡了,但是有很多应用程序和开发人员仍在使用这种形式的OUTER JOIN 语法。
DUAL  单行、单列表在 Oracle 应用程序中被广泛地用作哑表。
ROWNUM 伪列 该伪列通常用于限制返回的行数并在结果集中枚举行。
ROWID 伪列 Rowid 用于快速获取之前根据其物理地址获取的行。
MINUS SQL 操作符 在 Oracle 中,用 MINUS 而不是 EXCEPT 从另一个结果集中减去一个结果集。
SELECT INTO FOR UPDATE FOR UPDATE 构建在 SELECT INTO 之上,允许从 DB2 中抽取一行,以便稍后在不使用游标的情况下修改它。
PUBLIC SYNONYM 公共同义字是一个没有模式名的别名。DB2 支持表对象、序列和 PL/SQL 包的公共同义字。
CREATE TEMPORARY TABLE 除了声明全局临时表之外,DB2 还支持创建全局临时表。
TRUNCATE 表语句 此语句无需激活触发器即可快速删除整个表的内容。
不严格的名称解析 DB2 9.7 不再需要命名内联视图。另外,可以更轻松地从集合操作符(比如 UNION)继承列名称。

到这里,对 DB2 变化的概述就结束了,这是因为有了这些变化,向 DB2 数据库提交 SQL 的 Oracle 应用程序才能保持几乎不变的运行。但是,有很多应用程序的主要部分在服务器自身上执行。Oracle 应用程序服务器端的语言选择是 PL/SQL。没有对 PL/SQL 的支持,就不要声称可以提供兼容性。

 

 

DB2 对 PL/SQL 的支持

通常,应用程序从一个产品定位到另一个产品时,SQL 和过程语言也从一种 SQL 专用语言转换成另一种。这会造成几个问题:

  • 由于源和目标语言之间自动的不顺畅的错配导致得到的转换后代码让人费解。
  • 应用程序开发人员不熟悉目标 SQL 专用语言。这使得调试转换后的代码很困难。由于缺乏技能,后续维护会成为一个难题。
  • 在处理打包应用程序时,需要为该应用程序的每个新版本重复转换。
  • 最后,结果只是类似,从理论上说,它要比原始程序运行得慢一些。

为了避免这些问题,DB2 9.7 包含了本机 PL/SQL 支持。这意味着什么呢?

如您在图 3 中看到的,DB2 引擎现在包括一个 PL/SQL 编译器以及一个 SQL PL 编译器。这两个编译器为 DB2 的 SQL Unified Runtime Engined 生成虚拟机代码。很重要的一点是要注意到监控和开发工具,比如 Optim Development Studio,是在运行时引擎级别被挂靠到 DB2 的。


图 3. PL/SQL 编译器支持
Optim Development Studio 中的 PL/SQL 编译器支持 

将 PL/SQL 作为一类过程语言集成到 DB2 中有以下几个影响:

  • 没有转换。源码在模式目录中保持原样。
  • 开发人员可以继续使用熟悉的语言工作。无需将逻辑移动到 DB2 的专用语言,即使新逻辑是用 SQL PL 编写的。使用不同语言的例程可以彼此调用。
  • 打包应用程序厂商可以针对 Oracle 和 DB2 使用一个源代码。
  • PL/SQL 和 SQL PL 都为 DB2 的 SQL Unified Runtime Engine 生成同样的虚拟机代码。因此,在设计上,PL/SQL 和 SQL PL 执行的速度一样。
  • 因为调试器基础设施直接挂钩在 SQL Unified Runtime Engine 中,所以 PL/SQL 很自然地得到 Optim Development Studio 的支持。

图 4 说明了 PL/SQL 调试会话。该调试器支持标准特性,比如跳入、跳过和断点。此外,它允许用户在程序运行时,改变局部 PL/SQL 变量。


图 4. DB2 中支持的 PL/SQL 调试器 
DB2 中支持的 PL/SQL 调试器 

PL/SQL 语法细则

那么,PL/SQL 支持究竟意味着什么呢?首先,有一个核心语法支持。DB2 支持所有 PL/SQL 的通用构造,比如:

  • if then else
  • while 循环
  • := 赋值
  • 局部变量和常量
  • #PRAGMA EXCEPTION 和异常处理
  • 各种形式的 for 循环(范围、游标和查询)
  • %TYPE 和 %ROWTYPE 将变量和参数锚定到其他对象
  • #PRAGMA AUTONOMOUS 事务,允许在私有事务中执行过程

PL/SQL 对象支持

PL/SQL 可以用在各种不同的支持过程逻辑的对象中:

  • 标量函数
  • 在每行触发器之前
  • 在每行触发器之后
  • 过程
  • 匿名块
  • PL/SQL 包

PL/SQL 包支持

Oracle 应用程序中的大部分 PL/SQL 都包含在所谓的中。PL/SQL 包 — 不要与 DB2 包弄混 — 是单个对象的集合,能够区分那些外部可访问的对象和哪些仅用于包内部的帮助函数。包的 ANSI SQL 等价物是 模块。DB2 现在支持 ANSI SQL 模块以及 PL/SQL 包。特别是,提供了以下功能:

  • CREATE [OR REPLACE] PACKAGE,定义外部访问例程的原型。它还定义了所有外部可访问的、非过程对象,比如变量和类型。
  • CREATE [OR REPLACE] PACKAGE BODY,它实现了所有私有和公共例程以及所有其他私有对象。
  • 在包或包体内部,可以定义以下对象:
    • 变量和常量
    • 数据类型
    • 异常
    • 标量函数
    • 过程
    • 游标
  • 包初始化
  • 包的公共同义字

 

 

DB2 提供了通用内置包

某些 Oracle 应用程序利用 RDBMS 提供的包。特别是,提供报告、电子邮件或交叉连接通信的库非常流行。为了便于 DB2 支持这些应用程序,DB2 提供了表 7 中列出的包:


表 7. DB2 提供的内置包

说明
DBMS_OUTPUT 提供基本报告功能,可以通过命令行开关。
UTL_FILE 允许处理 DB2 服务器上的文件的模块。
DBMS_SQL 除了现有 EXECUTE  EXECUTE IMMEDIATE 语句,该包提供了用于执行动态 SQL 的 SQL API。
UTL_MAIL 该模块允许从 SQL 发送电子邮件通知。
UTL_SMTP 低级别的 API,类似于提供 SMTP 集成的 UTL_MAIL。
DBMS_ALERT 该包使用时允许不同的会话之间彼此发信号。
DBMS_PIPE 该模块允许会话彼此发送数据。
DBMS_JOB 提供与 DB2 的任务调度器集成的可兼容 API。
DBMS_LOB Oracle API,用于 LOB 处理,回应 DB2 的内置 LOB 函数。
DBMS_UTILITY 应用程序中使用的各种过程的集合。

 

特定于 Oracle 的 JDBC 扩展

JDBC 是标准 Java 客户机接口。但是为了支持特定的非标准数据类型,已经向 Oracle 的 JDBC 驱动程序中添加了扩展。

要将基于 Java 技术的应用程序的兼容性提到最高,DB2 9.7 JDBC 驱动程序提供了对通过引用游标和 VARRAY 参数调用过程的支持(当然还提供了其他一些特性)。

 

 

使用 CLPPlus 的 SQL*Plus 脚本支持

很多时候,DDL 脚本甚至报告都是使用 SQL*Plus 命令行处理器编写的。要使迁移这些脚本以及编写它们的开发人员的技能更加容易,DB2 提供了兼容 SQL*Plus 的命令行处理器,叫做 CLPPlus。该工具提供了以下功能:

  • 兼容 SQL*Plus 的命令选项
  • 变量替换
  • 列格式化
  • 报告功能
  • 控制变量


图 5. 兼容 SQL*Plus 的 CLPLus 工具
兼容 SQL*Plus 的 CLPLus 工具 

 

在 DB2 中使用就像拖放操作那么简单

既然 DB2 已经对 PL/SQL 进行了调整,使其尽可能保持与 Oracle SQL 一致,现在就无需使用复杂的迁移工具箱了。只要使用 IBM Data Movement Tool 就可以轻松地将表、包或整个模式从 Oracle 中拖放到 DB2 中。只有在发生异常的时候需要做很少的修改即可将应用程序移动到 DB2 或者修改应用程序,这样可以在 DB2 和 Oracle 上操作同样的数据源。

步骤可简单到只需:

  1. 设置必要的注册表变量:
    • db2set DB2_COMPATIBILITY_VECTOR=ORA
    • db2set DB2_DEFERRED_PREPARE_SEMANTICS=YES
  2. 重启数据库管理器:
    • db2stop
    • db2start
  3. 创建兼容 Oracle 的数据库:
    • db2 create database mydb pagesize 32 K
    • db2 update db cfg for mydb using auto_reval deferred_force
  4. 启动 IBM Data Movement Tool,并连接到 Oracle 和 DB2 数据库(见 图 6)。连接后,可以选择仅提取 DDL 或者提取 DDL 和数据。最后,有两个选择:通过执行生成的脚本直接部署,或者继续使用交互部署 面板。(对于大部分重要应用程序建议使用后者)。 

    图 6. 使用 IBM Data Movement Tool 拖放 Oracle 模式到 DB2
    使用 IBM Data Movement Tool 拖放 Oracle 模式到 DB2 

  5. 使用交互部署(见 图 7)将需要的模式从 Oracle 移动到 DB2。在交互部署 模式中,您会看到一个导航树,它显示了所有从 Oracle 数据库中提取的对象。选择所有对象并执行部署菜单选项。该工具将复制这些对象到 DB2 并记录其进度。某些对象可能不能成功部署,该工具会为您提供选项来处理这些对象。选择对象时,您会看到 DDL 以及 DB2 遇到的错误。现在可以按需修复定义并使用内置编辑器重新部署。目标是在发生异常的时候交互式地将所有对象移动到 DB2。 

    图 7. 使用 IBM Data Movement Tool 将 Oracle 模式拖放到 DB2
    使用 IBM Data Movement Tool 将 Oracle 模式拖放到 DB2 

 

 

Oracle 数据库与 DB2 兼容性评估

那么使 DB2 9.7 支持 Oracle 应用程序究竟有多容易呢?答案是要视情况而定。IBM 有一个内部工具,叫做 MEET DB2,可以分析 Oracle 数据库中的所有对象并进行评分。它会生成一个报告,其中列出哪些地方可以开箱即用,哪些地方需要进行调整。您的客户代表或销售联系人可以运行此工具快速对您当前的 Oracle 数据库与 DB2 的兼容性进行评估。


图 8. MEET DB2 评估报告工具
MEET DB2 评估报告工具 

在 DB2 9.7 一年的 beta 版测试期间,对很多应用程序(共有 750.000 行 PL/SQL 代码)进行了详细分析,平均开箱即用迁移率为 90%-99%。


图 9. 支持语句的平均迁移率 98%
支持语句的平均迁移率 98% 

 

局限性

DB2 Express、DB2 Express-C 和 DB2 Personal 版目前尚未提供 PL/SQL、内置包库和 CLPPlus。

 

 

结束语

凭借其本机多专用语言 SQL 支持,DB2 9.7 支持在 DB2 上轻松地使用 Oracle 应用程序。打包应用程序厂商可以以最少的成本提供既可用于 Oracle 又可用于 DB2 的应用程序。客户可以自由选择提供其所需技术的厂商,无需收到以前的限制。

要测试这些特性,可以下载 DB2 9.7 的试用版(见 参考资料)。

 

 

常见问题解答

DB2 9.7 支持哪个版本的 Oracle?

为 SQL 和 PL/SQL 专用语言提供的范围严格基于应用程序正在使用的版本。支持最新的 Oracle 11g 中引入的某些特性。但是不支持 Oracle 8i 中使用的某些构造。在一个涉及 18 个应用程序总共 750,000 行代码的研究中,90%-99% 的代码被原封不动的移动到了 DB2。其他代码的调整可以自动进行或者是重复的。

Oracle 应用程序在 DB2 上的运行速度如何?

这个问题很难回答!很遗憾,Oracle 许可条款中禁止任何人未经预先书面同意公布基准测试结果。不用说,我们不会自讨没趣的去询问其是否同意。但是,凭借其特别设计,又经过质量保证基准测试的确认,在 DB2 上用 PL/SQL 编写的应用程序与在 DB2 上用 SQL PL 编写的应用程序运行得一样快。使用过这种支持过程的厂商基本上都感到惊喜。

提供这些特性需要进行多少工作?

不像大家想象的那么多。已经以战略方式为 DB2 9.5 完成了一些初始工作,比如 CONNECT BY  NUMBER。坦率地讲,这些工作会在 18 个月之内完成。

支持从 Oracle 到 DB2 有哪些常见难题?

DB2 的兼容性显然不是 100%。所以在您第一次在 DB2 上使用 Oracle 应用程序时可能有些小问题。但是,这些问题很多都是无足轻重的而且容易修复。例如,DB2 支持 PL/SQL 触发器,但不允许组合触发器操作。就是说,要为 UPDATEDELETE  INSERT 操作共享一个触发器。现在,假设有一个 PL/SQL 多操作触发器,使用 INSERTEDUPDATED  DELETED 谓词的 boolean 变量很容易将它复制到三个 DB2 PL/SQL 触发器中。


 

posted @ 2012-01-04 11:27  catch22  阅读(857)  评论(0编辑  收藏  举报