关于监控:如何查看实时MySQL查询?

How can I view live MySQL queries?

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

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


您可以很容易地将每个查询记录到日志文件中:

1
2
3
4
5
6
7
8
9
10
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

那就别忘了

1
mysql> SET GLOBAL general_log = 'OFF';

否则性能会下降,磁盘会满的!


您可以运行mysql命令SHOW FULL PROCESSLIST;,查看在任何给定时间处理的查询,但这可能无法实现您希望的结果。

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

但请注意,这可能会大大降低服务器上的速度,因为在每个查询的顶部都添加了一个额外的INSERT

编辑:另一种选择是常规的查询日志,但是将其写入平面文件会消除许多显示灵活性的可能性,特别是在实时显示方面。如果您只需要一种简单、易于实现的方法来查看正在发生的事情,那么启用GQL,然后在日志文件上运行tail -f,就可以做到这一点。


尽管已经接受了一个答案,我还是想提出一个最简单的选择:

1
$ mysqladmin -u bob -p -i 1 processlist

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

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

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

最好在快速检查正在运行的查询而不必设置侦听器或任何其他项时使用此选项。


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

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

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

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

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

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

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

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

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


我处于一种特殊的情况下,我没有打开日志的权限,并且如果打开了日志,就没有查看日志的权限。我无法添加触发器,但我有权调用Show ProcessList。所以,我尽了最大努力,想出了一个办法:

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

1
2
3
4
5
6
#!/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

执行脚本:

1
./showsqlprocesslist > showsqlprocesslist.out &

跟踪输出:

1
tail -f showsqlprocesslist.out

宾果邦戈。即使它没有节流,它只占用2-4%的CPU在我运行它的盒子上。我希望这能帮助别人。


埃多克斯1〔5〕

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

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

由于有许多转义字符,您可以将strace的输出通过管道(只需在这两个一行程序之间添加|)格式化到以下命令中:

1
2
3
4
5
grep --line-buffered -o '".\+[^"]"' | grep --line-buffered -o '[^"]*[^"]' | while read -r line; do printf"%b" $line; done | tr"

"
"\275\276" | tr -d"[:cntrl:]" | tr"\275\276""

"

因此,您应该在不接触配置文件的情况下,立即看到非常干净的SQL查询。

显然,这不会取代启用日志的标准方法,下面描述了这一点(这涉及到重新加载SQL Server)。

埃多克斯1〔8〕

使用mysql探针查看实时mysql查询,而不必接触服务器。示例脚本:

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

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

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

了解更多:开始使用dtracing mysql

吉布斯MySQL Spyglass

看看这个答案。

原木

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

将这些行添加到您的~/.my.cnf或global my.cnf中:

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

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

然后重新启动mysql/mariadb by(必要时前缀为sudo):

1
killall -HUP mysqld

然后检查日志:

1
tail -f /tmp/mysqld.log

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


这是我遇到的LinuxUbuntu机器上最简单的设置。疯狂地看到所有的疑问现场。

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

1
2
3
4
5
6
7
#
# * 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:

1
sudo /etc/init.d/mysql restart

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

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

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

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


从命令行可以运行:

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

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

或者更好:

1
 mysqladmin -u root -p -i 1 processlist;


查看MTOP。


我一直在寻找同样的方法,从不同的帖子中拼凑出一个解决方案,再加上创建了一个小的控制台应用程序,在将实时查询文本写入日志文件时输出它。在我的案例中,这一点很重要,因为我在MySQL中使用实体框架,我需要能够检查生成的SQL。

创建日志文件的步骤(为了简单起见,这里提供了其他日志的一些副本):

  • 编辑位于以下位置的文件:

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

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

  • 使用mysql workbench打开命令行,输入密码。

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

    1
    2
    3
    4
    5
    SET GLOBAL general_log = 'ON';

    To turn off:

    SET GLOBAL general_log = 'OFF';

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

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

    可在此处下载的源

    资料来源:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    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);
            }
        }
      }
    }


  • 除了前面描述如何启用常规日志记录的答案之外,在将任何SQL写入日志之前,我还必须在我的Vanilla MySQL5.6安装中修改一个附加变量:

    1
    SET GLOBAL log_output = 'FILE';

    默认设置为"无"。


    吉布斯MySQL Spyglass

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

    Github:Agildata/Gibbs MySQL Spyglass

    了解更多:用rust捕获mysql包

    安装命令:

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