龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 数据库类 > Oracle 技术 >

在复杂应用环境下监控 ORACLE 数据库性能(1)(3)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
2. 对投入运营的系统中 PHP 程序的监控 理想的开发流程是 设计 -> 文档 -> 编码 -> 测试 -> 投入使用,但实际运行的系统往往是由良莠不齐的程序所组成,有
2. 对投入运营的系统中 PHP 程序的监控

理想的开发流程是 设计 -> 文档 -> 编码 -> 测试 -> 投入使用,但实际运行的系统往往是由良莠不齐的程序所组成,有些缺乏文档,有些可读性差,有些程序极为脆弱。 对于这样的既成事实,如果系统中出现了瓶颈,不可能一条语句一条语句地来进行测试,只能是用一种统一的方法定位主要问题的所在。 由于 PHP 程序中的 SQL 语句使用了所谓动态 SQL 语句,即用 户可以在程序运行时动态生成一个 SQL 语句, 所以如果对静态的 PHP 程序文件 进行

( 如用 grep 工具 ) 可能会搜捕不到成形的完整 SQL 语句,这就要求用一种动态方法来拦截实际执行的每一个完整的 SQL 语句,观察 PHP 中关于 ORACLE 数据库操作的函数簇,发现 OCIParse 和 Ora_Parse 两个函数是 SQL 语句的入口,而将这两个函数统一替换为一个用户自定义的函数即可实现对 SQL 语句的拦截,在笔者涉入的实际系统中,是这样解决的 : 首先分析该系统中所有的 PHP 程序文件,发现凡涉及 ORACLE 数据库操作的都需要包含一个以 *.conf 结尾的配置文件,该配置文件是数据库的用户名,密码和连接标识符的定义文件,这些是开发初期定下的规范,以便于对程序中共用的配置信息进行统一的管理,以下是一个 oracle.conf

$oracle_user="oracle_user";

$oracle_password="oracle_password";

$oracle_dbid = "oracle_dbid";

?>

在涉及数据库操作的 PHP 程序中,总有一行语句以引入该配置文件 :

include("/oracle.conf");

设计一个函数如 debug_OCIParse 如下,以替换 OCIParse, 并将该文件放入一个叫 debug.conf 的别一个配置文件中,如下 :

oracle.conf:

global $impossible_conflit_with_this_oracle,$user,$password,$dbname;

if(!$impossible_conflit_with_this_oracle) require("/home/httpd/debug.conf");

$impossible_conflit_with_this_oracle=1;

$user="username";

$password="password";

$dbname="dblink";

?>

==========================================================

debug.conf:

==========================================================

function debug_OCIParse($debug_conn, $debug_sql, $filename, $line)

{

debug_WriteLog($debug_sql, $filename, $line);

return OCIParse($debug_conn, $debug_sql);

}

function debug_Ora_Parse($debug_conn, $debug_sql, $filename, $line)

{

debug_WriteLog($debug_sql, $filename, $line);

return Ora_Parse($debug_conn, $debug_sql);

}

function debug_WriteLog($debug_sql, $filename, $line)

{

#if(!strstr($filename,"message.phtml")) return;

$string = date("Y-m-d H:i:s")." $filename:$line\n\t$debug_sql\n";

$fp = fopen("/home/httpd/sql.log", "a");

fwrite($fp, $string, strlen($string));

fclose($fp);

}

?>

==========================================================

然后,统一将所有 PHP 程序中的 OCIParse 函数替换为 debug_OCIParse 函数,并要求 PHP 程序员以后使用 debug_OCIParse 函数进行开发,如下,将$stmt = OCIParse($conn, $sql); 替换为 :

$stmt = debug_OCIParse($conn, $sql, __FILE__, __LINE__);

这个工作可由系统管理员统一做一次,以后就要要求 PHP 程序员形成规范。 例,可用如下脚本

find /home/httpd/html -name '*.ph*' | xargs -n1 | while read i

do

ex -c ':se ic|g/ociparse/s/ociparse/debug_&/|s/);$/,__FILE__,__LINE__&/' -c ':x!' $i

done

这几行脚本并非放之皆准,但对于规范的 php 文件,一般来说没有问题,笔者的系统中用该方法维护几百 M 的 PHP 程序,少有例外,由于这是只运行一次的脚本,所以只要根据自己具体的系统做适当的调整即可,如上,如果对含有 OCIParse 的程序行的内容不太确定,可以用如下方法先进行查看 :

find /home/httpd/html -name '*.ph*' | xargs grep -in ociparse > ~/list

这段脚本中的 ex 命令稍作解释 :

ex 是 vi 编辑器的后端工具,可以在命令行上使用一些编辑命令,每个编辑命令以 -c 选项开头,如上

:se ic 是改变编辑器对大小写不敏感,全称是 :set ignorecase

| 号用来间隔多个编辑命令

g/ociparse/s/ociparse/debug_&/ 的编辑语意为 : 找到含有 ociparse 的行,对这些行执行如下编辑命令。

s/ociparse/debug_&/, s 意为 substitute, 将 ociparse 替换为 debug_&, 这其中 & 代表前面找到的匹配字符串,由于是忽略大小写的,所以用 & 来保留前面找到的不管是大小写如何混合的字符串的原型。 这样,ociparse 就会被替换为 debug_ociparse, 而 OCIParse 将会被替换为 debug_OCIParse.

接下来的 |s/);$/,__FILE__,__LINE__&/ 是将 ociparse 语句的右括号进行替换,将用于调试监控的两个参数 (PHP 中的宏 ) 加上,$ 不是指一个真正的字符,而是指一个特定的位置 -- 行尾,以避免无辜的 ); 被替换掉。

另一个命令 -c ':x!' 是将该文件存盘退出. 

打出这么一套组合拳需要你对这些命令了如指掌,如果你对某个文件没有写权,或出了其它岔子,那简直是一场灾难,这种魔法级的指令总是高风险的,搞不好会走火入魔,让你发下毒誓有生之年不再碰它。 所以谨慎与备份总是对的。

精彩图集

赞助商链接