如何查看实时MySQL查询?

时间:2009-02-20 06:54:19

标签: mysql monitoring

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

例如,我喜欢设置某种类型的侦听器,然后请求网页并查看引擎执行的所有查询,或者只查看在生产服务器上运行的所有查询。我怎么能这样做?

12 个答案:

答案 0 :(得分:472)

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

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';

或性能将直线下降,您的磁盘将填满!

答案 1 :(得分:267)

您可以运行MySQL命令SHOW FULL PROCESSLIST;以查看在任何给定时间正在处理的查询,但这可能无法达到您所希望的目的。

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

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


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

答案 2 :(得分:172)

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

$ mysqladmin -u bob -p -i 1 processlist

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

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

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

当您想要检查正在运行的查询而不必设置监听器或其他任何内容时,最好使用此选项。

答案 3 :(得分:40)

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

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

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

您还可以添加条件,使其更具体,只需任何SQL查询。

e.g。显示运行5秒或更长时间的所有查询:

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

e.g。显示所有正在运行的UPDATE:

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

有关完整详情,请参阅:http://dev.mysql.com/doc/refman/5.1/en/processlist-table.html

答案 4 :(得分:17)

我处于一种特殊情况,即我无权打开登录,如果打开日志,则无权查看日志。我无法添加触发器,但我确实有权调用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

Bingo bango。即使它没有受到限制,它只占用了我运行它的盒子上2-4%的CPU。我希望这可能对某人有帮助。

答案 5 :(得分:16)

strace

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

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

由于存在大量转义字符,因此您可以通过管道(仅在这两个单行之间添加|format 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

Gibbs MySQL Spyglass

请参阅此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服务器:killall -HUP mysqld

答案 6 :(得分:15)

这是我遇到的Linux Ubuntu机器上最简单的设置。很难看到所有的查询。

在Ubuntu上找到并打开你的MySQL配置文件,通常是/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

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

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

答案 7 :(得分:13)

从命令行运行:

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;

答案 8 :(得分:12)

查看mtop

答案 9 :(得分:7)

我一直在寻找同样的方法,并拼凑了各种帖子的解决方案,并创建了一个小型控制台应用程序,以便在将其写入日志文件时输出实时查询文本。这在我的情况下很重要,因为我正在使用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);
            }
        }
      }
    }
    

答案 10 :(得分:1)

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

SET GLOBAL log_output = 'FILE';

默认设置为“无”'

答案 11 :(得分:0)

Gibbs 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