MySQL tworzy tymczasowe tabele na dysku. Jak mogę to zatrzymać?

27

Prowadzimy witrynę (Moodle), którą użytkownicy obecnie uważają za wolną. Myślę, że udało mi się wyśledzić problem, tworząc MySQL, tworząc tymczasowe tabele na dysku. Obserwuję zmienną created_tmp_disk_tablesw administracji serwera Mysql Workbench i liczba ta rośnie z około 50 tabelami / s. Po kilku dniach użytkowania created_tmp_disk_tableswynosi> 100 tys. Wydaje się również, że pamięć nie została zwolniona. Użycie stale rośnie, aż system stanie się praktycznie bezużyteczny i musimy ponownie uruchomić MySQL. Muszę go ponownie uruchamiać prawie codziennie, a zaczyna się to od użycia około 30-35% dostępnej pamięci i kończenie dnia 80%.

Nie mam żadnych obiektów blob w bazie danych ani kontroli nad zapytaniami, więc nie mogę ich zoptymalizować. Użyłem również Kreatora konfirmacji Percona, aby wygenerować plik konfiguracyjny, ale mój.ini też nie rozwiązał mojego problemu.

pytania

  1. Co powinienem zmienić, aby powstrzymać MySQL od tworzenia tabel tymczasowych na dysku? Czy muszę zmienić ustawienia? Czy mam wrzucić więcej pamięci?

  2. Jak mogę zatrzymać MySQL przed zjedzeniem mojej pamięci?

Edytować

Włączyłem slow_queriesdziennik i odkryłem, że zapytanie SELECT GET_LOCK()zostało zarejestrowane jako wolne. Szybkie wyszukiwanie ujawniło, że zezwoliłem na trwałe połączenia w konfiguracji PHP ( mysqli.allow_persistent = ON). Wyłączyłem to. Zmniejszyło to szybkość, z jaką MySQL zużywa pamięć, ale nadal tworzy tabele tymczasowe.

Sprawdziłem również, czy key_buffer sizejest wystarczająco duży. Spojrzałem na zmienną key_writes. To powinno być zero. Jeśli nie, zwiększ wartość. Mam key_buffer_sizezero key_readsi zero, key_writeswięc zakładam, że key_buffer_sizejest wystarczająco duży.

Zwiększyłem tmp_table_sizei max-heap-table-sizedo 1024M, ponieważ wzrost liczby utworzonych tabel_tmp_dysk może wskazywać, że tabele nie mieszczą się w pamięci. To nie rozwiązało problemu.

Ref: http://www.mysqlperformanceblog.com/2007/08/16/how-much-overhead-is-caused-by-on-disk-temporary-tables/

Edytuj 2

Jeśli widzisz wiele sort_merge_passesna sekundę w wynikach POKAŻ GLOBALNY STAN, możesz rozważyć zwiększenie tej sort_buffer_sizewartości. Miałem 2 sort_merge_passesna godzinę, więc uważam, że sort_buffer_sizejest wystarczająco duża.

Patrz: Podręcznik Mysql włączony sort_buffer_size

Edytuj 3

Zmodyfikowałem sortowanie i dołączam do buforów, jak sugeruje @RolandoMySQLDBA. Wynik jest wyświetlany w poniższej tabeli, ale myślę, że created_tmp_tables_on_disknadal jest wysoki. Zrestartowałem serwer mysql po zmianie wartości i sprawdziłem created_tmp_tables_on_diskpo dniu (8 godzin) i obliczyłem średnią. Jakieś inne sugestie? Wydaje mi się, że jest coś, co nie mieści się w jakimś pojemniku, ale nie mogę zrozumieć, co to jest.

+---------------------+-------------+-------------+--------------------+
| 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            |
+---------------------+-------------+-------------+--------------------+   



Oto moja konfiguracja:

+-----------------------+-----------------------+
|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                |
+-----------------------+-----------------------+

Dodatkowe informacje

+--------------------+---------+
|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|
+--------------------+---------+

Ta konfiguracja została mi dana, więc mam nad nią ograniczoną kontrolę. Serwer WWW zużywa bardzo mało procesora i pamięci RAM, więc wykluczyłem tę maszynę jako wąskie gardło. Większość ustawień MySQL pochodzi z narzędzia do automatycznego generowania konfiguracji.

Monitorowałem system za pomocą PerfMon przez kilka reprezentatywnych dni. Na tej podstawie dochodzę do wniosku, że to nie system operacyjny zamienia się na dysk.

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
użytkownik30431
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White mówi GoFundMonica

Odpowiedzi:

16

Patrząc na my.ini, mam dwie sugestie

SUGESTIA # 1

Zwiększyłbym następujące ustawienia w twoim my.ini

sort_buffer_size=4M
join_buffer_size=4M

Spowoduje to, że niektóre złączenia i sortowanie pozostaną w pamięci. Oczywiście, raz JOINalbo ORDER BYpotrzebuje więcej niż 4M, to będzie strona na dysku w postaci tabeli MyISAM.

Jeśli nie możesz się zalogować jako root@localhost, uruchom ponownie mysql przy pomocy

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

Jeśli możesz zalogować się jako root @ localhost, nie musisz ponownie uruchamiać mysql, aby użyć tych ustawień.

Po prostu uruchom to w kliencie MySQL:

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

SUGESTIA # 2

Ponieważ Twoje dane znajdują się na Dysku D:, możesz mieć dyskowe operacje we / wy na Dysku C:.

Uruchom to zapytanie:

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

