MySQL erstellt temporäre Tabellen auf der Festplatte. Wie höre ich damit auf?


27

Wir betreiben eine Website (Moodle), die die Benutzer derzeit als langsam empfinden. Ich glaube, ich habe das Problem damit aufgespürt, dass MySQL temporäre Tabellen auf der Festplatte erstellt. Ich beobachte die Variable created_tmp_disk_tablesin der Mysql Workbench-Serververwaltung und die Anzahl steigt mit ungefähr 50 Tabellen / s. Nach einem Tagesgebrauch created_tmp_disk_tablesist> 100k. Auch scheint der Speicher nicht freigegeben zu werden. Die Nutzung nimmt weiter zu, bis das System praktisch unbrauchbar wird und wir MySQL neu starten müssen. Ich muss es fast jeden Tag neu starten und es beginnt damit, dass ich ungefähr 30-35% des verfügbaren Speichers verwende und den Tag mit 80% beende.

Ich habe keine Blobs in der Datenbank und auch keine Kontrolle über die Abfragen, sodass ich nicht versuchen kann, sie zu optimieren. Ich habe auch den Percona-Konfigurationsassistenten verwendet , um eine Konfigurationsdatei zu generieren, aber meine.ini hat auch mein Problem nicht gelöst.

Fragen

  1. Was sollte ich ändern, um zu verhindern, dass MySQL temporäre Tabellen auf der Festplatte erstellt? Gibt es Einstellungen, die ich ändern muss? Soll ich mehr Speicher darauf werfen?

  2. Wie kann ich verhindern, dass MySQL mein Gedächtnis aufzehrt?

Bearbeiten

Ich habe das slow_queriesProtokoll aktiviert und festgestellt, dass die Abfrage SELECT GET_LOCK()als langsam protokolliert wurde. Eine schnelle Suche ergab, dass ich dauerhafte Verbindungen in der PHP-Konfiguration zugelassen hatte ( mysqli.allow_persistent = ON). Ich habe das ausgeschaltet. Dies reduzierte die Rate, mit der MySQL Speicher verbraucht. Es werden jedoch immer noch temporäre Tabellen erstellt.

Ich habe auch nachgesehen, dass das key_buffer sizegroß genug ist. Ich schaute auf die Variable key_writes. Dies sollte Null sein. Wenn nicht, erhöhen Sie die key_buffer_size.Ich habe Null key_readsund Null, key_writesso dass ich davon ausgehe , dass die key_buffer_sizegroß genug ist.

Ich habe das tmp_table_sizeund max-heap-table-sizeauf 1024 MB erhöht, da eine Erhöhung in created_tmp_disk_tables möglicherweise darauf hinweist, dass die Tabellen nicht in den Speicher passen. Das hat es nicht gelöst.

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

Bearbeiten 2

Wenn sort_merge_passesin der Ausgabe von SHOW GLOBAL STATUS viele pro Sekunde angezeigt werden, können Sie den sort_buffer_sizeWert erhöhen . Ich hatte 2 sort_merge_passesin einer Stunde, also halte ich das sort_buffer_sizefür groß genug.

Ref: MySQL Handbuch auf sort_buffer_size

Bearbeiten 3

Ich habe die Sortier- und Verknüpfungspuffer geändert, wie von @RolandoMySQLDBA vorgeschlagen. Das Ergebnis wird in der folgenden Tabelle angezeigt, aber ich denke, das created_tmp_tables_on_diskist immer noch hoch. Ich habe den MySQL-Server neu gestartet, nachdem ich den Wert geändert und created_tmp_tables_on_disknach einem Tag (8 Stunden) überprüft und den Durchschnitt berechnet habe. Irgendwelche anderen Vorschläge? Es scheint mir, dass es etwas gibt, das nicht in eine Art Behälter passt, aber ich kann nicht herausfinden, was es ist.

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



Das ist meine Konfiguration:

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

Zusätzliche Information

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

Dieses Setup wurde mir gegeben, damit ich nur begrenzte Kontrolle darüber habe. Der Webserver verwendet sehr wenig CPU und RAM, daher habe ich diesen Computer als Engpass ausgeschlossen. Ein Großteil der MySQL-Einstellungen stammt aus einem Konfigurationswerkzeug zur automatischen Generierung.

Ich habe das System über einige repräsentative Tage hinweg mit PerfMon überwacht. Daraus schließe ich, dass nicht das Betriebssystem auf die Festplatte wechselt.

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

Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
Paul White sagt GoFundMonica

Antworten:


16

Wenn my.iniich mir das anschaue , habe ich zwei Vorschläge

VORSCHLAG # 1

Ich würde die folgenden Einstellungen in Ihrem Browser vornehmen my.ini

sort_buffer_size=4M
join_buffer_size=4M

Dadurch bleiben einige Verknüpfungen und Sortierungen im Speicher. Sobald eine JOINoder eine ORDER BYmehr als benötigt 4M, wird sie als MyISAM-Tabelle auf die Festplatte gelegt.

Wenn Sie sich nicht als einloggen können root@localhost, starten Sie mysql mit neu

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

Wenn Sie sich als root @ localhost anmelden können, müssen Sie mysql nicht neu starten, um diese Einstellungen zu verwenden.

Führen Sie dies einfach im MySQL-Client aus:

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

VORSCHLAG # 2

Da sich Ihre Daten auf dem Laufwerk befinden D:, befindet sich möglicherweise Disk I / O auf dem Laufwerk C:.

Bitte führen Sie diese Abfrage aus:

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

