【问题标题】:Mysql often crashes [duplicate]Mysql经常崩溃[重复]
【发布时间】:2013-08-10 00:09:10
【问题描述】:

我的Mysql服务器经常崩溃,我需要使用“service mysqld start”命令重启mysql。 我检查了mysql错误日志文件。

130807 22:59:47 mysqld_safe Number of processes running now: 0
130807 22:59:47 mysqld_safe mysqld restarted
130807 22:59:47 [Note] Plugin 'FEDERATED' is disabled.
130807 22:59:47 InnoDB: The InnoDB memory heap is disabled
130807 22:59:47 InnoDB: Mutexes and rw_locks use GCC atomic builtins
130807 22:59:47 InnoDB: Compressed tables use zlib 1.2.5
130807 22:59:47 InnoDB: Using Linux native AIO
130807 22:59:47 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
130807 22:59:47 InnoDB: Completed initialization of buffer pool
130807 22:59:47 InnoDB: Fatal error: cannot allocate memory for the buffer pool
130807 22:59:47 [ERROR] Plugin 'InnoDB' init function returned error.
130807 22:59:47 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
130807 22:59:47 [ERROR] Unknown/unsupported storage engine: InnoDB
130807 22:59:47 [ERROR] Aborting

130807 22:59:47 [Note] /usr/libexec/mysqld: Shutdown complete

130807 22:59:47 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

我有大约 10,000 个用户,并且我有一个包含 10,000 个表的数据库。这些表用于记录用户状态。而且,当我创建一个新的用户表时,我将以下代码与 PDO 一起使用。

$statusTable = "status_".$uid;
$qstr = "CREATE TABLE IF NOT EXISTS `status`.`$statusTable` (
    `prim_id` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `message` VARCHAR( 600 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
    `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE = INNODB";
$db->query($qstr);

这段代码会导致mysql崩溃吗?我使用 615MB 内存的 EC2 实例。谢谢!!

【问题讨论】:

  • 显然有些内存无法分配,所以你要么错误配置了 MySQL(也许尝试mariadb)或者没有足够的内存。顺便说一句,errno==12 表示ENOMEM
  • 10,000 张桌子??????每个用户一个??什么??我不知道这是否是您的问题,但它肯定不是好的数据库设计。
  • 同意 Supdley。您最多应该有几十张桌子(其中的数量是人为合理的)。如果硬件资源足够,其中一些可能很大(有数百万行)。
  • 我忍不住-1。每个用户一张桌子。只有在 PHP 世界中才会发生。
  • 所以...我最好将所有消息记录在一个大表中。当我需要获取用户的所有消息时,我会从这个大表中选择 uid = ?。对吗?

标签: mysql


【解决方案1】:

简单的回答:您不需要为每个用户创建一个新表来跟踪他们的状态。您正在使用他们的$uid,因此,您可以使用带有uid 列的单个表来跟踪他们的数据。然后当你想获取他们的数据时,使用$uid比如

SELECT * FROM user_data
WHERE uid=$uid

此外,您可以设置一个 cron 调度程序,以便在 MySQL 崩溃时重新启动它。

* * * * * 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

【讨论】:

    【解决方案2】:

    我认为问题在于您的数据库有许多并行连接,这导致了这个问题。问题不在于桌子,问题在于它周围的架构。

    【讨论】:

    • 是的,我有很多并行连接,但是如何改善这个问题?
    • 增加内存并添加交换,...​​
    • 每次交易完成后关闭连接!
    【解决方案3】:

    除了非常糟糕的数据库设计之外,您的问题/问题似乎以前是posted and answered

    【讨论】:

    • 好的。该链接类似于我的问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 2014-11-17
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多