Tuning a MySQL server in 5 minutes
Continuing with the Server management series, this time we’ll learn how to tune a MySQL server to handle high server loads. Obviously, this piece assumes that you’re using MySQL to serve a dynamic site. If this is not the case, you’ll still find this article useful, but you’ll have to derive your own interpretations out of it.
If you recall the article titled Tuning an Apache server in 5 minutes, you’ll also know that there’s a tunable for Apache which lets you set the maximum number of Apache processes that run on your server. Once you’ve tuned Apache, it only makes sense to tune MySQL to handle that many connections simultaneously.
Before you go on, “Tuning a MySQL server in 5 minutes” is indeed an exaggeration. I concede you that. Database tuning is so much more than what this article says. I don’t mean to disrespect DBAs: they usually perform large amounts of magic in order for databases to get from abysmal to top-dog performance. But the first step to having a site that doesn’t break with traffic surges is usually what I’m about to discuss.
Tips for very high loads
Okay, on to our business. First off, if you’re handling a very large number of simultaneous connections to your Apache server (in the order of 250 or higher), it would make sense to offload the database processing to a different server. That way, you’ll have more control over loads exerted by Apache and by MySQL, separately.
If you’re short on money, that’s of course not an option. Keep reading to find out an acceptable compromise then.
The (important) differences between static and dynamic page loads
For the purpose of this article, we’ll name two distinct types of connections to your Web server:
- Dynamic requests
- Any request to your Apache server that causes a MySQL connection to be opened and database queries to be emitted. A good example is a PHP page which requests a list of products from your database.
- Static requests
- Any request to your Apache server which doesn’t incur the cost of a MySQL connection. Examples of these are static HTML pages or file downloads.
And, of course, you’ll need to discriminate between those two.
Figuring out the right maximum number of MySQL connections
Usually, a good starting estimate is one dynamic request for each 5 requests. That’s because most pages load CSS style sheets, and images, although those files do not get loaded on subsequent requests from the same visitors (partly due to browser caching). To get an exact number for this ratio, however, you’ll need to analyze your Apache access_log log file (manually, or via the known Analog or Webalizer log analysis packages).
Once you’ve arrived to an accurate estimate for your scenario, multiply that ratio by the maximum number of connections you’ve configured on your Apache server. For example, if your Apache server is serving a maximum of 256 clients (which is a lot), and your ratio of dynamic requests vs. all requests is 1/8, you’d have an expected maximum of 32 database connections. Just to be on the safe side, multiply that by two, and you’ll have a foolproof figure. But if you want to be really, really certain, you should always expect a maximum of 256 database connections.
Setting the maximum connections on your MySQL server
Using your favorite text editor, as root, open up the /etc/my.cnf file (the location of the file may vary according to your distribution). You should see something like this:
[ecuagol@216-55-181-30 ~]$ cat /etc/my.cnf [mysqld] safe-show-database innodb_data_file_path=ibdata1:10M:autoextend datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock
[mysql.server] user=mysql basedir=/var/lib
[safe_mysqld] err-log=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid
We’ll be dealing with the [mysqld] section. Under that section, add two new parameters (or modify them, if they are already there and they aren’t commented):
set-variable = max_connections = 60set-variable = max_user_connections = 60
MySQL defaults to 1 max connection, with 1 max connection per user. Evidently, you’ll be replacing 60 with your expected maximum number of connections. With these settings, you’ll be on the safe side.
The reason you’re setting both max_connections and max_user_connections is because, generally, Apache appears to your MySQL database server as one single user. So, you need to raise them both.
You may also want to increase other parameters, if you’ll be expecting heavy loads or unusual queries:
set-variable = max_allowed_packet=1M(sanity check to stop runaway queries)set-variable = max_connect_errors=999999set-variable = table_cache=1200
Where 1200 should be max_user_connections multiplied by the maximum number of JOINs your heaviest SQL query contains.
After tuning your server, restart MySQL (/sbin/service mysqld restart usually does the trick on Fedora Core).
Conclusions and final words
That’s it! Hope I’ll see you around for the next installment. By the way, if you spot any inaccuracies or errors, feel free to comment on it using the comment form right below this article. Happy hacking!
March 6th, 2006 at 19:19
Sorry but that was 5 minutes wasted
That just allows mysql to run away with my system more, it doesn’t tune anything at all.
March 6th, 2006 at 19:20
Dude, if your server needs no tuning, that’s great. Ours needed that change to work properly with the amount of requests it handles.
March 6th, 2006 at 19:44
[...] While reading planetmysql.org I ran across this Tune a MySQL server in 5 minutes.. I think that entry is really missing a lot in terms of actual tuning for the real world. Also I thought max_user_connections is number of connections per hour. Since I only have minutes I can’t look it up! You probably don’t want to set this with apache. So here in three minutes are the four variables you really need and some generic guidlines for setting them. This assumes that MySQL is running on it’s own server and has one apache server connecting to it. [...]
March 7th, 2006 at 2:01
Nice Shades Man
March 7th, 2006 at 4:16
Standard critic: Any article about tuning who does not include “before” and “after” benchmarks is useless.
Telling the reader how much he will be gaining and in how much time he will recover his investment (1) including the one of reading the article is not a feature but a requisite.
(1) Just imagine that you spend a week recompiling a distribution and that later you discover that the gain is 1%. The investment is recovered in two years. Now let’s imagine that your policy is a full upgrade after one year…
March 13th, 2006 at 4:27
[...] Tune a MySQL server in 5 minutes. [...]
March 13th, 2006 at 23:53
A completely open mind leads to a closed heart. I am tempted to try this out.
May 7th, 2006 at 0:50
Very good site. Thanks for author!
January 17th, 2007 at 16:25
this tutorial sucks.. you should cover many other mysql variables..
January 17th, 2007 at 17:38
If this tutorial sucks, then write your own.
April 29th, 2007 at 20:48
[...] How to do it? I wrote a separate guide that deals with the problem. In the same vein, MySQL needs to be kept in check, so check this other guide. [...]
May 7th, 2007 at 13:29
What a load of bollocks
November 26th, 2007 at 9:22
Ignore the endless supply of identical naysayers. You’re doing good.