Amazon EC2,mysql中止启动因为InnoDB:mmap(x bytes)失败; errno 12

时间:2012-04-23 16:33:17

标签: mysql amazon-ec2

我已根据我阅读here

的内容在EC2上设置了实例服务器

mysql服务器频繁失败,第三次mysql服务器消失了。日志仅显示

120423 09:13:38 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
120423 09:14:27 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120423  9:14:27 [Note] Plugin 'FEDERATED' is disabled.
120423  9:14:27 InnoDB: The InnoDB memory heap is disabled
120423  9:14:27 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120423  9:14:27 InnoDB: Compressed tables use zlib 1.2.3
120423  9:14:27 InnoDB: Using Linux native AIO
120423  9:14:27 InnoDB: Initializing buffer pool, size = 512.0M
InnoDB: mmap(549453824 bytes) failed; errno 12
120423  9:14:27 InnoDB: Completed initialization of buffer pool
120423  9:14:27 InnoDB: Fatal error: cannot allocate memory for the buffer pool
120423  9:14:27 [ERROR] Plugin 'InnoDB' init function returned error.
120423  9:14:27 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
120423  9:14:27 [ERROR] Unknown/unsupported storage engine: InnoDB
120423  9:14:27 [ERROR] Aborting

真正的failed; errno 12是什么?我怎么能提供更多的空间/内存或任何需要修复它的东西。

我每次都通过重新启动整个系统并删除所有日志并重新启动mysql服务器来解决这个问题。但我知道我的配置有问题。

