MySQL создает временные таблицы на диске. Как мне это остановить?

27

Мы запустили сайт (Moodle), который в настоящее время пользователи находят медленным. Я думаю, что отследил проблему, создав MySQL временные таблицы на диске. Я наблюдаю переменную created_tmp_disk_tablesв администрировании сервера Mysql Workbench, и ее число увеличивается примерно на 50 таблиц / с. После дней использования created_tmp_disk_tables> 100k. Кроме того, память, кажется, не освобождается. Использование продолжает расти, пока система не станет в значительной степени непригодной для использования, и мы должны перезапустить MySQL. Мне нужно перезапускать его почти каждый день, и он начинается с использования около 30-35% доступной памяти и заканчивает день с 80%.

У меня нет блобов в базе данных и нет контроля над запросами, поэтому я не могу попытаться оптимизировать их. Я также использовал Percona Confirguration Wizard для создания файла конфигурации, но my.ini также не решил мою проблему.

Вопросов

  1. Что я должен изменить, чтобы MySQL не создавал временные таблицы на диске? Есть ли настройки, которые мне нужно изменить? Должен ли я бросить больше памяти на это?

  2. Как я могу остановить MySQL от потребления моей памяти?

редактировать

Я включил slow_queriesжурнал и обнаружил, что запрос SELECT GET_LOCK()был зарегистрирован как медленный. Быстрый поиск показал, что я разрешил постоянные соединения в конфигурации PHP ( mysqli.allow_persistent = ON). Я выключил это. Это уменьшило скорость, с которой MySQL потребляет память. Хотя он все еще создает временные таблицы.

Я также проверил, что key_buffer sizeэто достаточно большой. Я посмотрел на переменную key_writes. Это должно быть ноль. Если нет, увеличьте. У key_buffer_sizeменя есть ноль key_readsи ноль, key_writesпоэтому я предполагаю, что key_buffer_sizeон достаточно велик.

Я увеличил tmp_table_sizeи max-heap-table-sizeдо 1024M, так как увеличение созданных_данных_данных может указывать на то, что таблицы не помещаются в памяти. Это не решило это.

Ссылка: http://www.mysqlperformanceblog.com/2007/08/16/how-much-overhead-is-caused-by-on-disk-teilitary-tables/

Редактировать 2

Если вы видите много sort_merge_passesв секунду в выходных данных SHOW GLOBAL STATUS, вы можете рассмотреть возможность увеличения sort_buffer_sizeзначения. У меня было 2 sort_merge_passesв час, поэтому я считаю, что sort_buffer_sizeдостаточно большой.

Ссылка: Mysql Руководство по sort_buffer_size

Редактировать 3

Я изменил буферы сортировки и объединения в соответствии с предложением @RolandoMySQLDBA. Результат отображается в таблице ниже, но я думаю, что created_tmp_tables_on_diskона все еще высока. Я перезапустил сервер mysql после того, как изменил значение и проверил значение created_tmp_tables_on_diskчерез день (8 часов) и вычислил среднее значение. Любые другие предложения? Мне кажется, что что-то не подходит внутри какого-то контейнера, но я не могу понять, что это такое.

+---------------------+-------------+-------------+--------------------+
| Tmp_table_size,     | Sort_buffer | Join_buffer | No of created      |
| max_heap_table_size |             |             | tmp_tables on disk |
+---------------------+-------------+-------------+--------------------+
| 125M                | 256K        | 256K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 512K        | 512K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 1M          | 1M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 4M          | 4M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+   



Это моя конфигурация:

+-----------------------+-----------------------+
|DATABASE SERVER        |WEB SERVER             |
+-----------------------+-----------------------+
|Windows Server 2008 R2 |Windows Server 2008 R2 |
+-----------------------+-----------------------+
|MySQL 5.1.48           |IIS 7.5                |
+-----------------------+-----------------------+
|4 Core CPU             |4 Core CPU             |
+-----------------------+-----------------------+
|4GB RAM                |8GB RAM                |
+-----------------------+-----------------------+

Дополнительная информация

+--------------------+---------+
|PARAM               |VALUE    |
+--------------------+---------+
|Num of tables in Db |361      |
+--------------------+---------+
|Size of database    |2.5G     |
+--------------------+---------+
|Database engine     |InnoDB   |
+--------------------+---------+
|Read/write ratio    |3.5      |
|(Innodb_data_read/  |         |
|innodb_data_written)|         |
+--------------------+---------+
|Avg table size      |15k rows |
+--------------------+---------+
|Max table size      |744k rows|
+--------------------+---------+

