MySQL mit hoher Last optimieren

AnPa

Registered User
Hallo Leute,

nach langer Zeit melde ich mich mal wieder zu Wort.

Mein MySQL Server bearbeitet seine Anfragen (SELECT, INSERT, UPDATES, etc.) zwischenzeitlich sehr langsam. Er steht auch unter einer, ich finde, hohen Last.

Kurz zum Rechner: Intel Core i7, 24 GB RAM, 2x1TB SataII Software RAID.

Lt. PHPMyAdmin habe ich folgende Werte ermittelt:
Code:
Abfragestatistik: Seit seinem Start wurden 3,659,819,535 Abfragen an diesen MySQL-Server gesandt.
Insgesamt 	ø pro Stunde 	ø pro Minute 	ø pro Sekunde
3,660 M 	2,93 M 	48,84 k 	814,08

Was evtl. noch von Interesse ist:
Code:
select 	3,338 M 	2,673 M 	91,43%
insert 	26 M 	20,997 k 	0,72%
update 	21 M 	16,627 k 	0,57%
set option 	10 M 	8,388 k 	0,29%
delete 	10 M 	8,158 k 	0,28%
replace 	6,544 k 	5,240 k 	0,18%
change db 	6,171 k 	4,941 k 	0,17%
lock tables 	5,183 k 	4,150 k 	0,14%
unlock tables 	5,183 k 	4,150 k 	0,14%

Also ist es hauptsächlich "nur" select. Es liegen 2 größere Projekte auf dem Server. Die eine Datenbank umfasst ungefähr 3GB mit ca. 35 Mio. einträgen, die größe der weiteren ist nicht unbedingt ausschlaggebend.

Ich mutze: Server Version: 5.0.51a-24+lenny5-log

Gelesen habe ich, das MySQL 5.5 die Abfragen extremst beschleunigen soll (!). Ist dem so? Ist es empfehlenswert schon MySQL 5.5 zu nutzen?
Ist ein Upgrade problemlos möglich?

Ich habe die Konfiguration weitgehend nach tuning-primer.sh eingestellt.

Hier die komplette config:

Code:
[client]
port		= 3306
socket	= /var/run/mysqld/mysqld.sock


[mysqld_safe]
socket	= /var/run/mysqld/mysqld.sock
nice		= 0

[mysqld]

user		= mysql
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
port		= 3306
basedir		= /usr
datadir		= /var/lib/mysql
tmpdir		= /tmp
language	= /usr/share/mysql/english
skip-external-locking
open_files_limit = 12000
key_buffer		= 1024M
sort_buffer		= 15M
max_allowed_packet	= 16M
thread_stack		= 128K
thread_cache_size	= 8
myisam-recover		= BACKUP
max_connections        = 1000
wait_timeout		= 120
table_cache            = 3500
max_heap_table_size	= 128M
tmp_table_size		= 128M
query_cache_limit       = 16M
query_cache_size        = 256M
query_cache_min_res_unit= 1K
innodb_buffer_pool_size = 8192M
read_buffer_size	= 8M
join_buffer_size	= 1M
log_slow_queries	= /var/log/mysql/mysql-slow.log
expire_logs_days	= 10
skip-bdb
log-error=/var/log/mysql/mysql-bin.err


[mysqldump]
quick
quote-names
max_allowed_packet	= 16M

[mysql]
#no-auto-rehash	# faster start of mysql but no tab completition

[isamchk]
key_buffer		= 16M

Hat jemand Verbesserungsvorschläge?

Auf dem Server laufen weiterhin:

Postfix, Apache2, ProFtpd, ein weiterer MailServer der als Backend PHP nutzt und daher auch viel auf MySQL zugreift.

Grüße
Angelo
 
Ausgabe von top? Mal das slowquery-log aktiviert und geprüft?

Zudem: 900 Anfragen pro Sekunde ist natürlich nicht unbedingt wenig - "passt" der Wert?
 
Hallo,

danke für deine Antwort.

Die top-Ausgabe muss etwas warten. Ich habe gerade mit dem ramdisk repli gebastelt und dabei den Server zum Abschuss gebracht.
Er fährt gerade wieder hoch.

Also ich denke schon das die Zahlen passen:

Es sind zeitweise 2-300 User Online. Dazu kommen ca. 30-40k Mails / Tag rein, ca. 400 User die ständig via IMAP / POP3 auf Ihre Mails zugreifen wollen.

Also sind die Zahlen wohl richtig.

edit: Das habe ich versucht: http://foobar.lamp-solutions.de/how...ysql-performacne-mit-einer-ramdisk-tunen.html

Aber es startete wohl nicht. Ich bekam immer die Fehlermeldung das er nicht Verbinden kann zum Socket. Komischerweise waren in TOP aber mysqld Prozesse vorhanden. Als ich diese dann Abschiessen wollte, weil Sie den ganzen Server lahmgelegt hatten, ging gar nix mehr und ich musste einen Hard-Reset machen!

Gruß
Angelo
 
