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 = 60
  • set-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=999999
  • set-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!

13 Responses to “Tuning a MySQL server in 5 minutes”

  1. Chris Says:

    Sorry but that was 5 minutes wasted :P That just allows mysql to run away with my system more, it doesn’t tune anything at all.

  2. Rudd-O Says:

    Dude, if your server needs no tuning, that’s great. Ours needed that change to work properly with the amount of requests it handles.

  3. Eric Bergen - A Blog. » Blog Archive » 3 Minute MySQL (tuning) Says:

    [...] 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. [...]

  4. chron Says:

    Nice Shades Man

  5. JFM Says:

    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…

  6. php, mysql, xhtml, css, access, wordpress, flash, photoshop, graphisme, tips Says:

    [...] Tune a MySQL server in 5 minutes. [...]

  7. Mr. PHP Says:

    A completely open mind leads to a closed heart. I am tempted to try this out.

  8. peto4ok Says:

    Very good site. Thanks for author!

  9. brian Says:

    this tutorial sucks.. you should cover many other mysql variables..

  10. Rudd-O Says:

    If this tutorial sucks, then write your own.

  11. Weathering heavy traffic with WordPress and Turbocharged | Turbocharged Says:

    [...] 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. [...]

  12. Anonymous Says:

    What a load of bollocks

  13. billi Says:

    Ignore the endless supply of identical naysayers. You’re doing good.

Leave a Reply