MySQL створює тимчасові таблиці на диску. Як це зупинити?


27

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

У мене немає баб у базі даних і ніякого контролю над запитами, тому я не можу намагатися їх оптимізувати. Я також використовував майстер конфігурації Percona для створення файлу конфігурації, але мій.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до 1024М, оскільки збільшення create_tmp_disk_tables може вказувати на те, що таблиці не можуть вміститися в пам'яті. Це не вирішило.

Посилання: http://www.mysqlperformanceblog.com/2007/08/16/how-much-overhead-is-caused-by-on-disk-temporary-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

Коментарі не для розширеного обговорення; ця розмова перенесена в чат .
Пол Білий каже, що GoFundMonica

Відповіді:


16

Дивлячись на my.ini, у мене є дві пропозиції

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

Я б зіткнувся з такими налаштуваннями у ваших my.ini

sort_buffer_size=4M
join_buffer_size=4M

Це зробить кілька приєднань і начебто залишиться в пам’яті. Звичайно, щойно a JOINабо 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
  • mysqldпередайте базу даних в текстовий файл 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/Installing_Moodle#Create_an_empty_database

Я впевнений, що доступні і останні документи.

Який сенс переміщення бази даних до Linux ???

Як це допомагає ситуації з тимчасовою таблицею ???

Тоді я б запропонував встановити диск RAM як цільову папку для темп-таблиць

Створення таблиці темп все ще буде відбуватися, але вона буде записана в ОЗУ, а не на диск. зменшення вводу / виводу диска.

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

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

Я б запропонував переглянути SUGGESTION №2 зі швидким диском RAID-0 (32+ ГБ), налаштувавши його як Drive T: (T для Temp). Встановивши такий диск, додайте це до my.ini:

[mysqld]
tmpdir="T:\"

Потрібно перезапустити MySQL, використовуючи

net stop mysql
net start mysql

BTW Я спеціально сказав RAID-0, щоб ви могли отримати хороші показники запису через RAID-1, RAID-10. Диск з таблицею tmp - це не те, що я би робив зайвим.

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


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такою, як зазначено у запитанні.

Використання пам'яті Використання процесора


Який механізм зберігання даних ви використовуєте? MyiSAM? Якщо ви не використовуєте таблиці MyISAM, покладатися на key_buffer_size не має сенсу. якщо ви використовуєте двигун зберігання innodb, який розмір innodb_buffer_pool_size. Ви використовуєте query_cache?
kasi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.