Ponieważ uruchamiam mysql na pulpicie z ustawieniami domyślnymi, moje tabele tymczasowe są zapisywane na Dysku C:. Jeśli Dysk D jest dyskiem lepszym niż Dysk C:, być może możesz mapować tabele temp na Dysk D:, ustawiając tmpdir w my.ininastępujący sposób:

tmpdir="D:/DBs/"

Będziesz musiał zrestartować mysql, ponieważ tmpdir nie jest zmienną dynamiczną.

Spróbuj !!!

AKTUALIZACJA 29.11.2013 10:09 EST

SUGESTIA # 3

Biorąc pod uwagę fakt, że MySQL działa w systemie Windows i nie można dotknąć zapytań w pakiecie podstawowym, mam dwa pomysły, które należy wykonać razem.

POMYSŁ nr 1: Przenieś bazę danych na maszynę z systemem Linux

Powinieneś być w stanie

  • Skonfiguruj maszynę z systemem Linux
  • Zainstaluj MySQL na komputerze z systemem Linux
  • Włącz rejestrowanie binarne dla MySQL w systemie Windows
  • mysqldump bazę danych do tekstowego pliku SQL
  • Załaduj plik SQL do MySQL działającego w systemie Linux
  • Skonfiguruj replikację z MySQL / Windows na MySQL / Linux

POMYSŁ # 2: Ponownie skonfiguruj Moodle, aby wskazywał maszynę z systemem Linux

Moodle zostało zaprojektowane przede wszystkim dla LAMP. Wystarczy zmienić pliki konfiguracyjne, aby wskazywały na komputer z systemem Linux zamiast na localhost.

Oto link do starego dokumentu Moodle 2.3 na temat konfigurowania MySQL: http://docs.moodle.org/23/en/Installing_Moodle#Create_an_empty_database

Jestem pewien, że najnowsze dokumenty są również dostępne.

Jaki jest sens przenoszenia bazy danych do systemu Linux?

Jak to pomaga w sytuacji w tabeli tymczasowej ???

Sugerowałbym wtedy ustawienie dysku RAM jako folderu docelowego dla twoich tabel tymczasowych

Tworzenie tabeli tymczasowej nadal będzie się odbywać, ale zostanie zapisane w pamięci RAM, a nie na dysku. redukowanie We / Wy dysku.

AKTUALIZACJA 29.11.2013 11:24 EST

SUGESTIA # 4

Proponuję ponownie odwiedzić SUGGESTION # 2 z szybkim dyskiem RAID-0 (32+ GB), konfigurując go jako Dysk T: (T dla Temp). Po zainstalowaniu takiego dysku dodaj go do my.ini:

[mysqld]
tmpdir="T:\"

Wymagane byłoby ponowne uruchomienie MySQL przy użyciu

net stop mysql
net start mysql

BTW powiedziałem celowo RAID-0, abyś mógł uzyskać dobrą wydajność zapisu w porównaniu do RAID-1, RAID-10. Dysk tabeli tmp nie jest czymś, co uczynię nadmiarowym.

Bez optymalizacji zapytań, jak komentuje @RaymondNijland, nie można w żaden sposób zmniejszyć liczby tworzenia tabeli tymczasowej. SUGGESTION #3i SUGGESTION #4oferują przyspieszenie tworzenia tabeli temp i we / wy tabeli temp jako jedyną alternatywę.

RolandoMySQLDBA
źródło
13

Odpowiadam na moje własne pytanie, aby uzyskać kompletność

Jako preferowaną odpowiedź wybiorę @RolandoMySQLDBA, ponieważ dał mi najwięcej wskazówek, mimo że tak naprawdę nie rozwiązał mojego problemu.

Poniżej znajdują się wyniki mojego dochodzenia

Wniosek

MySQL w systemie Windows po prostu tworzy wiele tabel tymczasowych, a dostrajanie MySQL poprzez modyfikację zawartości plików konfiguracyjnych nie pomogło.

Detale

Tabela wyszczególnia parametry, które odpowiednio zmodyfikowałem w my.ini przed wykonaniem jakichkolwiek zapytań. MySQL został ponownie uruchomiony między każdym testem.

Użyłem my.ini znalezionego w oryginalnym pytaniu jako szablonu, a następnie zmieniłem wartość parametrów jeden po drugim zgodnie z poniższą tabelą.

Użyłem JMeter do wygenerowania 100 równoczesnych żądań internetowych (ponieważ reprezentowało to nasze użycie) powtórzonych 10 dziesięć razy. Każde Testskładało się więc z 1000 wniosków łącznie. Spowodowało to kolejne wywołania bazy danych. To pokazało, że MySQL utworzy wiele tabel tymczasowych niezależnie od zmienionych parametrów konfiguracyjnych.

+----+------------+-------+---------------+------------+
|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   |       |               |            |  
+----+------------+-------+---------------+------------+

* Średnia z trzech przebiegów

Poniższe obrazy przedstawiają ilość pamięci i procesora wymaganych przez serwer bazy danych dla różnych konfiguracji. Czarne linie wskazują wartości minimalne i maksymalne, a niebieskie paski wskazują wartości początkowe i końcowe. Maksymalna pamięć była 4096Mtaka, jak wskazano w pytaniu.

Zużycie pamięci Użycie procesora

użytkownik30431
źródło
Z jakiego silnika pamięci korzystasz? MyiSAM? Jeśli nie używasz tabel MyISAM, nie ma sensu polegać na key_buffer_size. jeśli używasz silnika pamięci masowej innodb, jaki jest rozmiar innodb_buffer_pool_size. Czy używasz query_cache?
kasi