I have this server that has only one site with one database on it. And yet, I cannot tweak it to make the load go back down to normal.
If I restart mysql service, memory and load go down to normal, but a few days later, memory and load are progressively increasing.
Server specs
- Centos 7
- total memory 7.8G
- swap 1G
htop output
MySQL version
mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper
my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
#[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
#datadir=/var/lib/mysql
#socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
#symbolic-links=0
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
#max_allowed_packet=1024M
##################
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
plugin-load-add=validate_password.so
max_allowed_packet=100M
#------------------| query cach config
# https://easyengine.io/tutorials/mysql/query-cache
#------------------|
query_cache_type = 1
query_cache_size = 256M
query_cache_limit = 2M
#query_cache_strip_comments =1
port = 3306
#socket = /var/lib/mysql/mysql.sock
#skip-external-locking
key_buffer_size = 512M
max_allowed_packet=268435456
table_open_cache = 256
sort_buffer_size = 256
read_buffer_size = 256
read_rnd_buffer_size = 40
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
# Try number of CPU's x 2 for thread_concurrency
#thread_concurrency = 2
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (via the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
# Replication Master Server (default)
# binary logging is required for replication
#log-bin=mysql-bin
# binary logging format - mixed recommended
binlog_format=mixed
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
# but will not function as a master if omitted
#server-id = 1
# ============================================================ #
# =============== Custom server tweaks [start] =============== #
# ============================================================ #
default_storage_engine = InnoDB
innodb_buffer_pool_size = 2G #4G # 8G # Use up to 70-80% of RAM & optionally check if /proc/sys/vm/swappiness is set to 0. Use Tuning Primer or MySQL Tuner to adjust accordingly.
innodb_file_per_table = 1
#--------------------------|
# 2 means log buffer is flushed to OS file cache on every transaction commit.
# The implication of 2 is optimal and improve performance
# if you are not concerning ACID and can lose transactions for last second or two in case of OS crashes
# -------------------------|
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_log_buffer_size = 16M
#---------------------------|
# Delete the ib_logfile0 & ib_logfile1 files in /var/lib/mysql whenever you change this,
# even the first time you set it up, as the default value is 8M.
# Don't go above 256M.
# ref: https://gist.github.com/wh4u/1fafe2bf98f630d7753717b5a8835bca
#---------------------------|
innodb_log_file_size = 256M
innodb_file_per_table=ON
innodb_stats_on_metadata = OFF
innodb_buffer_pool_instances = 8 #(or 1 if innodb_buffer_pool_size < 1GB)
#query_cache_type = 0
#query_cache_size = 0 #(disabling mutex)
#---------------|
# ref: http://techinfobest.com/optimize-mysql-table_open_cache/
# --------------|
#open_files_limit=10000
open_files_limit=19107
table_open_cache=39390
slow-query-log=1
long_query_time = 1
log-queries-not-using-indexes = 1
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
htop output after a couple of days
If I don't restart MySQL, this is what happens after 3-4 days
Can someone point me to the right direction please?
Additional details
MySQL crashed a little later with following messages in the log:
2020-01-03T12:59:51.514413Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4887ms. The settings might not be optimal. (flushed=142 and evicted=0, during the time.)
2020-01-03T13:00:35.061257Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 11874ms. The settings might not be optimal. (flushed=89 and evicted=0, during the time.)
2020-01-03T13:01:13.857771Z 0 [Warning] Could not increase number of max_open_files to more than 5000 (request: 78941)
2020-01-03T13:01:13.858498Z 0 [Warning] Changed limits: table_open_cache: 2419 (requested 39390)
2020-01-03T13:01:14.177515Z 0 [Warning] option 'sort_buffer_size': unsigned value 256 adjusted to 32768
2020-01-03T13:01:14.177549Z 0 [Warning] option 'read_buffer_size': unsigned value 256 adjusted to 8192
2020-01-03T13:01:14.177630Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2020-01-03T13:01:14.420855Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.28-log) starting as process 15029 ...
2020-01-03T13:01:15.607997Z 0 [Warning] You need to use --log-bin to make --binlog-format work.
2020-01-03T13:01:15.758435Z 0 [Note] InnoDB: PUNCH HOLE support available
2020-01-03T13:01:15.758521Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2020-01-03T13:01:15.758535Z 0 [Note] InnoDB: Uses event mutexes
2020-01-03T13:01:15.758552Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2020-01-03T13:01:15.758563Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2020-01-03T13:01:15.758574Z 0 [Note] InnoDB: Using Linux native AIO
2020-01-03T13:01:15.759295Z 0 [Note] InnoDB: Number of pools: 1
2020-01-03T13:01:15.759589Z 0 [Note] InnoDB: Using CPU crc32 instructions
2020-01-03T13:01:15.773538Z 0 [Note] InnoDB: Initializing buffer pool, total size = 2G, instances = 8, chunk size = 128M
2020-01-03T13:01:16.072379Z 0 [Note] InnoDB: Completed initialization of buffer pool
2020-01-03T13:01:16.142472Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2020-01-03T13:01:16.237526Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2020-01-03T13:01:16.349890Z 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 82179195773
2020-01-03T13:01:16.349986Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 82179207508
2020-01-03T13:01:16.471207Z 0 [Note] InnoDB: Database was not shutdown normally!
I tried the solution that was provided in the duplicate question suggestion, but this has made things worse. The server runs out of memory within minutes.
UPDATE
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872
Dictionary memory allocated 1654382
Buffer pool size 131072
Free buffers 1
Database pages 128972
Old database pages 47448
Modified db pages 1578
Pending reads 1
Pending writes: LRU 0, flush list 163, single page 0
Pages made young 17903348, not young 602752081
0.00 youngs/s, 0.00 non-youngs/s
Pages read 75403666, created 44758503, written 47149356
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 997 / 1000, young-making rate 0 / 1000 not 67 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 128972, unzip_LRU len: 0
I/O sum[106576]:cur[1912], unzip sum[0]:cur[0]
Are Old database pages
too many? What issues do you see?
UPDATE #2
Here is what my.cnf looks like at the moment
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
#[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
#datadir=/var/lib/mysql
#socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
#symbolic-links=0
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
#max_allowed_packet=1024M
##################
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
plugin-load-add=validate_password.so
max_allowed_packet=100M
#------------------| query cach config
# https://easyengine.io/tutorials/mysql/query-cache
#------------------|
query_cache_type = 1
query_cache_size = 256M
query_cache_limit = 2M
#query_cache_strip_comments =1
port = 3306
#socket = /var/lib/mysql/mysql.sock
#skip-external-locking
key_buffer_size = 512M
max_allowed_packet=268435456
#table_open_cache = 256
sort_buffer_size = 256
read_buffer_size = 256
read_rnd_buffer_size = 40
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
# Try number of CPU's x 2 for thread_concurrency
#thread_concurrency = 2
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (via the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
# Replication Master Server (default)
# binary logging is required for replication
#log-bin=mysql-bin
# binary logging format - mixed recommended
binlog_format=mixed
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
# but will not function as a master if omitted
#server-id = 1
# ============================================================ #
# =============== Custom server tweaks [start] =============== #
# ============================================================ #
default_storage_engine = InnoDB
innodb_buffer_pool_size = 2G #4G # 8G # Use up to 70-80% of RAM & optionally check if /proc/sys/vm/swappiness is set to 0. Use Tuning Primer or MySQL Tuner to adjust accordingly.
innodb_file_per_table = 1
#--------------------------|
# 2 means log buffer is flushed to OS file cache on every transaction commit.
# The implication of 2 is optimal and improve performance
# if you are not concerning ACID and can lose transactions for last second or two in case of OS crashes
# -------------------------|
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_log_buffer_size = 16M
#---------------------------|
# Delete the ib_logfile0 & ib_logfile1 files in /var/lib/mysql whenever you change this,
# even the first time you set it up, as the default value is 8M.
# Don't go above 256M.
# ref: https://gist.github.com/wh4u/1fafe2bf98f630d7753717b5a8835bca
#---------------------------|
innodb_log_file_size = 256M
innodb_file_per_table=ON
innodb_stats_on_metadata = OFF
innodb_buffer_pool_instances = 8 #(or 1 if innodb_buffer_pool_size < 1GB)
#query_cache_type = 0
#query_cache_size = 0 #(disabling mutex)
#---------------|
# ref: http://techinfobest.com/optimize-mysql-table_open_cache/
# --------------|
table_open_cache=1501
#table_open_cache=30000
open_files_limit=3003
#open_files_limit=19107
#table_open_cache=39390
slow-query-log=0
long_query_time = 1
log-queries-not-using-indexes = 1
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
I noticed some parameters were double in the file so I commented out the duplicates. e.g. table_open_cache
was in two places under mysqld, one with value 256 and the other with value 39390.
Best Answer
table_open_cache=1501,open_files_limit=3003
(as suggested by Vasiliki) should be fine.Note: When
open_files_limit
is more thanulimit -n
, the former is lowered during startup. So, doSHOW VARIABLES LIKE 'open_files_limit';
to see what the setting really is. (Ditto fortable_open_cache
.)table_open_cache
is a "cache". As such, too-large a value will waste memory; too-small a value will slow certain things down. The value is the number of tables, not the number of bytes. 2000 is the median value used by over a hundred servers I polled. (10th percentile: 400; 90th percentile: 10000. Your 39390 is about 95th percentile--a red flag.) Set it to 1501 and forget it unless you are doing something really abnormal.ulimit -n
is a per-process file limit imposed by Linux (and its cousins). 1024 is the default in certain Operating System versions, and is a reasonable limit for casual programs. However, it is too low for MySQL, as has been discovered by many users doing non-trivial database work. It is, however, mostly a limit to keep you from going hog-wild in opening files. Setting it to 10000 is probably reasonable; that is helpful for MySQL, and not 'harmful'.open_files_limit
is initialized toulimit -n
. (I do not understand how you have 1024 and 19107. But note "[Warning] Changed limits: table_open_cache: 2419 (requested 39390)") But, again, this is merely a limit to keep the program from getting out-of-hand.table_open_cache
is the critical one in all this. However, you may be stopped from setting it because of the other two settings.But...
You asked about "high load" -- Almost always that comes from inefficient queries. Such can usually be fixed by improving indexing (think "composite") and/or reformulating queries. Let's have a look at a slow query and discuss it.
You showed a large number of processes. Please provide
SHOW VARIABLES LIKE 'max_connections';
It may be a default of 151, which is OK. (Note: this default has changed a few times based on version.) Consider lowering it to 50. Also, let's seeSHOW GLOBAL STATUS LIKE 'Max_used_connections';
If this is more than, say, 10, then that could be a symptom of other issues.You mention that memory keeps growing. Well, this is 'normal', but only to a point. The biggest user of RAM should be the buffer_pool;
innodb_buffer_pool_size = 2G
says that that part will grow until it occupies 2GB, then stop growing. The excessively large table cache (controlled bytable_open_cache
) is another memory user. (No, I don't know how many bytes in each entry.) Each "connection" consumes some memory. And connections are "cached", so my comments aboutmax_connections
indicate another memory consumer and way to control it. (Again, I don't know the per-connection memory usage.)The
htop
output does not back your "high load". You have 6 cores? And they average about 3-4%? On the other hand, Load average is more than 3? (I trust the CPU percentage more than the LA.) Again; let's look at a slow query; you "can't tune your way out of a performance problem".