Эта настройка была дана мне, поэтому я ограничил контроль над ней. Веб-сервер использует очень мало ЦП и ОЗУ, поэтому я исключил эту машину как узкое место. Большинство настроек MySQL происходит из инструмента автоматической генерации конфигурации.

Я наблюдал за системой, используя PerfMon в течение нескольких представительных дней. Исходя из этого, я делаю вывод, что не ОС загружает диск.

My.ini

[client]
port=3306
[mysql]
default-character-set=utf8

[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.1/"
datadir="D:/DBs/Data/"
default-character-set=utf8
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=125
query_cache_size=350M
table_cache=1520
tmp_table_size=125M
table-definition-cache= 1024
max-heap-table-size= 32M
thread_cache_size=38

MyISAM Specific options
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=125M
key_buffer_size=55M
read_buffer_size=1024K
read_rnd_buffer_size=256K
sort_buffer_size=1024K
join_buffer_size=1024K


INNODB Specific options
innodb_data_home_dir="D:/DBs/"
innodb_additional_mem_pool_size=32M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=16M
innodb_buffer_pool_size=2G
innodb_log_file_size=407M
innodb_thread_concurrency=8
user30431
источник
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Пол Уайт говорит GoFundMonica

Ответы:

16

Глядя на my.iniменя, у меня есть два предложения

ПРЕДЛОЖЕНИЕ № 1

Я бы поднял следующие настройки в вашем my.ini

sort_buffer_size=4M
join_buffer_size=4M

Это сделает несколько соединений и останется в памяти. Конечно, если a JOINили a ORDER BYнужно больше 4M, он будет перенаправлять на диск в виде таблицы MyISAM.

Если вы не можете войти как root@localhost, то перезапустите mysql с

C:\> net stop mysql
C:\> net start mysql

Если вы можете войти в систему как root @ localhost, вам не нужно перезапускать mysql, чтобы использовать эти настройки.

Просто запустите это в клиенте MySQL:

SET @FourMegs = 1024 * 1024 * 4;
SET GLOBAL sort_buffer_size = @FourMegs;
SET GLOBAL join_buffer_size = @FourMegs;

ПРЕДЛОЖЕНИЕ № 2

Поскольку ваши данные находятся на диске D:, у вас может быть дисковый ввод-вывод на диске C:.

Пожалуйста, запустите этот запрос:

mysql> show variables like 'tmpdir';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tmpdir        | C:\Windows\TEMP |
+---------------+-----------------+
1 row in set (0.00 sec)

Поскольку я запускаю mysql на рабочем столе с настройками по умолчанию, мои временные таблицы записываются на диск C:. Если Drive D лучший диск , чем Drive C:, возможно , вы можете отобразить временные таблицы на Диске D:, установив TMPDIR в my.iniследующим образом :

tmpdir="D:/DBs/"

Вам придется перезапустить mysql, поскольку tmpdir не является динамической переменной.

Попробуйте!

ОБНОВЛЕНИЕ 2013-11-29 10:09 EST

ПРЕДЛОЖЕНИЕ № 3

Учитывая тот факт, что MySQL работает в Windows, и вы не можете касаться запросов в основном пакете, у меня есть две идеи, которые нужно сделать вместе.

IDEA # 1: переместить базу данных на компьютер с Linux

Ты должен быть способен

  • Настройте машину Linux
  • Установите MySQL на машину с Linux
  • Включить двоичное ведение журнала для MySQL в Windows
  • mysqldump базы данных в текстовый файл SQL
  • Загрузить файл SQL в MySQL, работающий в Linux
  • Настройка репликации из MySQL / Windows в MySQL / Linux

IDEA # 2: перенастроить Moodle, чтобы он указывал на Linux-машину

Moodle был разработан для LAMP в первую очередь. Просто измените конфигурационные файлы так, чтобы они указывали на машину с Linux, а не на localhost.

Вот ссылка на старый документ Moodle 2.3 по настройке MySQL: http://docs.moodle.org/23/en/Install_Moodle#Create_an_empty_database

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

Какой смысл переносить базу данных в Linux ???

Как это помогает ситуации с временными таблицами ???

Затем я бы предложил установить RAM-диск в качестве целевой папки для ваших временных таблиц.

Создание временной таблицы все еще будет происходить, но она будет записана в ОЗУ, а не на диск. сокращение дискового ввода-вывода.

ОБНОВЛЕНИЕ 2013-11-29 11:24 EST

ПРЕДЛОЖЕНИЕ № 4

Я бы предложил пересмотреть SUGGESTION # 2 с быстрым диском RAID-0 (32+ ГБ), настроив его как диск T: (T для Temp). После установки такого диска добавьте это в my.ini:

[mysqld]
tmpdir="T:\"

MySQL перезапуск потребуется, используя

net stop mysql
net start mysql

Кстати, я сказал RAID-0 специально, чтобы вы могли получить хорошую производительность записи по RAID-1, RAID-10. Настольный диск tmp - это не то, что я бы сделал избыточным.

Без оптимизации запросов, которые комментирует @RaymondNijland, вы никоим образом не можете уменьшить количество созданных временных таблиц. SUGGESTION #3и SUGGESTION #4предложить ускорение создания временной таблицы и ввода-вывода временной таблицы в качестве единственной альтернативы.

RolandoMySQLDBA
источник
13

Я отвечаю на свой вопрос здесь для полноты

Я выберу @RolandoMySQLDBA в качестве предпочтительного ответа, потому что он дал мне большинство советов, хотя на самом деле это не решило мою проблему.

Ниже приведены результаты моего расследования

Вывод

MySQL на Windows просто создает множество временных таблиц, и настройка MySQL путем изменения содержимого файлов конфигурации не помогла.

Детали

В таблице приведены параметры, которые я изменил в my.ini соответственно перед выполнением любых запросов. MySQL был перезапущен между каждым тестом.

Я использовал my.ini, найденный в исходном вопросе, в качестве шаблона, а затем изменил значение параметров один за другим в соответствии с таблицей ниже.

Я использовал JMeter для генерации 100 одновременных веб-запросов (которые представляли наше использование), повторенных 10 десять раз. TestТаким образом, каждый состоит из 1000 запросов. Это привело к последующим вызовам базы данных. Это показало, что MySQL будет создавать много временных таблиц независимо от того, какие параметры конфигурации мы изменили.

+----+------------+-------+---------------+------------+
|Test|Parameter   |Value  |NumOfTempTables|Db Max Conn |
+----+------------+-------+---------------+------------+
| 1  |key_buffer_ | 25M   | 30682         | 29         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 2  |key_buffer_ | 55M   | 30793         | 29         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 3  |key_buffer_ | 100M  | 30666         | 28         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 4  |key_buffer_ | 125M  | 30593         | 24         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 5  |query_cache_| 100M  | 30627         | 32         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 6  |query_cache_| 250M  | 30761         | 26         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 7  |query_cache_| 500M  | 30864         | 83*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 8  |query_cache_| 1G    | 30706         | 75*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 9  |tmp_table_  | 125M  | 30724         | 31         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 10 |tmp_table_  | 250M  | 30689         | 90*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 11 |tmp_table_  | 500M  | 30792         | 28         |
|    |size        |       |               |            |  
+----+------------+-------+---------------+------------+
| 12 |Sort_buffer&| 256K  | 30754         | 28         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 13 |Sort_buffer&| 512K  | 30788         | 30         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 14 |Sort_buffer&| 1M    | 30788         | 28         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 15 |Sort_buffer&| 4M    | 30642         | 35         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 16 |innodb-     | 1G    | 30695         | 33         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |
+----+------------+-------+---------------+------------+
| 17 |innodb-     | 2G    | 30791         | 28         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            | 
+----+------------+-------+---------------+------------+
| 18 |innodb-     | 3G    | 30719         | 34         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |  
+----+------------+-------+---------------+------------+

* Среднее из трех запусков

На изображениях ниже показан объем памяти и ЦП, который необходим серверу базы данных для различных конфигураций. Черные линии указывают минимальное и максимальное значения, а синие полосы указывают начальное и конечное значения. Максимальная память была 4096Mкак указано в вопросе.

Использование памяти Использование процессора

user30431
источник
Какой механизм хранения вы используете? MyiSAM? Если вы не используете таблицы MyISAM, не стоит полагаться на key_buffer_size. если вы используете механизм хранения innodb, каков размер innodb_buffer_pool_size. Вы используете query_cache?
Каси