图灵社区按
TEAP是什么?TEAP是Turingbook Early Access Program的简称,即早期试读,它公布的是图灵在途新书未经编辑的内容。一本书的翻译周期约为3到6个月,如果在翻译过程中,译者就能与读者进行沟通和交流,对整本书的翻译品质是有帮助的。通过TEAP,读者可以提前阅读将来才能出版的内容,译者也能收获宝贵的反馈意见,改进翻译,提高质量。

本书原名为Expert PLSQL Practices,中文暂定名为《Oracle PL/SQL实战》,本篇选自第11章 大规模PL/SQL编程 第1节)

我的社区ID博客

在数据库中使用PL/SQL实现业务逻辑的优势

大多数业务应用程序是以数据为中心的,因此它们的核心都需要数据库支持。这些应用程序通 常会使用数年甚至数十年,在此期间,一方面,用户界面有时会改变或扩展以跟上艺术的形 势。另一方面,数据模型和业务逻辑通常会跟随所要支持的业务流程更稳步地演进。许多这类 应用程序最后会发展得很庞大,无论它们始于小型(比如一个电子表格程序的APEX替代品) 抑或在发端时就很复杂。因此,我们需要一种架构和开发语言,这种架构和语言适合用数年时 间开发和维护以数据为中心的业务逻辑。Oracle数据库的PL/SQL能完美地满足这需求。

用PL/SQL编写业务逻辑会导致大量的PL/SQL代码,例如,我们公司的旗舰应用程序拥有1100 多万行代码,有170位开发人员在维护它,这是真正的大型编程。使用任何语言进行大型编 程,并保持灵活和高效需要良好的模块化和对编程规范严格遵守基础上的高度统一。PL/SQL 提供了实现和强制执行这些方面的坚实基础。另外,PL/SQL还支持面向对象编程,这能显著 地增加复用,因而能在降低开发成本的同时提升软件质量。

本章首先描述了为何及何时采用PL/SQL实现业务逻辑是一个不错的选择,然后解释了掌握大 规模PL/SQL编程成功的关键因素的几种方法。

在数据库中使用PL/SQL实现业务逻辑的优势:

·简单:大多数开发人员在一个单一层只需要用一种语言编写代码。他们能够独立编写 完整的业务功能而不必花费时间去协调与等待其他层的开发人员做好本职工作。此外,并 发模型使得可以很容易地开发与其它模块并行运行的程序。 ·性能:数据访问,包括批量操作,直接在数据库处理是最快的。这与Exadata的基本思 路是相同的,即:使加工/处理更接近数据,并只把最少量的数据通过网络发送。对于批量 处理这类OLTP银行系统的主要功能,所有的处理都可以在数据库进行。 ·安全:定义者权利的程序更容易确保未经授权的人不可以从数据库外部访问任何关键 信息。所有数据都可以驻留在锁定的模式中,并可以限制只有少数几个包可以从外部访问 这些数据。不需要授予直接访问表或视图的权限。如果业务逻辑在数据库外实现,那么会 有(至少在一段时间后)多个应用程序直接访问数据库。这使得一致的安全策略很难强制 执行。在应用服务器中存储的密码很容易被滥用在直接访问数据上。此外,在数据库?服 务器中的会话状态还可防止欺骗攻击。 ·一致性:我相信Oracle的读一致性。如果我不得不在中间层缓存同步负载很重的OLTP 活动的基础上显示实时的客户明细表,那么我不会睡得好。 ·任何环境下的可用性:许多应用程序需要与其它程序进行交互。任何语言都可以通过 JDBC,OCI,ODBC等调用存储过程。当然,这也是真正的Web服务。 ·在分布式事务中的参与:分布式事务对需要确保执行一次且仅执行一次的业务系统的 接口是至关重要的。借助Oracle的分布式事务,事务参与者设置是简单的并为大多数事务 协调器所支持。另一方面,在一个多厂商环境中如果通过Web服务或CORBA中间层的数据 库连接为任意接口建立/设置分布式事务,那简直是一个噩梦。 ·集中化,单层的部署:即使表和业务逻辑需要进行修改,大多数的改进和错误修正也 只需要修改一个层。 ·可扩展性:凭借功能更强大的服务器和真正应用集群(RAC),Oracle数据库的规模 可很适当地内部扩展或水平扩展。 ·稳定性和可靠性:Oracle数据库是一个非常稳定可靠的执行环境。

三层架构的大多数优点源于数据访问、业务逻辑和展现的逻辑分离而不是物理分离。逻辑分离, 并因此带来的好处,可以凭借数据库内的模块化实现,正如后面描述的那样。 存储过程可以用PL/SQL、Java、.NET或几乎任何程序语言作为外部过程编码。PL/SQL是我的首 选语言。

PL/SQL存储过程

PL/SQL是一种专门设计的无缝处理SQL所必须的3GL,为业务逻辑编码提供了额外的好处。

此外,基于版本的重新定义为PL/SQL代码与其他类型的对象提供了在线应用程序的升级。 PL/SQL还能在内存数据库TimesTen中运行,从而带来了与内存中缓存数据相同的优点,以实现 更高的性能。

Java存储过程

Java存储过程不能提供与PL/SQL的相同的SQL无缝集成。事实上,Java没有在图11-2中列出的 任何优点。此外,对Oracle 11gR2而言,在Java存储过程内调用SQL的性能比从PL/SQL调用或 在数据库外运行的Java调用差很多。考虑到数据库外的JDBC的表现是出色的,这很可能得到 改善。另一方面,在11g中,即时编译器的算法性能比PL/SQL更好,并且与数据库以外的Java 几乎相同。

