web-dev-qa-db-fra.com

Quelque chose dans MySQL provoque une charge progressivement élevée qui consomme presque toutes la mémoire

J'ai ce serveur qui n'a qu'un seul site avec une base de données sur elle. Et pourtant, je ne peux pas le modifier pour que la charge remonte à la normale.

Si je redémarre le service MySQL, la mémoire et la charge descendent à la normale, mais quelques jours plus tard, la mémoire et la charge augmentent progressivement.

Spécifications de serveur

  • Centos 7
  • mémoire totale 7.8g
  • échanger 1G

sortie htop

htop output

Version mysql

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

sortie HTOP après quelques jours

Si je ne redémarre pas MySQL, c'est ce qui se passe après 3-4 jours

htop output

Quelqu'un peut-il me dire à la bonne direction s'il vous plaît?

Détails supplémentaires

MySQL s'est écrasé un peu plus tard avec des messages suivants dans le journal:

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!

J'ai essayé la solution fournie dans la suggestion de questions en double , mais cela a aggravé les choses. Le serveur manque de mémoire en quelques minutes.

[~ # ~ ~] Mise à jour [~ # ~]

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]

Sommes Old database pages trop? Quels problèmes voyez-vous?

Mise à jour n ° 2 Voici ce que my.cnf ressemble au 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

J'ai remarqué que certains paramètres étaient doubles dans le fichier, donc j'ai commenté les duplicats. par exemple. table_open_cache était à deux endroits sous MySQLD, une avec valeur 256 et l'autre avec la valeur 39390.

3
Vasiliki

Avec des problèmes de performance, ce n'est jamais une chose qui cause le problème. J'écrirai tout ce que je faisais et j'espère que cela aidera les autres aussi. Les commentaires de tous étaient Soooo utiles, vous avez tous montré la voie à la recherche de la ou des solutions.

J'ai suivi ce guide pour calculer les numéros corrects.

mysql> show global status  like 'open%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| Open_files               | 43    |
| Open_streams             | 0     |
| Open_table_definitions   | 375   |
| Open_tables              | 2288  |
| Opened_files             | 6842  |
| Opened_table_definitions | 376   |
| Opened_tables            | 3286  |
+--------------------------+-------+

mysql> SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE';
+----------+
| COUNT(*) |
+----------+
|      273 |
+----------+

mysql> show global status like '%Threads_connected%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 11    |
+-------------------+-------+

Table_open_cache = total_tables*Threads_connected
                    = 273 * 11
                    = 3003


table_open_cache=1501
open_files_limit=3003

Rick James était juste à propos des valeurs précédentes étant trop grande.

Ensuite, les paramètres suivants n'étaient pas corrects:

sort_buffer_size = 256   (Default value: 262144, as per official documentation)
read_buffer_size = 256    (Better 128K)
read_rnd_buffer_size = 40     (Default Value: 262144, as per official documentation) 

reasonable alternatives are: 
sort_buffer_size=512K 
read_buffer_size=256K 
read_rnd_buffer_size=128K 

comme Wilson Hauck a suggéré.

max_connections étaient 150 donc j'ai réduit à 50.

En outre, PHP-FPM Configuration requise Édition nécessaire.

pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35


pm.start_servers= min_spare_servers + (max_spare_servers - min_spare_servers) / 2

changing to 
pm.max_children = 25
pm.start_servers = 11
pm.min_spare_servers = 5
pm.max_spare_servers = 17

Il est préférable de toujours suivre les formules fournies dans la documentation officielle.

Tout cela a apporté une mémoire à une utilisation normale. Mais la charge du processeur était toujours trop élevée.

Dernier, mais non le moindre, j'ai utilisé l'outil Jetprofiler . Même le free version aidé. J'ai identifié les requêtes qui travaillaient juste depuis trop longtemps. La grande chose est que JetProfiler vous donne même une suggestion et vous pouvez optimiser la requête.

Maintenant, htop regarde beaucoup mieux.

the-good-htop

1
Vasiliki

table_open_cache=1501,open_files_limit=3003 (comme suggéré par Vasiliki) devrait être bien.

Remarque: quand open_files_limit est plus que ulimit -n, le premier est abaissé lors du démarrage. Alors faites SHOW VARIABLES LIKE 'open_files_limit'; Pour voir ce que le réglage vraiment est. (Idem pour table_open_cache.)

