【问题标题】:Amazon EC2, mysql aborting start because InnoDB: mmap (x bytes) failed; errno 12Amazon EC2,mysql 中止启动,因为 InnoDB:mmap(x 字节)失败;错误号 12
【发布时间】:2012-05-04 07:12:01
【问题描述】:

我有一个基于this的EC2上的微型实例服务器@

mysql server 经常出现故障,mysql server 第三次不见了。日志只显示

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

【问题讨论】:

  • 我的 EC2 微型实例也有同样的问题。试过设置 innodb_buffer_pool_size=128M 看看效果如何。
  • 如果您使用的是微型实例,您可能需要添加交换空间:prowebdev.us/2012/05/amazon-ec2-linux-micro-swap-space.html
  • EC2 微实例默认没有交换空间,需要手动设置。否则你可能会看到大量的 MySQL 因内存不足而崩溃。

标签: mysql amazon-ec2


【解决方案1】:

看起来您为帖子中显示的 my.cfg 文件中的 innodb_buffer_pool_size 请求 128M 内存,但 MySQL 认为您请求 512M记忆:

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

几行之后,错误消息告诉您 MySQL 将无法启动,因为它无法为 InnoDB 缓冲池保留足够的 (512M) 内存:

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

这引出了三个问题:

  1. 您的实例有多少内存?是否应该有足够的内存来容纳 512M InnoDB 试图为缓冲池抓取,加上 MySQL 分配的所有其他内容,加上您的应用程序和操作系统?
  2. 为什么 InnoDB 试图采取的措施超出您的预期?
  3. 为什么 MySQL 会重新启动?

你可以回答1。

至于 2.,有几个不同的地方可以找到 MySQL 选项文件。随后找到的文件会覆盖先前找到的文件中指定的选项。见

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

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

最后,但有些无关紧要,您使用的是 EBS 支持的实例吗?这通常强烈建议用于数据库服务器(实际上,对于任何情况,除非有特殊情况)。有关更多信息,请参阅

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

【讨论】:

    【解决方案2】:

    我在 Amazon EC2 微型实例上也遇到了这个问题。我尝试通过将以下内容添加到 /etc/my.cnf 来减少 inno_db 的内存使用量

    innodb_buffer_pool_size = 64M

    这不起作用,我尝试将其降低到 16M,但仍然不起作用。然后我意识到该实例的可用内存基本上为零。所以我尝试重新启动apache

    sudo 系统 httpd 重启 sudo 系统 mysqld 重启

    一切正常。也许另一种解决方案是将 apache 配置为不以某种方式占用这么多内存。

    【讨论】:

    • MySQL 可能仍会崩溃,因此您可能需要向微实例添加交换空间。
    • 谢谢,有道理。我想我也可以尝试限制 apache 可以产生的线程数。
    • 效果很好。我也有这个问题,通过重新启动 httpd 解决了这个问题。
    • 很棒的收获,同样的船。我将我的 apache 设置为使用更少的 ram,并创建了一个 512m 的交换文件,但将 vm.swappiness 设置为 10,这样它只会在紧要关头使用。
    • 重启nginx和php-fpm也释放了足够的内存让mysql启动!谢谢!
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      添加交换页面为我解决了这个问题。

      您可以按照以下步骤设置交换空间。

      如果还是不行,请考虑使用 RDS 服务。

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

      我复制了博客的内容以作记录。归功于博客作者pmoubed

      Amazon EC2 微实例交换空间 - Linux

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

      以下步骤展示了如何为您的 Micro 实例创建交换空间。我假设您有 AWS 账户,并且正在运行 Micro 实例。

      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

      如果您想在每次重启后自动启用交换文件,则需要第 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/

      【讨论】:

      • 仅供参考,这对我来说适用于 Digital Ocean 液滴 (512 MB)。并不是说这会让任何人感到惊讶,但如果有人不确定,它可能会在任何有相同问题的服务器上工作。
      • 感谢您的救命之恩!还在使用 Ubuntu Server 运行一个微型实例。
      • 对于 Digital Ocean 用户,我按照本教程进行操作,效果非常好:digitalocean.com/community/articles/…
      • 非常感谢。在过去的 24 小时里一直在拉我的头发,玩各种缓冲区/缓存/查询大小.. 你是救生员!
      • 这里是另一个很好的信息来源:support.rackspace.com/how-to/create-a-linux-swap-file
      【解决方案5】:

      使用以下任一解决方案:

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

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

      配置

      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
      

      【讨论】:

        【解决方案6】:

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

        (1) 增加物理内存。添加 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

        【讨论】:

          【解决方案7】:

          简单的答案:

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

          详细回答:

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

          还有其他几个讨论 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 
          

          将完成重新启动该过程的技巧。您可以 cron:

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

          但是,如果 mysql 已加载,但服务未激活,您的 cron 将什么也不做。因此,您应该使用更详细的命令,例如:

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

          这种情况下,如果服务loadedinactive比如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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-30
            • 1970-01-01
            • 2012-07-30
            • 2020-01-29
            • 1970-01-01
            • 2020-08-16
            • 2011-06-24
            • 2013-11-30
            相关资源
            最近更新 更多