Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->编程语言 ->PHP4/PHP5 ->正文

可扩展 可伸缩的 Oracle 与 PHP

来源: ORACLE 作者:webmaster 时间:2007-04-16 点击: [收藏] [投稿]

来自 MySQL 环境的用户可能试图避开持续连接(这是 MySQL 环境中的建议)。由 Oracle 影子进程启动所导致的栓锁和文件争用使得非持续连接的使用效率极低。那么解决方案是什么呢?

  • 应该确定我们的数据库能够支持多少个同时发生的会话,并相应地设置其限制。有些文章详细说明了怎么样完成此工作,但主要是一个计算过程:计算系统中物理内存的总量,并减去内核、支持程序和 Oracle 后台进程所使用的内存。然后减去所有被配置为 Oracle 共享内存的那些内存(共享池和缓冲区高速缓存)。剩下的内存可以用于影子进程。将该数量除以一个影子进程所使用的专用进程内存的平均数量(应该自己测出该数量,因为它根据您所运行的查询性质而变化),则我们得到可支持的进程数量。
  • 对我们的 Web 服务器进行配置,以便使其永远不能创建超过您的进程设置允许数量的连接。其实现方法是将每个 Web 服务器的 MaxChildren 可调参数设置得足够低,使得所有 Web 服务器总共拥有的子进程数量低于可支持的 Oracle 连接数。这意味着每个 Apache 实例不再支持 256 个子进程。
  • 重新设计我们的应用程序,使其不会遗漏额外的子进程。我们在后文中还会讨论这个话题。

这样有多重要?作为一个老板,我们即使启用了持续连接,也一直遇到栓锁问题。任何遇到过严重栓锁争用的人都能证实,这是一个极为严重的问题,服务器在很大程度上不响应,因为它花费过多时间来进行锁定操作。我们在调查中发现,尽管在终止前有大量进程为数以百计的请求提供服务,但很多进程只服务于单个请求。这一切是由于我们将 Apache 的 MaxSpareServers 设置得太低。我们所使用的负载均衡设备的一些问题导致了“突然爆发”的行为,此时 Web 服务器被多个同时发生的请求所冲击,然后闲置数秒时间。在 Apache 内部,这导致要创建额外的子进程,来为高请求等级提供服务;但当它一旦平息时(几乎立即平息),就会出现大部分目前处于闲置状态的子进程(终止进程并关闭其 Oracle 连接)。总体看来,这与运行非持续进程的效果相似。将 MaxSpareServers 设得较高就可消除此问题,并消除了栓锁争用。

执行 SQL

任何 Oracle 客户服务器关系的主要内容是执行查询。这里没有篇幅来谈论对查询的调整 — 那是需要整本书来讨论的主题。相反,我们将集中讨论怎么样尽可能地使已经调整过的查询高效运行。

使用 PHP 编写良好的 Oracle 应用程序代码的第一步是始终使用绑定 SQL。当我们编写类似以下的查询时:

SELECT * FROM USERS WHERE USERNAME = 'george'

Oracle 必须对该查询进行软分析,查看以前是否曾编译过该查询。在默认情况下,"george" 值被作为文字项,这意味着如果我们使用不同的名字 ('bob') 执行此查询,则 Oracle 将把它看作完全不同的查询。Oracle 在其共享池中保留它执行的每个查询的分析副本,因此如果您使用数千个名字来执行此查询,则在您的共享池中将有数千个该查询的不同副本。即使在轻度活跃的网站上,这也会导致严重的内存碎片以及 ORA-4031 错误增殖。

对这个问题的解决方案是使用绑定 SQL。绑定 SQL 允许我们将 WHERE 子句中的文字值替换为占位符,如下所示:

SELECT * FROM USERS WHERE USERNAME = ':NAME'

在这里,查询只须被完全分析一次(硬分析);以后所有的分析都是所谓的软分析,此时引擎只是简单地从 SGA 中提取已编译的查询。此外,将只有一个单次分析的副本被存储,从而显著减少了不断执行的查询对内存的需求。

现在我们可以执行如下:

<?php
$db = OCIPLogin('scott', 'tiger', 'testdb');
$stmt = OCIParse("SELECT * FROM USERS WHERE USERNAME = ':NAME'");
OCIBindByName($stmt, ":NAME", "george");
OCIExecute($stmt);
?>

在 Oracle8i 之前,我们必须手动绑定查询;从 8i 开始,通过设置 init.ora 的参数 "cursor_sharing = FORCE",我们可以指示优化器为我们完成这一工作。该设置通知优化器查找可以绑定的文字值,并手动执行绑定。自 9i 起,我们可以使用设置“cursor_sharing = SIMILAR”,该设置指示优化器深入查看基表的统计信息,了解自动绑定文字是否有好处(如果某个字段的分布极不均匀,则可能没有好处)。尽管应该启用这些设置(在 8i 中为 FORCE,在 9i 及更高版本中为 SIMILAR),但深入到查询中分析潜在绑定的这种操作对于优化器而言成本很高,因此在可能的情况下,应该手动绑定您的查询。

Oracle 客户服务器在 SQLNet 协议基础上运行,众所周知,这种协议的对话很多。例如,如果您执行一个返回 100 行的查询,则会有分析查询的对话交换、对每个绑定变量的交换、对执行的查询以及对每个提取行的查询。其中每次交换都包括客户端与服务器之间的网络数据包交换(称为一次往返)。减少往返次数可能具有深刻的性能影响。

解决这个问题的第一种方法是建立客户的预取缓冲区。在网络上传送单独一行的效率极低,因此最好主动将很多行集中在一起,并将它们从本地缓冲区中读出。如果我们将语句的句柄设置如下,则 Oracle 客户库能够自动执行这种服务:

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:使用 PHP 和 Oracle 开发企业应用程序   下一篇:PHP 5 数据对象 (PDO) 抽象层与 Oracle

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号