【问题标题】:How can I view live MySQL queries?如何查看实时 MySQL 查询?
【发布时间】:2010-10-08 18:54:44
【问题描述】:

如何在我的 Linux 服务器上跟踪 MySQL 查询?

例如,我想设置某种监听器,然后请求一个网页并查看引擎执行的所有查询,或者只查看在生产服务器上运行的所有查询。我该怎么做?

【问题讨论】:

  • 根据问题的严重程度,我强烈建议尝试 MySql Proxy。 B/c 它可以放置在应用服务器上,a)它是可扩展的,b)不必影响到数据库的所有流量。它处于“alpha”阶段,但已经存在很长时间了。 dev.mysql.com/downloads/mysql-proxy
  • 我已经改写了这个问题以省略对工具的任何引用。我认为这个问题在这里完全是主题,因为“我们是否正在运行我们应该进行的查询?”是调试数据库相关问题的第一步。
  • @MaasSql mysql 代理对 php 开发人员没有帮助,同时使用 PDO 作为查询并且值仅在服务器上绑定。

标签: mysql monitoring


【解决方案1】:

如果你想要监控和统计,那么有一个很好的开源工具Percona Monitoring and Management

但它是基于服务器的系统,启动起来也不是很简单。

它还有live demo system 用于测试。

【讨论】:

    【解决方案2】:

    吉布斯 MySQL 望远镜

    AgilData 最近推出了 Gibbs MySQL Scalability Advisor(一个免费的自助服务工具),它允许用户捕获要上传到 Gibbs 的实时查询流。 Spyglass(它是开源的)将监视您的 MySQL 服务器和客户端应用程序之间的交互。无需重新配置或重新启动 MySQL 数据库服务器(客户端或应用程序)。

    GitHub:AgilData/gibbs-mysql-spyglass

    了解更多:Packet Capturing MySQL with Rust

    安装命令:

    curl -s https://raw.githubusercontent.com/AgilData/gibbs-mysql-spyglass/master/install.sh | bash
    

    【讨论】:

    • Spyglass 似乎需要来自已关闭服务器的 API 密钥,最后一次提交是在 3 年前。不确定此产品是否仍受支持/工作。
    【解决方案3】:

    strace

    查看实时 MySQL/MariaDB 查询的最快方法是使用调试器。在 Linux 上可以使用strace,例如:

    sudo strace -e trace=read,write -s 2000 -fp $(pgrep -nf mysql) 2>&1
    

    由于有很多转义字符,您可以通过 pipingformat strace's output (只需在这两个单行之间添加|)到以下命令中:

    grep --line-buffered -o '".\+[^"]"' | grep --line-buffered -o '[^"]*[^"]' | while read -r line; do printf "%b" $line; done | tr "\r\n" "\275\276" | tr -d "[:cntrl:]" | tr "\275\276" "\r\n"
    

    因此,您应该会看到相当干净的 SQL 查询,无需接触配置文件。

    显然这不会取代启用日志的标准方式,如下所述(涉及重新加载 SQL 服务器)。

    dtrace

    使用 MySQL 探针查看实时 MySQL 查询,而无需接触服务器。示例脚本:

    #!/usr/sbin/dtrace -q
    pid$target::*mysql_parse*:entry /* This probe is fired when the execution enters mysql_parse */
    {
         printf("Query: %s\n", copyinstr(arg1));
    }
    

    将上述脚本保存到文件(如watch.d),然后运行:

    pfexec dtrace -s watch.d -p $(pgrep -x mysqld)
    

    了解更多:Getting started with DTracing MySQL

    吉布斯 MySQL 望远镜

    看到这个answer

    日志

    以下是对开发建议有用的步骤。

    将这些行添加到您的~/.my.cnf 或全局my.cnf

    [mysqld]
    general_log=1
    general_log_file=/tmp/mysqld.log
    

    路径:/var/log/mysqld.log/usr/local/var/log/mysqld.log 也可能根据您的文件权限起作用。

    然后重启您的 MySQL/MariaDB(如有必要,使用 sudo 前缀):

    killall -HUP mysqld
    

    然后检查您的日志:

    tail -f /tmp/mysqld.log
    

    完成后,将general_log更改为0(以便以后使用),然后删除文件并重新启动SQL Server:killall -HUP mysqld

    【讨论】:

    • 如果从 MySQL 查询中设置 general_log,则无需终止服务器。它将开始写入general_log_file 指向的文件。
    【解决方案4】:

    即使答案已经被接受,我还是想提出一个可能是最简单的选择:

    $ mysqladmin -u bob -p -i 1 processlist
    

    这将每秒在您的屏幕上打印当前查询。

    • -u你要执行命令的mysql用户
    • -p 提示您输入密码(因此您不必将其保存在文件中或让命令出现在命令历史记录中)
    • i 以秒为单位的时间间隔。
    • 使用--verbose 标志显示完整的进程列表,显示每个进程的完整查询。 (谢谢nmat

    有一个可能的缺点:如果快速查询在您设置的时间间隔内运行,它们可能不会显示。 IE:我的间隔设置为一秒,如果有一个查询需要.02 秒才能运行并且在间隔之间运行,您将看不到它。

    当您想要快速检查正在运行的查询而不需要设置侦听器或其他任何东西时,最好使用此选项。

    【讨论】:

    • 这是最好的解决方案!
    • 在我看来这是更好的解决方案,因为不要每次都使用新的mysql连接来发送命令,而是打开一个mysql连接并使用它来发送显示进程列表;
    • @JoseNobile 如果您在适配器中保持 mysql 连接打开,这并不重要。我的解决方案不完全适合 OP,因为我的解决方案还没有准备好在适配器中使用。然而,它又快又容易。
    • 您可以添加--verbose查看完整查询
    • 这是我一直在寻找的答案。它应该被接受为答案。这也是最容易实现的答案。
    【解决方案5】:

    您可以运行 MySQL 命令SHOW FULL PROCESSLIST; 以查看在任何给定时间正在处理哪些查询,但这可能无法实现您的期望。

    无需修改使用服务器的每个应用程序即可获取历史记录的最佳方法可能是通过触发器。您可以设置触发器,以便每个查询运行都会导致查询被插入到某种历史记录表中,然后创建一个单独的页面来访问此信息。

    请注意,这可能会大大减慢服务器上的所有内容,在每个查询的顶部添加一个额外的 INSERT


    编辑:另一种选择是General Query Log,但将其写入平面文件会消除很多显示灵活性的可能性,尤其是实时显示。如果您只是想要一种简单、易于实现的方式来查看发生了什么,启用 GQL,然后在日志文件上运行 tail -f 就可以了。

    【讨论】:

    • 这听起来可能很傻,但我究竟该如何启用 GQL?我添加了 log_output=file、general_log=1 和 general_log_file=/pathtofile,并跟踪了日志文件,点击了站点,却一无所获。我做错了什么?
    • 我无法确定任何事情,但请确保您重新启动了服务器,并且您选择的文件是 mysql 可以写入的文件。
    • 我已经弄明白了——我在 my.cnf 中需要的只是 log=/path/to/log 然后我只是做了尾巴,它显示了所有的查询。
    • 据我所知,没有办法触发 SELECT 语句中的任何内容。触发器仅适用于 INSERT、UPDATE、DELETE... 还是我被误导了?
    • 我之前也在同一个地方。目前,我正在使用Monyog,它以非常少的开销完成所有这些工作,因此没有任何速度减慢。
    【解决方案6】:

    您可以非常轻松地将每个查询记录到日志文件中:

    mysql> SHOW VARIABLES LIKE "general_log%";
    
    +------------------+----------------------------+
    | Variable_name    | Value                      |
    +------------------+----------------------------+
    | general_log      | OFF                        |
    | general_log_file | /var/run/mysqld/mysqld.log |
    +------------------+----------------------------+
    
    mysql> SET GLOBAL general_log = 'ON';
    

    做你的查询(在任何数据库上)。 grep 或以其他方式检查 /var/run/mysqld/mysqld.log

    那别忘了

    mysql> SET GLOBAL general_log = 'OFF';
    

    否则性能会一落千丈,你的磁盘会被填满!

    【讨论】:

    • 好答案!您可以使用tail -f -n300 /var/run/mysqld/mysqld.log 来实时跟踪您的日志文件
    • 请注意,这些变量需要 MySQL 5.1.12 或更高版本。在此之前,您必须重新启动 MySQL 才能更改这些设置。
    • 有没有办法让参数化的变量写入日志?我看到的是SELECT name FROM person where id=?,但我不知道id 是什么。
    • 重要 - 您必须使用 SHOW VARIABLES LIKE "log_output%" 检查日志输出。如果设置为table,那么日志将被保存到数据库本身,表mysql.general_log不在文件系统中。您可以将其更改为 fileSET GLOBAL log_output = 'file';
    • 很好的答案。 +1 警告关闭日志:)
    【解决方案7】:

    您可以从命令行运行:

    watch --interval=[your-interval-in-seconds] "mysqladmin -u root -p[your-root-pw] processlist | grep [your-db-name]"
    

    将值 [x] 替换为您的值。

    甚至更好:

     mysqladmin -u root -p -i 1 processlist;
    

    【讨论】:

    • 这实际上是一个非常好的 sn-p,可能会派上用场.. 谢谢!
    • 正是我想要的!手表需要单独安装。
    【解决方案8】:

    运行这个方便的 SQL 查询来查看正在运行的 MySQL 查询。它可以在您喜欢的任何环境中随时运行,无需任何代码更改或开销。它可能需要一些 MySQL 权限配置,但对我来说,它无需任何特殊设置即可运行。

    SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep';
    

    唯一的问题是您经常会错过执行速度非常快的查询,因此它对于运行时间较长的查询或 MySQL 服务器有正在备份的查询最有用 - 根据我的经验,这正是我想要的时间查看“实时”查询。

    您还可以添加条件以使其更具体,就像任何 SQL 查询一样。

    例如显示所有运行 5 秒或更长时间的查询:

    SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME >= 5;
    

    例如显示所有正在运行的更新:

    SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND INFO LIKE '%UPDATE %';
    

    详情请见:http://dev.mysql.com/doc/refman/5.1/en/processlist-table.html

    【讨论】:

      【解决方案9】:

      除了之前描述如何启用常规日志记录的答案之外,在将任何 SQL 写入日志之前,我必须在我的 vanilla MySql 5.6 安装中修改一个额外的变量:

      SET GLOBAL log_output = 'FILE';
      

      默认设置为“无”。

      【讨论】:

        【解决方案10】:

        这是我在 Linux Ubuntu 机器上遇到的最简单的设置。很高兴看到所有的查询都是实时的。

        找到并打开您的 MySQL 配置文件,通常是 Ubuntu 上的 /etc/mysql/my.cnf。查找“日志记录和复制”部分

        #
        # * Logging and Replication
        #
        # Both location gets rotated by the cronjob.
        # Be aware that this log type is a performance killer.
        
        log = /var/log/mysql/mysql.log
        

        只需取消注释“log”变量即可打开日志记录。用这个命令重启 MySQL:

        sudo /etc/init.d/mysql restart
        

        现在我们已准备好在查询进入时开始监视它们。打开一个新终端并运行此命令以滚动日志文件,并在必要时调整路径。

        tail -f /var/log/mysql/mysql.log
        

        现在运行您的应用程序。您将在终端窗口中看到数据库查询开始飞来飞去。 (确保您在终端上启用了滚动和历史记录)

        来自http://www.howtogeek.com/howto/database/monitor-all-sql-queries-in-mysql/

        【讨论】:

          【解决方案11】:

          我一直在寻找同样的方法,并从各种帖子中拼凑出一个解决方案,并创建了一个小型控制台应用程序来输出写入日志文件的实时查询文本。这对我来说很重要,因为我将实体框架与 MySQL 一起使用,并且我需要能够检查生成的 SQL。

          创建日志文件的步骤(与其他帖子有些重复,为了简单起见,都在这里):

          1. 编辑文件位于:

            C:\Program Files (x86)\MySQL\MySQL Server 5.5\my.ini
            

            在文件底部添加“log=development.log”。 (注意保存这个文件需要我以管理员身份运行我的文本编辑器)。

          2. 使用MySql工作台打开命令行,输入密码。

            运行以下命令以打开常规日志记录,该日志记录将记录所有运行的查询:

            SET GLOBAL general_log = 'ON';
            
            To turn off:
            
            SET GLOBAL general_log = 'OFF';
            

            这将导致正在运行的查询被写入以下位置的文本文件。

            C:\ProgramData\MySQL\MySQL Server 5.5\data\development.log
            
          3. 创建/运行将实时输出日志信息的控制台应用程序:

            Source available to download here

            来源:

            using System;
            using System.Configuration;
            using System.IO;
            using System.Threading;
            
            namespace LiveLogs.ConsoleApp
            {
              class Program
              {
                static void Main(string[] args)
                {
                    // Console sizing can cause exceptions if you are using a 
                    // small monitor. Change as required.
            
                    Console.SetWindowSize(152, 58);
                    Console.BufferHeight = 1500;
            
                    string filePath = ConfigurationManager.AppSettings["MonitoredTextFilePath"];
            
                    Console.Title = string.Format("Live Logs {0}", filePath);
            
                    var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            
                    // Move to the end of the stream so we do not read in existing
                    // log text, only watch for new text.
            
                    fileStream.Position = fileStream.Length;
            
                    StreamReader streamReader;
            
                    // Commented lines are for duplicating the log output as it's written to 
                    // allow verification via a diff that the contents are the same and all 
                    // is being output.
            
                    // var fsWrite = new FileStream(@"C:\DuplicateFile.txt", FileMode.Create);
                    // var sw = new StreamWriter(fsWrite);
            
                    int rowNum = 0;
            
                    while (true)
                    {
                        streamReader = new StreamReader(fileStream);
            
                        string line;
                        string rowStr;
            
                        while (streamReader.Peek() != -1)
                        {
                            rowNum++;
            
                            line = streamReader.ReadLine();
                            rowStr = rowNum.ToString();
            
                            string output = String.Format("{0} {1}:\t{2}", rowStr.PadLeft(6, '0'), DateTime.Now.ToLongTimeString(), line);
            
                            Console.WriteLine(output);
            
                            // sw.WriteLine(output);
                        }
            
                        // sw.Flush();
            
                        Thread.Sleep(500);
                    }
                }
              }
            }
            

          【讨论】:

          • 这看起来很酷,我一定会看一看,很高兴把它作为一个 OSS 项目并创建一个分析工具!
          • 我认为这是个好主意。我在谷歌代码上放了一个 SVN 回购。可能是有史以来最小的操作系统项目,但到目前为止这非常有用。我可能会扩展它,有兴趣看看其他人是否更进一步。 code.google.com/p/livelogs
          • OP 需要它在他的 Linux 机器上工作。看起来您的答案适用于 Windows 机器。虽然这个答案反映了创造力,但可能对其他人没有帮助。
          【解决方案12】:

          我处于一种特殊情况,我无权打开登录,并且如果日志打开,我也无权查看日志。我无法添加触发器,但我确实有权调用 show processlist。所以,我尽了最大的努力,想出了这个:

          创建一个名为“showsqlprocesslist”的 bash 脚本:

          #!/bin/bash
          
          while [ 1 -le 1 ]
          do
                   mysql --port=**** --protocol=tcp --password=**** --user=**** --host=**** -e "show processlist\G" | grep Info | grep -v processlist | grep -v "Info: NULL";
          done
          

          执行脚本:

          ./showsqlprocesslist > showsqlprocesslist.out &
          

          拖尾输出:

          tail -f showsqlprocesslist.out
          

          宾果游戏。即使它没有受到限制,它也只占用了我运行它的机器上 2-4% 的 CPU。我希望这可能对某人有所帮助。

          【讨论】:

          • 哈!美味的。喜欢它。
          • 它需要一些延迟以避免过多的冗长输出。请参阅我的编辑。
          • @Slyx 感谢在循环中设置睡眠的建议。但是,如果您正在寻找比睡眠时间更短的短期查询,您可能会错过您正在寻找的内容。如果您真的只是在寻找及时的快照,则不应循环运行。还应该注意的是,这仍然可能会错过非常短暂的查询。
          【解决方案13】:

          查看mtop

          【讨论】:

          • 是的,但祝你在 Debian 或 Ubuntu 上安装它好运:bugs.launchpad.net/ubuntu/+source/mtop/+bug/77980
          • 设法让它在 debian 上运行,但它有点毫无价值,因为它错过了很多查询。我可以看到查询计数器不断上升,但它很少显示任何查询。看起来它只显示耗时超过 1 秒的查询。
          • @Cobra_Fast 在 mtop Sourceforge 页面上明确说明:mtop (MySQL top) monitors a MySQL server showing the queries which are taking the most amount of time to complete. mtop.sourceforge.net 有时非常有用。
          猜你喜欢
          • 1970-01-01
          • 2014-05-21
          • 2011-11-10
          • 2013-02-22
          • 2013-06-28
          • 2013-11-19
          • 1970-01-01
          • 1970-01-01
          • 2016-02-11
          相关资源
          最近更新 更多