Можно ли проверить, что определенный запрос открывает количество файлов в MySQL?

У меня есть большое количество ограничений для открытых файлов в MySQL.

Я установил open_files_limit на 150000, но MySQL использует почти 80%.

Также у меня низкий трафик и максимальные одновременные соединения около 30, и ни один запрос не имеет более 4 подключений.

Ответ 1

Файлы, открытые сервером, видны в файле performance_schema.

См. таблицу performance_schema.file_instances.

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

Что касается отслеживания того, какой запрос открывает этот файл, он не работает таким образом из-за кэширования в самом сервере (кеш таблицы, кеш определения таблицы).

Ответ 2

Это было бы возможно только путем корректировки исходного кода и добавления журнала на этом уровне.

ALternative: выполните тест, используя этот сценарий:

Вам необходимо настроить автоматический тест, чтобы сделать это возможным:

  • Зарегистрируйте свои запросы;
  • Создайте script, который предварительно загружает вашу кучу с помощью обычного набора данных (иначе вы тестируете пустую память), сделайте снимок количества открытых таблиц;
  • Запускать каждый запрос и делать снимок открытых таблиц; (В ретроспективе) Я думаю, вы могли бы сделать это без перезапуска MySQL каждый раз, так что только каждый запрос и запись результатов. Отладка - утомительная работа: не невозможно, просто очень утомительно.

Лично я бы начал разные:

  • Установите плагин кактусов и percona cacti
  • Зарегистрировать неделю нормальной рабочей нагрузки
  • Затем выслеживайте запросы с высокой нагрузкой (медленный журнал > 0,1 секунды, запустите script, чтобы найти повторяющиеся запросы).
  • Еще одна неделя мониторинга
  • Затем выслеживайте дополнительные запросы с высоким количеством повторений: это часто неэффективный код, запускающий большое количество запросов, в которых меньше можно использовать (например, извлечение ключей, а затем все значения для каждого ключа на ключ (один за другим: Бывает много, когда программисты используют ORM).

Ответ 3

MySQL не должен открывать много файлов, если вы не установили смехотворно большое значение для параметра table_cache (по умолчанию 64, максимальный - 512 КБ).

Вы можете уменьшить количество открытых файлов, выполнив команду FLUSH TABLES.

В противном случае соответствующее значение table_cache можно приблизительно оценить (в Linux), выполнив strace -c для всех потоков MySQLd. Вы получаете что-то вроде:

# 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 от SysInternals или какой-то другой инструмент.

Когда у вас есть 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, point было более 40 открытых файлов.

Те же файлы можно проверить из /proc/ $PID/fd или из MySQL:

select * from performance_schema.file_instances where open_count > 1;

но счетчик MySQL немного короче, он не учитывает дескрипторы сокетов, файлы журналов и временные файлы.