home 首页 » 精彩日志 » 日志查看

分析MySQL查询记录

原文地址:http://blog.thinkphp.de/archives/303-Observing-the-MySQL-Query-Log.html

mayongzhan 译
 2008-02-29 19:40:15 

调试现有的应用程序是很困难的。有时候,只是想要得到程序执行的数据库操作是否已经发送到数据库。可以使用MySQL查询日志,不幸的是, MySQL查询日志不直接告诉使用者查询到哪些数据库。

我要得到最近几条程序执行的查询。因为这个程序不是这个数据库唯一的程序,而且MySQL查询记录不支持过滤,我使用一个awk的脚本来自己进行过滤。我做了一些格式化,以便能更好的阅读。

MySQL查询记录格式如下:

080228 15:27:50   1170 Connect     user@host on database_name
1170 Query SET NAMES "utf8"
1170 Query SELECT something FROM sometable WHERE some=thing
1170 Quit
我们需要过滤出Connect那行的含有我定义的数据库名称的那组结果。当然还要对SELECT进行一下格式化。

 

 

我的awk脚本:
BEGIN { 
mydb = "default_database";
if (ARGC == 2 && substr(ARGV[1],0,3)=="db=") {
mydb = substr(ARGV[1],4);
printf("my db %s\n",mydb);
}
}
/[0-9]* Connect/ {
if(index($0,mydb)==0) {
#printf("not using %s\n",$0);
} else {
if($2 == "Connect") {
what=$1;
} else {
what=$3;
}
print;
conns[what]="true";
}
}
/[0-9]* Query/ {
if(conns[$1]=="true") {
printf("% 4s %s : ",$1,$2);
for(i=3; i<=NF; i++){
if ($i == "FROM") printf("\n\t\t");
else if ($i == "WHERE") printf("\n\t\t");
else if ($i == "GROUP") printf("\n\t\t");
else if ($i == "HAVING") printf("\n\t\t");
else if ($i == "ORDER") printf("\n\t\t");
else if ($i == "LIMIT") printf("\n\t\t");
else if ($i == "AND") printf("\n\t\t\t"); # AND clauses are indented one level deeper
gsub(",",",\n\t\t\t",$i); # selected fields are also indented deeper
printf("%s ",$i);
}
printf("\n");
}
}
/[0-9]* Quit/ {
delete conns[$1];
printf("deleting %s\n",$1);
}

 

对那些不熟悉awk的用户:了解awk的使用就可以了。使用BEGIN作为开始,然后执行内部语句,当遇到$0,$1,$2时,相应执行相关的正则匹配。

如下:

  • BEGIN这块,得到一个参数为db=mydbname。
  • Connect匹配,是否为我们所需要的部分,把需要的部分保存在数组中。
  • Query匹配所有查询语句,然后在数组中查询判断是否为我们需要的。是的话,就格式化然后输出查询。
  • Quit从数组中删除Connect,然后输出。


  把上面的awk脚本保存为~/querylog.awk,然后在my.cnf中添加 log=/data/mysql-queries.log
tail -f /data/mysql-queries.log | awk -f ~/querylog.awk db=mydb_name


或许有人有类似的需求,会使用我的解决方案,当然也可能发现一些问题。欢迎提出改进意见。

收藏到网摘:

 
暂无评论
发表评论:
大名:*
网址:   http://sitename
评论:*