table_open_cache est un "cache". En tant que tel, une valeur trop importante va gaspiller la mémoire; Trop petit, une valeur va ralentir certaines choses. La valeur est le nombre de tables et non le nombre d'octets. 2000 est la valeur médiane utilisée par plus d'une centaine de serveurs que j'ai écris. (10e centile: 400; 90e centile: 10000. Votre 39390 est d'environ 95e centile - un drapeau rouge.) Définissez-le à 1501 et oubliez-le si vous ne faites que quelque chose de vraiment anormal.

ulimit -n est une limite de fichier per-processus imposée par Linux (et ses cousins). 1024 est la valeur par défaut dans certaines versions du système d'exploitation et constitue une limite raisonnable pour les programmes occasionnels. Cependant, il est trop basse pour MySQL, comme il a été découvert par de nombreux utilisateurs qui font des travaux de base de données non triviaux. Cependant, il s'agit principalement d'une limite pour vous empêcher de passer au porc-sauvage dans l'ouverture de fichiers. La définition à 10000 est probablement raisonnable; C'est utile pour MySQL, et pas "nocif".

open_files_limit est initialisé à ulimit -n. (Je ne comprends pas comment vous avez 1024 et 19107. MAIS NOTE "[AVERTISSEMENT] Modification des limites: TABLE_OPEN_CACHACHE: 2419 (Demande 39390)") Mais, encore une fois, cela ne signifie qu'une limite pour empêcher le programme de devenir hors de portée .

table_open_cache est la critique dans tout cela. Cependant, vous pouvez être arrêté de la définir à cause des deux autres paramètres.

Mais...

Vous avez posé une question sur "Haute charge" - presque toujours qui provient des requêtes inefficaces. Tels peuvent généralement être fixés en améliorant l'indexation (réfléchir à des requêtes composites ") et/ou reformulant. Regardons une recherche lente et discutons.

Vous avez montré un grand nombre de processus. Veuillez donner SHOW VARIABLES LIKE 'max_connections'; Cela peut être une valeur par défaut de 151, ce qui est correct. (Remarque: cette valeur par défaut a changé quelques fois en fonction de la version.) Envisagez de l'abaisser à 50. Aussi, voyons SHOW GLOBAL STATUS LIKE 'Max_used_connections'; Si cela est plus que, disons, 10, alors cela pourrait être un symptôme d'autres problèmes.

Vous mentionnez que la mémoire continue de croître. Eh bien, ceci est "normal", mais seulement à un point. Le plus gros utilisateur de RAM devrait être le buffer_pool; innodb_buffer_pool_size = 2G dit que cette partie augmentera jusqu'à ce qu'elle occupe 2 Go, puis arrêtez de croître. Le cache de table excessivement grand (contrôlé par table_open_cache) est un autre utilisateur de mémoire. (Non, je ne sais pas combien d'octets dans chaque entrée.) Chaque "connexion" consomme de la mémoire. Et les connexions sont "mises en cache", alors mes commentaires sur max_connections Indiquez un autre consommateur de mémoire et un autre moyen de le contrôler. (Encore une fois, je ne connais pas l'utilisation de la mémoire par connexion.)

La sortie htop ne recule pas votre "charge élevée". Vous avez 6 noyaux? Et ils en moyenne environ 3-4%? D'autre part, la moyenne de la charge est supérieure à 3? (Je fais confiance au pourcentage de la CPU plus que la LA.) Encore; Regardons une requête lente; Vous "ne peut pas régler votre moyen de sortir d'un problème de performance".

2
Rick James

Suggestions à prendre en compte pour votre section my.cnf [mysqld]

Supprimer les 3 lignes suivantes qui ont d'autres valeurs à utiliser sur d'autres lignes

innodb_file_per_table = 1
max_allowed_packet=100M
query_cache_size = 256M

CHANGEMENT

read_buffer_size=256K  # from 256 to improve performance
read_rnd_buffer_size=128K  # from 40 bytes to improve performance
sort_buffer_size=512K  # from 256 bytes to improve performance
thread_cache_size=32  # from 8 to reduce threads_created count

arrêtez de démarrer votre serveur. Publier une nouvelle page de 1ère page de haut.

0
Wilson Hauck