web-dev-qa-db-ja.com

MySQLの何かが負荷を徐々に増加させ、ほとんどすべてのメモリを消費している

このサーバーには、データベースが1つあるサイトが1つだけあります。それでも、負荷を通常の状態に戻すために調整することはできません。

Mysqlサービスを再起動すると、メモリと負荷が通常に低下しますが、数日後、メモリと負荷は徐々に増加します。

サーバーの仕様

  • Centos 7
  • 合計メモリ7.8G
  • スワップ1G

htop出力

htop output

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

数日後のhtop出力

MySQLを再起動しない場合、これは3〜4日後に発生します

htop output

誰かが私を正しい方向に向けることができますか?

さらなる詳細

MySQLが少し後にクラッシュし、次のメッセージがログに記録されました。

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!

重複する質問の提案 で提供されている解決策を試しましたが、これにより状況がさらに悪化しました。サーバーは数分以内にメモリ不足になります。

[〜#〜]更新[〜#〜]

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]

Old database pages 多すぎる?どのような問題がありますか?

UPDATE#2これが、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/
# --------------|
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

一部のパラメーターがファイルで二重になっていることに気付いたので、重複をコメントアウトしました。例えばtable_open_cacheはmysqldの下の2つの場所にあり、1つは値256、もう1つは値39390でした。

3
Vasiliki

パフォーマンスの問題では、問題の原因が1つではありません。私が行ったすべての調整を書きます。うまくいけば、これは他の人にも役立つでしょう。みんなのコメントはとても役に立ちました、あなたは皆、解決策を見つける方法を示しました。

私はこれに従って ガイド 正しい数を計算しました。

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

リック・ジェームズは、以前の値が大きすぎることについて正しかった。

次に、次のパラメータが正しくありませんでした:

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 

wilson Hauckが示唆したように。

max_connectionsは150だったので、50に減らしました。

また、php-fpm構成には編集が必要でした。

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

公式ドキュメントに記載されている公式に常に従うことをお勧めします。

これらすべてにより、メモリが通常の使用に低下しました。しかし、CPU負荷はまだ高すぎました。

最後に、私はツールJetProfilerを使用しました。無料の version でも役立ちました。長く機能しているクエリを特定しました。素晴らしいことは、jetprofilerが提案を提供し、クエリを最適化できることです。

htopの見栄えが大幅に向上しました。

the-good-htop

1
Vasiliki

table_open_cache=1501,open_files_limit=3003(Vasilikiの提案どおり)で問題ありません。

注:open_files_limitulimit -nより大きい場合、前者は起動時に下げられます。したがって、SHOW VARIABLES LIKE 'open_files_limit';を実行して、設定reallyが何であるかを確認します。 (table_open_cacheの同上。)

table_open_cacheは「キャッシュ」です。そのため、値が大きすぎるとメモリが浪費されます。値が小さすぎると、特定のものが遅くなります。値はテーブルの数であり、バイト数ではありません。 2000は、私がポーリングした100を超えるサーバーで使用される中央値です。 (10パーセンタイル:400、90パーセンタイル:10000。39390は約95パーセンタイルです-赤い旗です。)1501に設定して、本当に異常なことをしているのでない限り、それを忘れてください。

ulimit -nは、Linux(およびその従兄弟)によって課されるプロセスごとのファイル制限です。オペレーティングシステムの特定のバージョンでは、1024がデフォルトであり、カジュアルなプログラムでは妥当な制限です。ただし、重要なデータベース作業を行う多くのユーザーが発見したように、MySQLには低すぎます。ただし、これはほとんどの場合、ファイルを開く際に大騒ぎしないようにするための制限です。 10000に設定するのはおそらく妥当です。これはMySQLに役立ち、「有害」ではありません。

open_files_limitulimit -nに初期化されます。 (あなたが1024と19107を持っている方法を私は理解していません。しかし、「[警告]変更された制限:table_open_cache:2419(39390を要求)」に注意してください)しかし、これもまた、プログラムが手に負えないようにするための制限にすぎません。 。

table_open_cacheは、このすべてにおいて重要です。ただし、他の2つの設定が原因で、設定が停止する場合があります。

だが...

「高負荷」について質問しました-ほとんどの場合、これは非効率的なクエリによるものです。これは通常、インデックスの改善(「複合」と考える)やクエリの再定式化によって修正できます。遅いクエリを見て、それについて説明しましょう。

多数のプロセスを示しました。 SHOW VARIABLES LIKE 'max_connections';を入力してください。デフォルトの151でかまいません。 (注:このデフォルトはバージョンに基づいて数回変更されています。)50に下げることを検討してください。また、SHOW GLOBAL STATUS LIKE 'Max_used_connections';を見てみましょう。これがたとえば10以上の場合は、他の問題の症状である可能性があります。

あなたは記憶が成長し続けると述べています。まあ、これは「正常」ですが、ある程度までです。 RAM should) buffer_pool; innodb_buffer_pool_size = 2Gの最大のユーザーは、その部分が2GBを占有するまで拡大し、その後、拡大を停止すると言います。極端に大きなテーブルキャッシュ(table_open_cacheによって制御されます)は別のメモリユーザーです(いいえ、各エントリのバイト数はわかりません)。各「接続」はメモリを消費します。接続は「キャッシュ」されるため、私のコメントmax_connectionsは、別のメモリコンシューマとそれを制御する方法を示します(ここでも、接続ごとのメモリ使用量はわかりません)。

htop出力は、「高負荷」に対応していません。 6つのコアがありますか?そして、彼らは平均して3-4%ですか?一方、負荷平均は3以上ですか? (私はLAよりもCPUの割合を信頼しています。)繰り返します。遅いクエリを見てみましょう。あなたは「パフォーマンスの問題からあなたの方法を調整することはできません」。

2
Rick James

My.cnf [mysqld]セクションで検討すべき提案

他の行で使用される他の値を持つ次の3行を削除します

innodb_file_per_table = 1
max_allowed_packet=100M
query_cache_size = 256M

変化する

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

サーバーの起動を停止します。 TOPの1ページ目を更新してください。

0
Wilson Hauck