是否可以检查特定查询在 MySQL 中打开了多少个文件?

Is it possible to check that a particular query opens how many files in MySQL?

我在 MySQL 中有大量打开文件限制。

我已将 open_files_limit 设置为 150000 但 MySQL 仍然使用几乎 80 % 个。

此外,我的流量很低,最大并发连接数约为 30,并且没有查询超过 4 个连接。

这只能通过调整源代码并在该级别添加日志记录来实现。

备选方案:运行 使用此场景的测试:

您必须设置自动化测试才能实现此目的:

  • 记录您的查询;
  • 创建一个脚本,用普通数据集预加载您的堆(否则您正在针对空内存进行测试),拍摄打开表数量的快照;
  • 运行 每次查询并对打开的表进行快照; (回想起来)我认为你可以做到这一点而不必每次都重新启动 MySQL,因此只需每次查询并记录结果。调试是一项乏味的工作:并非不可能,只是非常乏味。

就个人而言,我会开始不同:

  • 安装 cacti 和 percona cacti 插件
  • 注册一周的正常工作量
  • 然后寻找高负载查询(慢日志 > 0.1 秒,运行 通过脚本查找重复查询)。
  • 再监测一周
  • 然后寻找具有高重复计数的其他查询:这通常是低效的代码,会触发大量查询,而可以使用的查询较少(例如检索键,然后检索每个键的每个键的所有值(一个通过一:程序员使用ORM时经常会出现这种情况。

服务器打开的文件在performance_schema中可见。

参见 table performance_schema.file_instances。

http://dev.mysql.com/doc/refman/5.5/en/file-instances-table.html

至于跟踪哪个查询打开了哪个文件,由于服务器本身的缓存(table 缓存,table 定义缓存),它无法那样工作。

MySQL 不应该打开那么多文件,除非你为 table_cache 参数设置了一个大得离谱的值(默认为 64,最大为 512K)。

您可以通过发出 FLUSH TABLES 命令来减少打开文件的数量。

否则,table_cache的适当值可以通过运行宁strace -c对所有MySQLd线程粗略估计(在Linux中)。你会得到类似的东西:

# strace -f -c -p $( pidof mysqld )
Process 13598 attached with 22 threads
[ ...pause while it gathers information... ]
^C
Process 13598 detached
...
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 58.82    0.040000          51       780           io_getevents
 29.41    0.020000         105       191        93 futex
 11.76    0.008000         103        78           select
  0.00    0.000000           0        72           stat
  0.00    0.000000           0        20           lstat
  0.00    0.000000           0        16           lseek
  0.00    0.000000           0        16           read
  0.00    0.000000           0         9         3 open
  0.00    0.000000           0         5           close
  0.00    0.000000           0         6           poll
...
------ ----------- ----------- --------- --------- ----------------

...看看 open() 和 close() 调用的影响是否存在合理差异;这些是 table_cache 影响的调用,它们会影响在任何给定点有多少打开的文件。

如果open()的影响可以忽略不计,那么一定要减少table_cache。它在慢速 IOSS 上最需要,而且剩下的不多了。

如果您 运行 正在使用 Windows,则必须尝试使用​​ ProcMon by SysInternals, or some similar tool

一旦您 table_cache 达到可管理的水平,您现在打开太多文件的查询将简单地关闭并重新打开许多相同的文件。您可能会注意到对性能的影响,这很可能可以忽略不计。有可能较小的 table 缓存实际上可能会让您得到 更快的结果 ,因为从现代、快速的 IOSS 缓存中获取项目可能比在真正的网络中搜索它更快大缓存。

如果您正在优化您的服务器,您可能还想看看 this article。要点是,随着缓存的发展,越大并不总是越好(它也适用于索引)。

检查 Linux

上的特定查询

在 Linux 上,您可以使用 strace(见上文)并验证打开了哪些文件以及如何打开:

$ sudo strace -f -p $( pidof mysqld ) 2>&1 | grep 'open("'

与此同时,我从另一个终端 运行 查询,并且:

[pid  8894] open("./ecm/db.opt", O_RDONLY) = 39
[pid  8894] open("./ecm/prof2_people.frm", O_RDONLY) = 39
[pid  8894] open("./ecm/prof2_discip.frm", O_RDONLY) = 39
[pid  8894] open("./ecm/prof2_discip.ibd", O_RDONLY) = 19
[pid  8894] open("./ecm/prof2_discip.ibd", O_RDWR) = 19
[pid  8894] open("./ecm/prof2_people.ibd", O_RDONLY) = 20
[pid  8894] open("./ecm/prof2_people.ibd", O_RDWR) = 20
[pid  8894] open("/proc/sys/vm/overcommit_memory", O_RDONLY|O_CLOEXEC) = 39

...这些是查询使用的文件(*一定要 运行 "cold-started" MySQL 上的查询以防止缓存),我看到分配的最高文件句柄是 39,因此打开的文件从未超过 40 个。

可以从 /proc/$PID/fd 或 MySQL:

检查相同的文件
select * from performance_schema.file_instances where open_count > 1;

但 MySQL 的计数略短,它没有考虑套接字描述符、日志文件和临时文件。