如何在我的Linux服务器上跟踪MySQL查询?
例如,我想要设置某种侦听器,然后请求一个web页面并查看引擎执行的所有查询,或者只是查看在生产服务器上运行的所有查询。我该怎么做呢?
如何在我的Linux服务器上跟踪MySQL查询?
例如,我想要设置某种侦听器,然后请求一个web页面并查看引擎执行的所有查询,或者只是查看在生产服务器上运行的所有查询。我该怎么做呢?
当前回答
这是我所遇到的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/
其他回答
尽管答案已经被接受,但我想提出一个可能是最简单的选择:
$ mysqladmin -u bob -p -i 1 processlist
这将每秒钟在屏幕上打印当前查询。
-u执行命令的mysql用户名 -p提示输入你的密码(这样你就不必把它保存在一个文件中或让命令出现在你的命令历史中) i以秒为单位的间隔。 使用——verbose标志显示完整的进程列表,显示每个进程的整个查询。(谢谢,nmat)
这可能有一个缺点:如果快速查询在您设置的时间间隔之间运行,则可能不会显示。IE:我的间隔设置为1秒,如果有一个查询需要0.02秒才能运行,并且在间隔之间运行,您将看不到它。
当您希望快速检查正在运行的查询而无需设置侦听器或其他任何东西时,最好使用此选项。
斯特拉
查看实时MySQL/MariaDB查询的最快方法是使用调试器。在Linux上,你可以使用strace,例如:
sudo strace -e trace=read,write -s 2000 -fp $(pgrep -nf mysql) 2>&1
因为有很多转义字符,你可以通过管道将strace的输出格式化(只需在这两个一行程序之间添加|)到下面的命令中:
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服务器)。
目录
使用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)
了解更多信息:开始使用DTracing MySQL
Gibbs MySQL Spyglass
请看这个答案。
Logs
以下是对发展有用的步骤。
将这些行添加到~/.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 by(必要时加上sudo):
killall -HUP mysqld
然后检查你的日志:
tail -f /tmp/mysqld.log
完成后,将general_log更改为0(以便将来可以使用它),然后删除文件并重新启动SQL server: killall -HUP mysqld。
我处于一种特殊的情况,我没有打开日志的权限,如果日志被打开,我也没有查看日志的权限。我不能添加触发器,但我确实有权限调用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在我运行它的盒子上。我希望这能帮助到一些人。
你可以很容易地将每个查询记录到日志文件中:
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';
执行查询(在任何db上)。查看/var/run/mysqld/mysqld.log
那就别忘了
mysql> SET GLOBAL general_log = 'OFF';
否则,性能将急剧下降,磁盘将被填满!
我一直想做同样的事情,并从各种帖子中拼凑出了一个解决方案,再加上创建了一个小的控制台应用程序来输出实时查询文本,因为它被写入日志文件。这在我的情况下是重要的,因为我使用实体框架与MySQL,我需要能够检查生成的SQL。
创建日志文件的步骤(一些其他帖子的复制,这里都是为了简单起见):
Edit the file located at: C:\Program Files (x86)\MySQL\MySQL Server 5.5\my.ini Add "log=development.log" to the bottom of the file. (Note saving this file required me to run my text editor as an admin). Use MySql workbench to open a command line, enter the password. Run the following to turn on general logging which will record all queries ran: SET GLOBAL general_log = 'ON'; To turn off: SET GLOBAL general_log = 'OFF'; This will cause running queries to be written to a text file at the following location. C:\ProgramData\MySQL\MySQL Server 5.5\data\development.log Create / Run a console app that will output the log information in real time: Source available to download here Source: 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); } } } }