是否有可能检查一个特定的查询打开MySQL中有多less文件?

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

我已经将open_files_limit设置为150000,但是MySQL仍然使用了将近80%

另外我有低stream量和最大并发连接30左右,没有查询有超过4个连接。

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

请参阅表performance_schema.file_instances。

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

至于跟踪哪个查询打开哪个文件,由于缓存在服务器本身(表缓存,表定义缓存)中,它不会以这种方式工作。

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

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

你将不得不建立一个自动化的测试,使之成为可能:

  • 记录您的查询;
  • 创建一个脚本,用一个正常的数据集预先装载你的堆(否则你正在测试空内存),打开表的数量的快照;
  • 运行每个查询并拍摄打开的表格的快照; (回想起来)我想你可以做到这一点,而无需每次重新启动MySQL,所以然后只是每个查询和记录结果。 调试是一项繁琐的工作:不是不可能的,只是非常乏味。

我个人会开始不同的:

  • 安装仙人掌和percona仙人掌插件
  • 注册一周的正常工作量
  • 然后搜索高负载查询(慢日志> 0.1秒,运行脚本查找重复查询)。
  • 另一周监测
  • 然后搜索更多的重复计数的查询:这通常是低效率的代码发射大量的查询,可以使用较少的(如检索键,然后每个键的每个键的所有值(一个接一个:会发生很多当程序员使用ORM)。

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

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

否则,可以通过针对所有MySQLd线程运行strace -c粗略估计table_cache的适当值(在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'es,并没有太多的左边。

如果你在Windows上运行,你将不得不尝试使用SysInternals的ProcMon或者类似的工具 。

一旦你有table_cache到可管理的级别,你的查询,现在打开太多的文件将关闭并重新打开许多这些相同的文件。 你可能会注意到对性能的影响,这很可能是微不足道的。 机会是,一个较小的表缓存实际上可以让你的结果更快 ,因为从一个现代的,快速的IOSS缓存中获取一个项目可能会比在一个非常大的缓存中搜索项目更快。

如果你正在优化你的服务器,你也可以看看这篇文章 。 外带是随着缓存的增加, 大的并不总是更好 (这也适用于索引)。

检查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 

…这些是查询使用的文件(*确保在“冷启动”MySQL上运行查询以防止缓存),并且我看到分配的最高文件句柄是39,因此在那里没有超过40个打开的文件。

可以从/ proc / $ PID / fd或从MySQL中检查相同的文件:

 select * from performance_schema.file_instances where open_count > 1; 

但是MySQL的计数稍微短一点,它不考虑套接字描述符,日志文件和临时文件。