As we all know, mysqld_safe and mysqld are very different
mysqld : The database server instance daemon
mysqld_safe : Control program that examines and sets the environment for mysqld to execute. The mysqld executable is actually launched in a loop. When mysqld terminates, the mysqld_safe program will examine the return results and decide whether
- mysqld terminated normally (intentional shutdown), leaves mysqld_safe
- mysqld terminated abnormally (crash or kill -9 of mysqld)
- Loop back, mysqld fails on retry, leaves mysqld_safe
- Loop back, mysqld starts up, stays in the mysqld_safe loop
Why is it important to have mysqld and mysqld_safe using the same MySQL version?
Let me illustrate it this way: Percona Server sometimes has additional features in mysqld_safe for manipulating the OS. For example, I have seen numactl --interleave=all
in a Percona Server mysqld_safe. If that line was not there, the mysqld for Percona Server may run into issues with memory and swapping.
The same scenario could possibly be the case for Oracle's (ugh, still hate saying that) mysqld and mysqld_safe. There could be improvements from one major release to another that would be removed if the mysqld_safe was older.
Rather than exploring the possibilities of using a old mysqld_safe and a new mysqld (or vica versa), please make your life simple and reinstall MySQL 5.5.30 from scratch.
Before doing so, please run
updatedb
locate mysqld_safe
in Linux and see if there are two lingering. If there are, get the paths straightened out. Otherwise, you may have to reinstall MySQL 5.5.30.
...even surpassing it's theorically maximum possible allocation.
[OK] Maximum possible memory usage: 7.3G (46% of installed RAM)
There is not actually a way to calculate maximum possible memory usage for MySQL, because there is no cap on the memory it can request from the system.
The calculation done by mysqltuner.pl is only an estimate, based on a formula that doesn't take into account all possible variables, because if all possible variables were taken into account, the answer would always be "infinite." It's unfortunate that it's labeled this way.
Here is my theory on what's contributing to your excessive memory usage:
thread_cache_size = 128
Given that your max_connections
is set to 200, the value of 128 for thread_cache_size
seems far too high. Here's what makes me think this might be contributing to your problem:
When a thread is no longer needed, the memory allocated to it is released and returned to the system unless the thread goes back into the thread cache. In that case, the memory remains allocated.
http://dev.mysql.com/doc/refman/5.6/en/memory-use.html
If your workload causes even an occasional client thread to require a large amount of memory, those threads may be holding onto that memory, then going back to the pool and sitting around, continuing to hold on to memory they don't technically "need" any more, on the premise that holding on to the memory is less costly than releasing it if you're likely to need it again.
I think it's worth a try to do the following, after first making a note of how much memory MySQL is using at the moment.
Note how many threads are currently cached:
mysql> show status like 'Threads_cached';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| Threads_cached | 9 |
+----------------+-------+
1 row in set (0.00 sec)
Next, disable the thread cache.
mysql> SET GLOBAL thread_cache_size = 0;
This disables the thread cache, but the cached threads will stay in the pool until they're used one more time. Disconnect from the server, then reconnect and repeat.
mysql> show status like 'Threads_cached';
Continue disconnecting, reconnecting, and checking until the counter reaches 0.
Then, see how much memory MySQL is holding.
You may see a decrease, possibly significant, and then again you may not. I tested this on one of my systems, which had 9 threads in the cache. Once those threads had all been cleared out of the cache, the total memory held by MySQL did decrease... not by much, but it does illustrate that threads in the cache do release at least some memory when they are destroyed.
If you see a significant decrease, you may have found your problem. If you don't, then there's one more thing that needs to happen, and how quickly it can happen depends on your environment.
If the theory holds that the other threads -- the ones currently servicing active client connections -- have significant memory allocated to them, either because of recent work in their current client session or because of work requiring a lot of memory that was done by another connection prior to them languishing in the pool, then you won't see all of the potential reduction in memory consumption until those threads are allowed to die and be destroyed. Presumably your application doesn't hold them forever, but how long it will take to know for sure whether there's a difference will depend on whether you have the option of cycling your application (dropping and reconnecting the client threads) or if you'll have to just wait for them to be dropped and reconnected over time on their own.
But... it seems like a worthwhile test. You should not see a substantial performance penalty by setting thread_cache_size
to 0. Fortunately, thread_cache_size
is a dynamic variable, so you can freely change it with the server running.
Best Answer
A good tool to help you tune MySQL config is the Percona Configuration Wizard for MySQL. This asks you some questions about your system and your workload, and gives you some approximate tuning values to start with.
Of course the term tuning suggests that further refinement may be beneficial, but this happens over time as you monitor your workload, resources usage, and bottlenecks. It's not something we can answer once and for all in a post like this one.
However, I have other comments about your config:
This is not going to take effect, because you override it with a smaller value later in your config file. See below.
This is 64x the default. Unless you have a good reason to increase it, don't. Note that the binlog cache is allocated per user thread, so if you have 100 concurrent transactions, this would use 200MB of RAM. Suggest you remove this line and use the default.
This constrains
tmp_table-size
. See below.This is 32x higher than the default. It's used only during table-scans of MyISAM tales. It would be better to create appropriate indexes and avoid table-scans. Suggest you remove this line and use the default.
This is 128x higher than the default, and 16x higher than the maximum allowed value of 2M. This is used only for MyISAM reads in MySQL 5.5 and earlier, and in MySQL 5.6 it's also used for multi-range reads. But it's probably not necessary to increase it. Suggest you remove this line and use the default.
This is 4x higher than the default. In MySQL 5.6, it's 16x higher than the default. This is also a buffer that is allocated for each user thread, so be careful how much you increase it. Suggest you remove this line and use the default.
This is 64x higher than the default, so be sure you have a good reason for increasing it. It's used during index scans and joins on unindexed columns. It would be better to index tables better. Keep in mind that the join buffer can be allocated for each user thread, so this 8MB amount can account for unpredictable memory growth. Suggest you remove this line and use the default.
Modern Linux kernels can create threads a lot faster than in the old days, so it's no longer as important to keep a thread cache. Suggest you remove this line and use the default.
Are you running on Solaris? If not, this variable has no purpose. Suggest you remove this line.
This is a lot of RAM to dedicate to the query cache, and it's probably overallocated. The query cache has some downsides, especially when you have many concurrent connections. Frequently we actually recommend to disable the query cache unless you can demonstrate you're getting a lot of bang for the buck.
Disable by setting both
query_cache_type=0
andquery_cache_size=0
.This is the default. Suggest you remove this line and use the default.
Recommend to set the default storage engine to InnoDB.
I recommend against using MyISAM for anything. MyISAM supports table-locking only, it's susceptible to corruption in crashes, it's not being developed anymore, and it's gradually being phased out. Claims that MyISAM is faster than InnoDB are based on very old versions of MySQL. Even as far back as 2007, benchmarks show that InnoDB is faster than MyISAM under most workloads.
One of the last reasons to use MyISAM, fulltext indexes, is also obsolete. InnoDB is getting fulltext indexes (they were introduced in 5.6, but they're not really usable yet). Sphinx Search is better for fulltext search anyway.
This is actually lower than the default of 256K on 64-bit systems. Suggest you remove this line and use the default.
This is the default. Suggest you remove this line and use the default.
This is not going to allow any tmp tables higher than
max_heap_table_size
, which you set to 32M earlier. So if you want large tmp tables, you must also increase that config variable to match. But be careful, because you could end up with multiple threads populating 4G tmp tables in memory, and then start swapping.These are used only by MyISAM, and you don't need them if you don't use MyISAM.
This is moot on modern Linux kernels, where dynamic memory allocation is actually more efficient than letting InnoDB preallocate memory. Suggest you remove this line and use the default.
This should be enough to hold all your InnoDB data and indexes, if possible, plus maybe about 10% extra for the change buffer.
You can query the size of your InnoDB data and indexes:
If that total greater than the size of your physical system RAM (64G), then increase the buffer pool as much as is practical. Usually the advice is about 80% of your system RAM, assuming you don't have any other big consumers of memory on the same server. If you do, subtract the memory needed for other processes.
If your data is a lot smaller than your system RAM, then there's no benefit to allocating a big buffer pool. Only one copy of each page of data and indexes is held in the buffer pool.
This is the default.
This variable is not recognized after MySQL 5.0 (or 5.1 unless you enable the InnoDB plugin). Use
innodb_read_io_threads
andinnodb_write_io_threads
. Besides, you're setting the variable to the default value anyway, so you don't need this line in your config file.If you're still running a version of MySQL old enough that this variable is recognized, I strongly suggest you upgrade.
This is probably outdated, unless you're running a very old version of MySQL. Suggest you remove this line and use the default of 0 (unlimited thread concurrency) unless you observe a bottleneck.
This is the default. Suggest you remove this line and use the default.
This is the default. Suggest you remove this line and use the default.
Is this enough? Too much? Here's a blog to help: http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/
There's no benefit to changing the innodb log file in group. Suggest you remove this line and use the default.
This was the default in MySQL 5.0. Now the default is 75. But it's not likely you'll have so many dirty pages regardless. Suggest you remove this line and use the default.
The default is 50 (seconds), and should be adequate for most workloads. Do you have a reason to increase this to 120?
You set max_allowed_packet to 32M earlier. Keep in mind that if you set a given variable in the config file more than once, the last setting takes precedence. So your packets are limited to 16M. If you intend them to be allowed up to 32M, then take out this line.
myisamchk and mysqlhotcopy are only used for MyISAM and ARCHIVE tables. If you migrate to use InnoDB, you won't need to use these tools.