Last edited by a moderator:
Hm, ohne nun Zugriff auf den Server zu haben, frag' doch mal bei dem Artikel direkt nach - wie es scheint gibt es dort auch eine Kommentarfunktion, vielleicht meldet sich ja jemand, würde mich auch interessieren :)
 
Hmm...
Ja das könnte ich mal machen!

Hat denn sonst jemand noch ne andere Idee, wie man das ganze etwas schneller machen könnte?

Da mir diese Ram-Disk geschichte auch etwas unsicher bezüglich plötzlichem Abstürzen zu sein scheint, was haltet Ihr von einer SSD als Mysql-Verzeichniss?

Hat das jemand von euch im Einsatz und bringt es entscheidende Vorteile??
 
Also würde es theoretisch ausreichen, wenn ich mir eine kleine, sagen wir mal 32 GB SSD einbauen lasse, und darauf dann das mysql-data-dir packe?
 
definiere alles?

Also auch der Daemon ansich?

Problem hierbei: mysql ist als debian-paket installiert.
Kann man da einfach so den "installationsort" ändern?
 
Ich hab noch nie probiert das wo anderst zu installieren.
Man kann doch wie bei mssql den Speicherort der db wählen oder?
 
Ja, das ist das data-dir. Dort sind alle Tabellen, Datenbanken, etc. gespeichert.
Das wüsste ich jetzt wie ich das umbastel auf die SSD.
Aber nicht das Programm, also den mysql-dienst selber.
 
Versuche doch einfach das /var/lib/mysql verzeichnis zu verschieben, mounte die SSD unter /var/lib/mysql und kopiere die Daten wieder ins Verzeichnis. ;-)

Gruß
Nero
 
Ich habe jetzt für 30 tage zum testen eine ssd drin.
Habe das mysql Verzeichnisse auch von dort am laufen.
Aber irgendwie bin ich nicht glücklich damit.
Es dauert teilweise immer noch ziemlich lange.
Habe auch das mit dem replika nochmal versucht. Das haut nun hin
hab jetzt Master auf der ssd und den Sklaven auf der sata.
bringt auch nix.

Nun bin ich ratlos.

Was kann das sein?
 
Dann scheint die I/O-Last eventuell nicht dein Bottleneck zu sein.
Die Ausgabe von top würde mit Sicherheit zur Klärung beitragen.

Außerdem solltest du dir imho über die Anzahl der max. Verbingungen Gedanken machen. Wäre n Versuch wert, die zu erhöhen....bin allerdings auch kein MySQL-Experte, daher nur ne Vermutung.
 
Ich hab bei einem meiner Projekte dadurch eine massive Verbesserung erhalten, dass ich das datadir auf eine ramfs ausgelagert hab

Code:
mysqld stoppen

-bash
mkdir /var/lib/mysqlramfs
mount -t ramfs -o size=7G ramfs /var/lib/mysqlramfs/
#ramfs erstellen
cp -r /var/lib/mysql/ /var/lib/mysqlramfs/
#dateien kopieren
chown -R mysql:mysql /var/lib/mysqlramfs/
#übereignen

my.cnf:
datadir = /var/lib/mysqlramfs/mysql

mysqld starten

Dann irgendwo (ggf. selber host, andere mysqld instanz) eine Replikation laufen lassen und gut ist :)
Ich hab beide auf dem selben root und mache dann vom Replikat meine Backups.

Alternativ:
RamFS als Replikat, alle Selects auf diesen umbiegen,
und den auf der HDD als Master (Inserts etc. an ihn)
 
Ich habe die Konfiguration weitgehend nach tuning-primer.sh eingestellt.
Dann gib uns doch bitte mal eine Ausgabe davon. Denn hier stehen mehr Informationen drin, als in Deiner Config.
Es würden auch solche Fragen wie "max_connections = 1000" sinnvoll oder nicht beantwortet werden.

Zwei Dinge die mir gleich aufgefallen sind:
read_buffer_size = 8M
Der ist zu hoch. Er sollte - je nach Architektur - zwischen 128K und 256K liegen. Siehe: http://www.mysqlperformanceblog.com/2007/09/17/mysql-what-read_buffer_size-value-is-optimal/
Am Besten den Test selber auf der Maschine durchführen um den optimalen Wert zu raus zu finden.

log_slow_queries = /var/log/mysql/mysql-slow.log
Und das dieses Logfile die Performance drosselt, hast Du sicherlich gelesen, oder?

huschi.
 
Hi Leute,

ich habe zwischenzeitlich auf MySQL 5.5 hochgeschraubt, da ich hörte, das InnoDB dort deutlich schneller sein soll.

MySQL läuft als Master mit dem Data-Dir auf der SSD, der Slave auf der normalen HD auf dem selben Rechner.

Ich finde zwar, das es schneller geworden ist, aber so richtig wie ich mir das erhofft habe, ist es nicht geworden.