Da ich standardmäßig mysql auf meinem Desktop ausführe, werden meine temporären Tabellen in Drive geschrieben C:. Wenn Laufwerk D eine bessere Disk als Laufwerk ist C:, vielleicht können Sie temporäre Tabellen zu Laufwerkszuordnung , D:indem tmpdir in my.iniwie folgt:

tmpdir="D:/DBs/"

Sie müssen mysql neu starten, da tmpdir keine dynamische Variable ist.

Versuche es !!!

UPDATE 29.11.2013 10:09 EST

VORSCHLAG # 3

Angesichts der Tatsache, dass MySQL unter Windows ausgeführt wird und Sie die Abfragen im Kernpaket nicht berühren können, habe ich zwei Ideen, die zusammen erledigt werden müssen.

IDEE 1: Verschieben Sie die Datenbank auf einen Linux-Computer

Du solltest dazu fähig sein

  • Richten Sie einen Linux-Computer ein
  • Installieren Sie MySQL auf dem Linux-Rechner
  • Aktivieren Sie die binäre Protokollierung für MySQL in Windows
  • mysqldump die Datenbank in eine SQL-Textdatei
  • Laden Sie die SQL-Datei in MySQL, das unter Linux ausgeführt wird
  • Richten Sie die Replikation von MySQL / Windows nach MySQL / Linux ein

IDEE 2: Konfigurieren Sie Moodle so, dass es auf den Linux-Rechner verweist

Moodle wurde in erster Linie für LAMP entwickelt. Ändern Sie einfach die Konfigurationsdateien so, dass sie auf den Linux-Computer anstatt auf localhost verweisen.

Hier ist ein Link zu einem alten Moodle 2.3-Dokument zum Einrichten von MySQL: http://docs.moodle.org/23/de/Installing_Moodle#Create_an_empty_database

Ich bin sicher, dass auch die neuesten Dokumente verfügbar sind.

Was bringt es, die Datenbank auf Linux zu verlagern?

Wie hilft das der temporären Tabellensituation ???

Ich würde dann vorschlagen, eine RAM-Disk als Zielordner für Ihre temporären Tabellen einzurichten

Die temporäre Tabellenerstellung wird weiterhin durchgeführt, jedoch nicht auf die Festplatte, sondern auf den Arbeitsspeicher geschrieben. Reduzierung der Festplatten-E / A.

UPDATE 29.11.2013 11:24 EST

VORSCHLAG # 4

Ich würde vorschlagen, SUGGESTION 2 mit einer schnellen RAID-0-Festplatte (32+ GB) zu wiederholen und sie als Laufwerk T: (T für Temp) zu konfigurieren. Fügen Sie nach der Installation eines solchen Datenträgers Folgendes hinzu my.ini:

[mysqld]
tmpdir="T:\"

Ein Neustart von MySQL wäre unter Verwendung von erforderlich

net stop mysql
net start mysql

Übrigens, ich habe RAID-0 absichtlich angegeben, damit Sie über RAID-1 und RAID-10 eine gute Schreibleistung erzielen. Eine tmp table disk würde ich nicht überflüssig machen.

Ohne die Abfragen zu optimieren, die von @RaymondNijland kommentiert wurden, können Sie die Anzahl der temporären Tabellenerstellungen in keiner Weise verringern. SUGGESTION #3und SUGGESTION #4bieten die Beschleunigung der temporären Tabellenerstellung und der temporären Tabellen-E / A als einzige Alternative.


13

Der Vollständigkeit halber beantworte ich hier meine eigene Frage

Ich werde @RolandoMySQLDBA als bevorzugte Antwort auswählen, da es mir die meisten Hinweise gab, obwohl es mein Problem nicht wirklich gelöst hat.

Unten sind die Ergebnisse meiner Untersuchung

Fazit

MySQL unter Windows erstellt nur viele temporäre Tabellen, und das Optimieren von MySQL durch Ändern des Inhalts der Konfigurationsdateien hat nicht geholfen.

Einzelheiten

In der Tabelle sind die Parameter aufgeführt, die ich jeweils in my.ini geändert habe, bevor Abfragen ausgeführt wurden. MySQL wurde zwischen jedem Test neu gestartet.

Ich habe die in der ursprünglichen Frage gefundene my.ini als Vorlage verwendet und dann den Wert der Parameter nacheinander gemäß der folgenden Tabelle geändert.

Ich habe JMeter verwendet , um 100 gleichzeitige Webanforderungen zu generieren (wie dies unsere Verwendung darstellt), die 10 Mal wiederholt wurden. Jedes Testbestand somit aus insgesamt 1000 Anfragen. Dies führte zu nachfolgenden Datenbankaufrufen. Dies zeigte, dass MySQL viele temporäre Tabellen erstellen würde, unabhängig davon, welche Konfigurationsparameter wir geändert haben.

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

* Durchschnitt von drei Läufen

Die folgenden Bilder zeigen den für die verschiedenen Konfigurationen erforderlichen Arbeitsspeicher und die CPU des Datenbankservers. Die schwarzen Linien kennzeichnen die Minimal- und Maximalwerte und die blauen Balken kennzeichnen Start- und Endwerte. Der maximale Speicher war 4096Mwie in der Frage angegeben.

Speichernutzung CPU auslastung


Welche Speicher-Engine verwenden Sie? MyiSAM? Wenn Sie keine MyISAM-Tabellen verwenden, ist es nicht sinnvoll, sich auf key_buffer_size zu verlassen. Wenn Sie eine Innodb-Speicherengine verwenden, ist dies die Größe von Innodb_Buffer_Pool_Size. Verwenden Sie query_cache?
kasi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.