如果PL/SQL无法完成某项工作,比如Oracle 10g之前的OS调用,或现有的Java库能大大简化工 作,那么Avaloq使用Java处理这些工作。例如,Avaloq安装工具使用Java检查ZIP文件的签名, 并且在数据库准备系统通过JDBC使用Java进行数据库之间的LOB传输,而不是通过数据库链 接使用PL/SQL,因为后者只在DDL中支持LOB,但不支持在DML中操作LOB。有许多库可 用,绝对是一个Java生态系统的实力。然而,这一事实往往被高估了。对于业务应用程序,往 往只有基础设施库是有用的,而即使是那些可能也是不够的。举例来说,任何Java记录框架都 不支持每个条目的安全性,把对相同的问题的记录调用分组到一个单一的条目或关于条目的工 作流程中。此外,不断出现的新库,可导致强迫最新框架采用障碍,这通常体现在一个单一的 产品中用了许多类似的库,因为对一个大型产品进行完全重构的努力是令人望而却步的。最后 但并非最不重要的一点是,PL/SQL中也配备了大量的库,在11gR2中,《PL/SQL包和类型参 考(PL/SQL Packages and Types Reference )》已增加到5,900页。

Java的一个好处是,可以在数据库中或在另一层运行相同的代码,如数据验证。后一种情况下 的另一种方法是由特定领域的语言生成PL/SQL和其他的语言代码。在Avaloq银行系统中,一 半以上的PL/SQL代码是由更高层次的特定领域语言生成的。

虽然Oracle允许开发人员在子程序的基础上,在PL/SQL和Java之间决定实现子程序(存储过程 或函数)的语言,但是我尽量避免产生难以维护的二者的胡乱组合。

Java存储过程,实际上是名不副实的。Oracle数据库包括一个完整的Java虚拟机(JVM)。因 此,它可能在任何几十种包含生成Java字节码编译器的语言中编写存储过程。从面向方面编程 的AspectJ到函数式编程的Scala,但是,这些语言没有任何一种支持(译者注:原文sport,怀 疑是support)无缝的SQL嵌入。

SQLJ是以预处理器为基础的Java扩展,它增加了简单的SQL集成和自动绑定变量的语法糖衣。 然而,它缺乏嵌入式SQL编译时检查和引用的对象的修改后自动对依赖失效的跟踪。自动验证 失效需要JVM的增强,而无法通过语言扩展补充。 SQLJ支持是参差不齐的。支持SQLJ的集成开发环境很少有。在原有的10g版本中,Oracle本身 不再支持SQLJ。但在客户投诉后,在10.1.0.4补丁集中SQLJ再次出现了。

基于.NET和C的外部程序

外部程序或子程序,因为它们在Oracle文档中是可互相替代的名称,是一个遵守PL/SQL调用规 范并用另一种语言实现的子程序。通过编写.NET存储过程,你就把自己限制在Windows上运 行的Oracle数据库上了。C语言编写,或可以从C调用的另一种语言的外部程序,都会妨碍可移 植性。此外,外部程序都在自己的进程中运行。因此,基于C的外部程序除了可以通过数据库 调用, 它们与中间层的业务逻辑相比没有明显的优势。

用数据库作为基于PL/SQL的应用程序服务器的的限制

如果你是一把锤子,那么一切看起来都像是钉子。另一方面,作为一个软件工程师,你应该知道 架构蓝图的适用性限制。在数据库中用PL/SQL描述业务逻辑的解决方案对数据为中心的ERP应用 是非常适合的,但它并不适合计算密集型的只需要很少的数据交互的应用程序。

此外,对于以下任务,PL/SQL不是我的第一选择:

·CPU密集型任务:PL/SQL的算法的性能比C和Java低。此外,应用PL/SQL有Oracle许 可成本。Java在商业应用服务器发生类似的许可证费用,而运行C或独立的Java程序无需运 行许可证。在Avaloq银行系统中,PL/SQL程序占了不足50%的CPU使用率,其余的CPU是 用在SQL上。 ·程序在内存中使用非常大的集合:PL/SQL集合会需要比等价的C集合明显更多的内 存。在本章后面会深入了解内存的使用。 ·非常复杂的数据结构:对大多数任务,使用PL/SQL集合与记录就足够了。然而,其余 的任务可以更容易地用包含泛型类型,内存中的引用,并自动进行垃圾收集的语言来表 达。

■ 注意:有时人们用供应商的独立性作为反对专有的存储过程语言的原因。这种说法是无效的, 因为大多数应用程序永远不会移植到另一个数据库,而且因为取得良好的性能和正确的并发处理 在不同的数据库需要多个具体实现,而没有单一的通用实现。Tom Kyte在《深入Oracle数据库体 系结构(Expert Oracle Database Architectures)》(Apress,2005年)一书中详细地描述了这一 点。我非常赞同他在该书这个主题中说的每一个字(虽然我不从Oracle公司领薪水)。这是两回 事,你可以不喜欢某个特定的数据库供应商,但是,你应该让你选择的数据库发挥最佳效用。

软因素

尽管Java可能比PL/SQL更有吸引力,但我发现雇用PL/SQL程序员比雇用同等的Java程序员不会 更难(可惜,也不更容易)。两种语言的学习曲线并没有太大的不同。PL/SQL是简单易学的。 对程序员,特别是新毕业生的大挑战是了解业务需求,学习大规模编程,掌握特定应用程序的框 架和模式,并编写有效的SQL。 如果是用Java编写的业务逻辑,那么SQL也是一个问题。当然,琐碎的SQL语句可以用对象关系 映射器生成。遵循一些简单模式的SQL语句在PL/SQL中也不成问题,但是复杂的语句,为了达 到最佳性能必须手工地编码。 在百万行代码应用程序的公司中,使新员工容易入门,是大规模编程成功的主要条件之一。