Jetzt weiß ich auch nicht, ob es evtl. gar nicht an MySQL liegt, sondern Apache2 + PHP eher der Flaschenhals ist.
Es gibt nicht die möglichkeit, die einzelnen Schritte, die ein PHP-Script vom Abruf bis zur Ausgabe durchläuft, irgendwie zu Monitoren um zu schauen, welcher Schritt wie lange dauert?

Hier die aktuelle Ausgabe des tuning-primer Scripts:

Code:
        -- MYSQL PERFORMANCE TUNING PRIMER --
             - By: Matthew Montgomery -

MySQL Version 5.5.17-log x86_64

Uptime = 1 days 9 hrs 35 min 32 sec
Avg. qps = 263
Total Questions = 31878037
Threads Connected = 90

Warning: Server has not been running for at least 48hrs.
It may not be safe to use these recommendations

To find out more information on how each of these
runtime variables effects performance visit:
http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html
Visit http://www.mysql.com/products/enterprise/advisors.html
for info about MySQL's Enterprise Monitoring and Advisory Service

SLOW QUERIES
The slow query log is enabled.
Current long_query_time = 10.000000 sec.
You have 560 out of 31878273 that take longer than 10.000000 sec. to complete
Your long_query_time seems to be fine

BINARY UPDATE LOG
The binary update log is enabled
Binlog sync is not enabled, you could loose binlog records during a server crash

WORKER THREADS
Current thread_cache_size = 8
Current threads_cached = 5
Current threads_per_sec = 0
Historic threads_per_sec = 0
Your thread_cache_size is fine

MAX CONNECTIONS
Current max_connections = 500
Current threads_connected = 90
Historic max_used_connections = 411
The number of used connections is 82% of the configured maximum.
Your max_connections variable seems to be fine.

INNODB STATUS
Current InnoDB index space = 743 M
Current InnoDB data space = 4.72 G
Current InnoDB buffer pool free = 80 %
Current innodb_buffer_pool_size = 11.71 G
Depending on how much space your innodb indexes take up it may be safe
to increase this value to up to 2 / 3 of total system memory

MEMORY USAGE
Max Memory Ever Allocated : 14.50 G
Configured Max Per-thread Buffers : 2.76 G
Configured Max Global Buffers : 12.23 G
Configured Max Memory Limit : 14.99 G
Physical Memory : 23.59 G
Max memory limit seem to be within acceptable norms

KEY BUFFER
Current MyISAM index space = 278 M
Current key_buffer_size = 256 M
Key cache miss rate is 1 : 308
Key buffer free ratio = 79 %
Your key_buffer_size seems to be fine

QUERY CACHE
Query cache is enabled
Current query_cache_size = 256 M
Current query_cache_used = 66 M
Current query_cache_limit = 1 M
Current Query cache Memory fill ratio = 26.01 %
Current query_cache_min_res_unit = 4 K
MySQL won't cache query results that are larger than query_cache_limit in size

SORT OPERATIONS
Current sort_buffer_size = 1 M
Current read_rnd_buffer_size = 4 M
Sort buffer seems to be fine

JOINS
Current join_buffer_size = 132.00 K
You have had 3 queries where a join could not use an index properly
You should enable "log-queries-not-using-indexes"
Then look for non indexed joins in the slow query log.
If you are unable to optimize your queries you may want to increase your
join_buffer_size to accommodate larger joins in one pass.

Note! This script will still suggest raising the join_buffer_size when
ANY joins not using indexes are found.

OPEN FILES LIMIT
Current open_files_limit = 12000 files
The open_files_limit should typically be set to at least 2x-3x
that of table_cache if you have heavy MyISAM usage.
Your open_files_limit value seems to be fine

TABLE CACHE
Current table_open_cache = 3500 tables
Current table_definition_cache = 3500 tables
You have a total of 2281 tables
You have 2981 open tables.
The table_cache value seems to be fine

TEMP TABLES
Current max_heap_table_size = 16 M
Current tmp_table_size = 16 M
Of 114958 temp tables, 10% were created on disk
Created disk tmp tables ratio seems fine

TABLE SCANS
Current read_buffer_size = 256 K
Current table scan ratio = 214 : 1
read_buffer_size seems to be fine

TABLE LOCKING
Current Lock Wait ratio = 1 : 1954
You may benefit from selective use of InnoDB.
If you have long running SELECT's against MyISAM tables and perform
frequent updates consider setting 'low_priority_updates=1'
./tuning-primer.sh: line 1181: [: AUTO: integer expression expected
 
Es gibt nicht die möglichkeit, die einzelnen Schritte, die ein PHP-Script vom Abruf bis zur Ausgabe durchläuft, irgendwie zu Monitoren um zu schauen, welcher Schritt wie lange dauert?
Doch, die entsprechende PHP-Erweiterung heisst XDebug und kann mit xdebug.profiler_enable aktiviert sowie mittels xdebug.profiler_output_dir und xdebug.profiler_output_name an deine Struktur angepasst werden.
Details hier: http://xdebug.org/docs/profiler

Zum Auslesen der Dateien bevorzuge ich WinCacheGrind, unter Linux setzt man ueblicherweise KCacheGrind ein.
 
Back
Top