Teil 4 - Grails in Produktion – mit Apache, Tomcat und MySQL
In diesem Blog-Post meiner Serie (hier geht es zum ersten Teil und hier zum letzten Teil dieser Blog-Serie) möchte ich die MySQL spezifischen Punkte besprechen. Diesen Post werde ich im Vergleich zum Tomcat-Post relativ kurz halten, da MySQL sehr einfach aufzusetzen ist. Komplexer wird es, wenn es um das Thema Hochverfügbarkeit geht. Wir bei exensio sind nicht die MySQL-Spezialisten (wir tunen MySQL nur soweit, dass die Settings dann später in der Produktivumgebung benutzt werden können), aber vielleicht kann die Buchempfehlung im Abschnitt Hochverfügbarkeit eine erste Hilfestellung geben.
Character Sets
Die Datenbank erzeugen wir mit folgendem SQL:
create database tevainternet DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
Hier bitte beachten, dass es für UTF8 unterschiedliche Mappings („ss“ entspricht „ß“ etc.) gibt. So mussten wir beispielsweise das Encoding für das Login-Token auf utf8_bin ändern, damit das Login-Token 1:1 abgespeichert wurde.
InnoDB
Bei MySQL ist es wichtig, für Grails Applikationen die InnoDB-Storage-Engine zu benutzen, da nur diese Transaktionen unterstützt. Die InnoDB kann explizit durch folgenden Eintrag in my.cnf konfiguriert werden:
default-storage-engine = innodb
in /etc/mysql/my.cnf in Abschnitt [mysqld] eintragen.
Es ist jedoch ausreichend in der Datasource.groovy den Dialect auf org.hibernate.dialect.MySQL5InnoDBDialect zu setzen.
Datasource.groovy
...
environments {
development {
dataSource {
pooled = true
url = 'jdbc:mysql://xx.xx.xx.xx/db01'
driverClassName = 'com.mysql.jdbc.Driver'
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
username = 'uid'
password = 'pwd'
dbCreate = 'update'
}
...
Weitere Konfigurationsparameter in my.cnf
- Connection-Settings:
max_connections habe ich für unsere Lasttests auf 400 (max_connections = 400) gesetzt. Die genaue Anzahl kann später im Produktivbetrieb über das Monitoring bestimmt werden. Hier bitte beachten, dass der Tomcat den Auf- bzw. Abbau des Connection-Pools zeitbasiert steuert. Somit kann es unter Volllast vorkommen, dass die Connections ausgehen, da MySQL die vom Tomcat freigegebenen Connections selbst noch hält, der Tomcat aber schon wieder neue aufmacht.
Weitere Settings bezüglich Connections:
interactive_timeout=120
wait_timeout=120
connect_timeout=10
thread_cache_size=128 - Performance-Settings:
Folgende Werte sollten angepasst werden:
table_cache=512 (default 64)
max_connections = 400
Query-Cache :
query_cache_limit = 4M
query_cache_size = 128M
query_cache_type = 1
InnoDB:
innodb_buffer_pool_size = 25 % des gesamten RAM
innodb_log_file_size = 25% von innodb_buffer_pool_size
innodb_log_buffer_size = 32M
Performance Tools
Folgende Tools haben sich während der Lasttests fürs Tuning von MySQL als sehr nützlich erwiesen:
Perl-Skript (mysqltuner) mit Performance-Infos [1]
Eine Alternative (tuning-primer) findet sich hier[2]
Hochverfügbarkeit
Ich möchte auf diesen Punkt kurz eingehen, obwohl wir (wie schon eingangs erwähnt) von exensio nicht die MySQL Spezialisten sind – da unsere Lösungen auf den unterschiedlichsten Datenbanken, neben MySQL z.B. auch auf PostgreSQL oder Oracle, lauffähig sind - und bisher immer mit dem Hosting Provider bzw. der internen IT-Abteilung des Kunden zusammengearbeitet haben. Die möglichen Lösungen sind sehr unterschiedlich. In einem aktuellen Projekt läuft MySQL auf einem Linux-Cluster. Meine Meinung hierzu ist, dass ich immer eine Master-Slave gegenüber einer Master-Master Konfiguration bevorzugen würde. Die ganze Thematik ist sehr komplex, einen guten Einstieg kann das Buch „High Availability MySQL Cookbook“ [3] liefern.
Links
[1] http://mysqltuner.pl/mysqltuner.pl
[2]http://www.day32.com/MySQL/tuning-primer.sh (Bitte hier noch den command line calculator bc installieren)
[3] http://www.packtpub.com/article/setting-up-mysql-replication-for-high-availability