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

上一篇 / 下一篇  2008-02-29 20:16:24 / 个人分类:技术文章

(如用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("<path_to_file>/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!'是将该文件存盘退出。

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


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-07-09  
  12345
6789101112
13141516171819
20212223242526
2728293031  

数据统计

  • 访问量: 55897
  • 日志数: 24223
  • 建立时间: 2007-12-06
  • 更新时间: 2008-06-15

RSS订阅

Open Toolbar