我在 DigitalOcean droplet(1GB RAM)上托管了一个 WordPress 网站。该网站的 MySQL 数据库偶尔会崩溃,导致网站显示“建立数据库连接时出错”。内存使用量在凌晨 2:40 左右下降,表明这是数据库崩溃的时间。我检查了当天的 MySQL 日志文件,最早的条目是在上午 10:47。以下是日志文件的开头:
2021-12-06T10:47:14.800977Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timest$
2021-12-06T10:47:14.806192Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.36-0ubuntu0.18.04.1) starting as process 2810 ...
2021-12-06T10:47:14.819674Z 0 [Note] InnoDB: PUNCH HOLE support available
2021-12-06T10:47:14.819711Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2021-12-06T10:47:14.819716Z 0 [Note] InnoDB: Uses event mutexes
2021-12-06T10:47:14.819720Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2021-12-06T10:47:14.819723Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2021-12-06T10:47:14.819727Z 0 [Note] InnoDB: Using Linux native AIO
2021-12-06T10:47:14.820551Z 0 [Note] InnoDB: Number of pools: 1
2021-12-06T10:47:14.823342Z 0 [Note] InnoDB: Using CPU crc32 instructions
2021-12-06T10:47:14.825847Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2021-12-06T10:47:14.826246Z 0 [ERROR] InnoDB: mmap(137428992 bytes) failed; errno 12
2021-12-06T10:47:14.826258Z 0 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2021-12-06T10:47:14.826262Z 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error
2021-12-06T10:47:14.826270Z 0 [ERROR] Plugin 'InnoDB' init function returned error.
2021-12-06T10:47:14.826274Z 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2021-12-06T10:47:14.826278Z 0 [ERROR] Failed to initialize builtin plugins.
2021-12-06T10:47:14.826282Z 0 [ERROR] Aborting
2021-12-06T10:47:14.832237Z 0 [Note] Binlog end
2021-12-06T10:47:14.832297Z 0 [Note] Shutting down plugin 'CSV'
2021-12-06T10:47:14.832572Z 0 [Note] /usr/sbin/mysqld: Shutdown complete
根据日志文件,MySQL 似乎内存不足。但是,Droplet 的内存使用率一直稳定在 73% 左右,直到凌晨 2:40 左右数据库崩溃,内存使用率才降至 32%。似乎有足够的内存可用,那么为什么会崩溃呢?
编辑根据要求,以下是我的 MySQL 配置文件的内容:
/etc/mysql/conf.d/mysql.cnf
[mysql]
/etc/mysql/conf.d/mysqldump.cnf
[mysqldump]
quick
quote-names
max_allowed_packet = 16M
/etc/mysql/mysql.conf.d/mysqld.cnf
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
# Here is entries for some specific programs
# The following values assume you have at least 32M ram
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0
[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
#
# * Fine Tuning
#
key_buffer_size = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover-options = BACKUP
#max_connections = 100
#table_open_cache = 64
#thread_concurrency = 10
#
# * Query Cache Configuration
#
query_cache_limit = 1M
query_cache_size = 16M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
#slow_query_log = 1
#slow_query_log_file = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#server-id = 1
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem
/etc/mysql/mysql.conf.d/mysqld_safe_syslog.cnf
[mysqld_safe]
syslog
答案1
在查看聊天中的内核日志后,MySQL 崩溃的原因是内存不足。
Dec 6 02:47:13 kernel: [341799.228400] Out of memory: Kill process 23566 (mysqld) score 197 or sacrifice child
Dec 6 02:47:13 kernel: [341799.229866] Killed process 23566 (mysqld) total-vm:1168576kB, anon-rss:198536kB, file-rss:0kB, shmem-rss:0kB
在此期间,有大量 Apache2 进程处于活动状态。这意味着流量增加会导致内存消耗增加。因此,内核决定终止 MySQL 以释放内存。
可以运行mysqltuner
来分析 MySQL 配置。它会给出建议,有助于减少 MySQL 内存消耗。
但是,增加流量仍然会导致同样的问题。因此,更可持续的解决方案是增加 droplet 可用的内存。
答案2
1GB RAM 是非常微小这些天。服务器可能如果您设置了,则不会存活innodb_buffer_pool_size = 50M
。对于某些百分比的 RAM 的建议不适用于如此小的 RAM 大小。
50M 可能太小。请提供您的信息,my.cnf
以便我们寻找其他可以缩小的设置。以下是一些可能的设置:
max_connections = 10
key_buffer_size = 10M
temp_table_size = 10M
max_heap_table_size = 10M
table_open_cache = 100
query_cache_size = 0
max_allowed_packet = 8M
key_buffer_size = 10M
max_connections = 10
是的,MySQL/MariaDB 可以在小型机器上运行,但需要进行调整。
如果 Apache 在同一台服务器上运行,请将其 MaxRequestWorkers 降低到 10。并检查在同一台 [虚拟] 服务器中运行的任何其他程序的配置。