马永占,myz,mayongzhan

相当稳定的进步,欢迎回贴交流

用户操作
[即时聊天] [发私信] [加为好友]
myz
myz的公告

XML聚合
feedsky
最近评论
q32r:ok
waterFLY:所有的东西都有tostring(),是因为所有的类都继承自object,object有 toString();
790500:马永占,你好,请加我QQ790500,我想做个小软件,是关于登陆论坛的
joe:Zend_Acl 每个人理解不同,我开始用zf做项目,权限也是自己写,后来全部重写为Zend_Acl,因为个人觉得Zend_Acl和Zend_Auth结合用不错

Zend_Filter 虽然我写的model底层类的那些基本的过滤都是直接用php函数,毕竟速度快,也方便,但这个只是基础,很多时候不同表单牵涉不同的过滤,例如ip地址过滤等等,那么就需要自己写filter了,……
nginxlee:很好,很强大!
文章分类
收藏
    相册
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 分析MySQL查询记录 - 马永占 译收藏

    新一篇: PHPSPL,StandardPHPlibrary Module (SPL标准库) | 旧一篇: 网站统计系统内容分析

    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。http://blog.csdn.net/mayongzhan - 马永占,myz,mayongzhan

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

    调试现有的应用程序是很困难的。有时候,只是想要得到程序执行的数据库操作是否已经发送到数据库。可以使用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


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

     

     

    Observing the MySQL Query Log - ThinkPHP /dev/blog - PHP

    Debugging an existing application can be hard to bootstrap. Sometimes it just helps to observe the queries a web application is sending to the database. Unfortunately, the MySQL Query log does not directly tell the user which query goes to which database.
    I wanted to have a tail on the queries that go from an existing web application to a particular database. Since that was not the only database, and the MySQL query log does not support filtering, I hacked up a short awk script to solve the task for me. On the way, I did some reformatting to be better able to read the queries.

    The MySQL query log looks like this:
    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
    So we need to filter out the "Connect" line for all connections to the database in question and retrieve the connection id, then output all lines that reference that connection id. While we're at it, we also break up the SELECT line into multiple lines for readability.

    This is my awk script:
    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);
    }
    For those not familiar with awk: The manpage tells you everything that is neccessary to understand how it works. Awk takes a couple of patterns (BEGIN, and /pattern/ here) and earch line that matches a pattern is then referenced as $0 and the following block is executed. Parts of the line are then put into $1, $2 and so forth.

    What I do here:
    • The BEGIN rule looks at the arguments, so that the user can provide a database name on the commandline as "db=mydbname"
    • The Connect pattern grabs the connect lines and looks wether the correct line is referenced. It then looks whether the timestamp is omitted. After that it stores the connection id in an awk array
    • The Query pattern grabs all queries, and if the connection id is already in our array, it prints the query, reformatting it with newlines and tabs
    • The Quit pattern removes the connection ids from the array (Might not be neccessary since MySQL uses the ids in ascending order, but whatever :) )


    I stored the above script as ~/querylog.awk and added log=/data/mysql-queries.log in my.cnf
    tail -f /data/mysql-queries.log | awk -f ~/querylog.awk db=mydb_name


    Perhaps someone with similar needs might find use in my solution. Suggestions for improvement are welcome!

     

    发表于 @ 2008年03月03日 12:02:00|评论(loading...)|收藏

    新一篇: PHPSPL,StandardPHPlibrary Module (SPL标准库) | 旧一篇: 网站统计系统内容分析

    评论:没有评论。

    Csdn Blog version 3.1a
    Copyright © myz