我的`my.cnf'如下所示:

[mysqld]
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
# max_allowed_packet=500M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0


innodb_buffer_pool_size         = 512M


[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

7 个答案:

答案 0 :(得分:160)

当我尝试在没有RDS的微型实例上运行wordpress时遇到了同样的问题。

添加一个Swap页面为我解决了这个问题。

您可以按照以下步骤设置交换页面:

http://www.prowebdev.us/2012/05/amazon-ec2-linux-micro-swap-space.html

如果它仍然不适合您,请考虑使用RDS服务。

===============================================

博客链接有时会失败。我复制了以下内容以备记录。感谢博客作者Pedram Moubed

Amazon EC2微实例交换空间 - Linux

我有一个Amazon EC2 Linux Micro实例。由于Micro实例只有613MB的内存,因此MySQL偶尔会崩溃。在对MySQL,Micro Instance和Memory Managment进行了长时间的搜索后,我发现Micro实例没有默认的SWAP空间。因此,如果您想避免崩溃,可能需要为微实例设置交换空间。实际上,性能明智更好地启用交换。

以下步骤显示如何为Micro实例创建交换空间。我假设你有一个运行Micro实例的AWS账户。

  1. 运行dd if=/dev/zero of=/swapfile bs=1M count=1024
  2. 运行mkswap /swapfile
  3. 运行swapon /swapfile
  4. 将此行/swapfile swap swap defaults 0 0添加到/etc/fstab
  5. 如果您想在每次重启后自动启用交换文件,则需要执行步骤4。

    与SWAP空间相关的一些有用命令:

    $ swapon -s   
    $ free -k
    
    $ swapoff -a
    $ swapon  -a
    

    参考文献:

    1. http://www.thegeekstuff.com/2010/08/how-to-add-swap-space/
    2. http://cloudstory.in/2012/02/getting-the-best-out-of-amazon-ec2-micro-instances/
    3. http://cloudstory.in/2012/02/adding-swap-space-to-amazon-ec2-linux-micro-instance-to-increase-the-performance/
    4. http://aws.amazon.com/ec2/instance-types/

答案 1 :(得分:23)

我在Amazon EC2微型实例上也遇到了这个问题。我尝试通过将以下内容添加到/etc/my.cnf

来减少inno_db的内存使用量
innodb_buffer_pool_size = 64M

那不起作用,我试着把它降到16M但它仍然没有用。然后我意识到实例基本上没有可用内存。所以我尝试重启apache

sudo system httpd restart
sudo system mysqld restart

一切都很好。也许另一种解决方案是将apache配置为不会以某种方式占用太多内存。

答案 2 :(得分:4)

看起来你要在帖子中显示的my.cfg文件中为innodb_buffer_pool_size请求 128M 内存,但MySQL认为你要求 512M 存储器:

  

初始化缓冲池,大小= 512.0M

几行下来,错误消息告诉你MySQL无法启动,因为它无法为InnoDB缓冲池预留足够的(512M)内存:

  

致命错误:无法为缓冲池分配内存

这引出了三个问题:

  1. 您的实例上有多少内存?是否有足够的内存来容纳512M InnoDB试图获取缓冲池,以及MySQL分配的所有内容,以及您的应用程序和操作系统?
  2. 为什么InnoDB会比你想象的更多?
  3. 为什么MySQL重启无论如何?
  4. 你可以回答1.

    对于2.,可以找到MySQL选项文件的几个不同位置。随后找到的文件覆盖先前找到的文件中指定的选项见

    http://dev.mysql.com/doc/refman/5.5/en/option-files.html

    问题3.可能是由于启动后某个时间发生内存不足的情况。如果是这种情况,您应该在日志中看到更多的指示。

    最后,但有些不相关,您使用的是EBS支持的实例吗?这通常强烈推荐用于数据库服务器(实际上,除了特殊情况之外的任何实例)。有关详细信息,请参阅

    https://stackoverflow.com/a/3630707/141172

答案 3 :(得分:2)

对我来说,通过向我的EC2实例添加交换卷来解决这个问题。我的服务只是消耗了盒子上的所有内存,并且会崩溃。不是我习惯的东西,多年来一直是RedHat / CentOS管理员--Anaconda做了大量的工作,免费的Ubuntu EC2实例没有。

我只是通过Web控制台创建了一个2Gb卷,将它附加到我的实例,然后执行了“mkswap / dev / [whatever]”,编辑了/ etc / fstab,并且崩溃停止了。

这些实例不像我们大多数人习惯的基于媒体的操作系统安装那样安装 - 它没有包,没有适当的文件系统,以及像AppArmor这样的东西被剥离,如果你不是这样的话会导致各种各样的问题意识到它和/或不知道如何配置它。

答案 4 :(得分:0)

使用以下解决方案中的任何一种:

  1. 增加物理RAM。添加1GB的额外RAM将解决问题。

  2. 使用以下配置更改分配SWAP空间:

  3. <强>配置

    dd if=/dev/zero of=/extraswap bs=1024 count=512M
    mkswap  /extraswap 
    swapon  /extraswap 
    ## Edit the /etc/fstab, and the following entry.
    /extraswap      none    swap    sw      0       0
    

答案 5 :(得分:0)

问题是服务器没有足够的内存来分配MySQL进程。这个问题有一些解决方案。

(1)增加物理RAM。添加1GB的额外RAM将解决此问题。 (2)分配SWAP空间。默认情况下,Digital Ocean VPS实例未配置为使用交换空间。通过分配512MB的交换空间,我们能够解决这个问题。要向服务器添加交换空间,请按照以下步骤操作:

## As a root user, perform the following:
# dd if=/dev/zero of=/swap.dat bs=1024 count=512M
# mkswap /swap.dat
# swapon /swap.dat
## Edit the /etc/fstab, and the following entry.
/swap.dat      none    swap    sw      0       0 

减小MySQL缓冲池大小的大小

## Edit /etc/my.cnf, and add the following line under the [mysqld] heading.
[mysqld]
innodb_buffer_pool_size=64M

另请检查您的磁盘空间。确保你有足够的空间。

df-h

答案 6 :(得分:0)

简单答案:

* * * * * systemctl is-active --quiet mysqld || systemctl restart mysqld

详细答案:

这是一个重要的问题,特别是对于使用非常小的VPS(例如1GB或更少的RAM)的用户。如果MySQL退出,则可能是服务器配置(Apache | nginx)或MySQL配置有问题。 DOS攻击可能导致系统资源使用率增加(见图)。最终结果是MySQL进程被内核关闭。对于长期解决方案,应该考虑优化您的Apache或MySQL配置。

System resources spike causing RAM spike (just before 6pm) and system resources spike causing only a CPU spike Midnight on Tue 18

还有其他一些关于Stack Overflow这些主题的讨论,以及MySQL手册和Percona博客:

MySQL手册-MySQL如何使用内存:

https://dev.mysql.com/doc/refman/8.0/en/memory-use.html

Percona-配置最佳MySQL内存使用的最佳做法:

https://www.percona.com/blog/2016/05/03/best-practices-for-configuring-optimal-mysql-memory-usage/

如何使用MySQLTuner优化MySQL性能:

https://www.linode.com/docs/databases/mysql/how-to-optimize-mysql-performance-using-mysqltuner/

Apache内存使用情况配置:

https://serverfault.com/questions/254436/apache-memory-usage-optimization

Apache性能调整手册:

https://httpd.apache.org/docs/2.4/misc/perf-tuning.html

调整Apache服务器:

https://www.linode.com/docs/web-servers/apache-tips-and-tricks/tuning-your-apache-server/

但是,关于您的原始问题,是的,您可以编写一个临时解决方案的脚本,以检查MySQL服务是否已加载并处于活动状态,如果未加载并处于活动状态则将重新启动MySQL。

您没有提及正在使用的操作系统。这将有助于给您特定的命令。我会给你一个CentOS linux的例子。
查看命令systemctl status mysql的以下输出。您可以在顶部看到该服务已加载活动

[root@centos-mysql-demo ~]# systemctl status mysqld
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-06-18 18:28:18 UTC; 924ms ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3350 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS)
  Process: 3273 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 3353 (mysqld)
   CGroup: /system.slice/mysqld.service
           └─3353 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

Jun 18 18:28:11 centos-mysql-demo systemd[1]: Starting MySQL Server...
Jun 18 18:28:18 centos-mysql-demo systemd[1]: Started MySQL Server.

如果未加载该服务,则显示以下命令:

systemctl status mysqld || systemctl restart mysqld 

将完成重新启动过程的技巧。您可以提出以下建议:

* * * * * systemctl status mysqld || systemctl restart mysqld

但是,如果mysql已加载,但服务未活动,则您的cron将不执行任何操作。因此,您应该使用更详细的命令,例如:

* * * * * systemctl is-active --quiet mysqld || systemctl restart mysqld

在这种情况下,如果服务已加载无效,例如DOS攻击可能离开您的mysql服务的状态,则该命令还将重新启动mysql。使用--quiet标志仅指定命令仅返回状态代码,而不向屏幕输出任何内容。如果省略--quiet标志,您将看到activeinactive的状态输出。

您还可以创建一些交换空间,以向服务器添加更多可用的RAM资源,例如:

sudo dd if=/dev/zero of=/swapfile count=2096 bs=1MiB
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon --show
swapon --summary
free -h