【问题标题】:Can `mysqlcheck` help me resolve database problems without damaging my database?`mysqlcheck` 能否在不损坏数据库的情况下帮助我解决数据库问题?
【发布时间】:2025-12-13 21:45:01
【问题描述】:

背景

我有一个 Drupal 站点,其中包含一个由 phpmyadmin 管理的数据库。该数据库的大小超过 1500 个表。我在速度方面遇到了很大的问题,正在寻找一个好的解决方法。该数据库已有 2.5-3 年的历史,从未维护过(据我所知)。

研究

我一直试图找到一种方法来加快速度,但一切都让我回到了数据库的纯大小。我遇到了命令

OPTIMIZE TABLE
tbl_name [, tbl_name] ...

女巫很快带我去更强大的地方

mysqlcheck -o <db_schema_name>

因为我们只有一个数据库,所以我没有可以使用此命令的测试区域。我知道在我的数据库上运行这个命令需要很长时间,由于数据库的庞大规模,可能需要几天时间。

推理

我想使用它的原因是因为 MySQL 似乎每天都会关闭或崩溃。在 phpmyadmin 我看到了这个

它只启动了 9 小时,自从我 1 个月前开始工作以来,我还没有关闭它。似乎永远不会超过 15 小时。

状态变量

这是将值显示为警报的状态变量列表,我希望通过 mysqlcheck 修复其中的一些。

结论

我想知道在数据库上运行 mysqlcheck 是否会导致任何问题或损坏我数据库中的任何数据。了解这样的操作需要多长时间也很方便。

【问题讨论】:

  • 你确认不是OOMing吗?
  • 登录尝试失败的次数也是惊人的,你确定不是有人试图强行进入吗?
  • 对不起,“OOMing”这个词也指的是什么?因为我在想的只是魔兽世界中的治疗师大喊“我是OOM,我是OOM,不要拉!!!”
  • 你最好在 DBA * 论坛上发布这个。
  • 当服务器内存不足时,内核会杀掉最大的进程。 Mysql 不只是自行重启。错误日志说什么?你做过最基本的故障排除吗? os 日志、db 日志中是否有任何内容?有没有足够的内存。机器是否正在重新启动......等等等等。

标签: mysql database


【解决方案1】:

答案的第一部分是好消息...mysqlcheck -o 不会比在每个表上运行 OPTIMIZE TABLE 更可能损害您的数据库,因为 这就是它的全部作用。 这是一个方便的实用程序,它可以登录到服务器,获取表列表,然后遍历它们,一次向服务器发送一个OPTIMIZE TABLE 查询以获取一个表,直到完成为止。

现在,一些坏消息。如果您的表空间中存在潜在损坏,OPTIMIZE TABLE 可能会遇到这种情况,因此您应该确定您已为这种可能性做好准备,并准备好备份和恢复计划。这种可能性很小,但 一种可能的结果。

更坏的消息:几乎可以肯定是找错了树。

在同一台机器上同时运行 Apache 和 MySQL 并带来大量流量(或显着流量变化)是违反最佳做法的,而且会导致问题,因为这两种服务在负载下往往会增加内存消耗,并且如果数据库是网站数据的后备存储,则增加的负载往往会同时发生在两个服务上。

请参阅我对 InnoDB Crash Post Mortem on Database Administrators Stack ExchangeWhy is Apache Running Wild and Killing MySQL on Server Fault 的回答,以全面了解这个相当普遍的问题,其中 MySQL 是受害者,比什么都重要。

请注意,您是否使用 InnoDB 并不重要。 MySQL 错误日志中的数据库恢复条目会有所不同,但最重要的是:在没有任何可疑之处之前,MySQL 错误日志显示:

mysqld_safe Number of processes running now: 0

紧随其后的消息经常被误解为 MySQL“崩溃”,但事实并非如此……它已被杀死。 MySQL 甚至可能拒绝重新启动,直到 Apache 平静下来或重新启动,或者服务器重新启动。同样,从错误日志中,您可能会也可能不会看到类似这样的内容:

InnoDB: Initializing buffer pool, size = 4.0G
InnoDB: mmap(4395630592 bytes) failed; errno 12
InnoDB: Completed initialization of buffer pool
InnoDB: Fatal error: cannot allocate memory for the buffer pool
[ERROR] Aborting
[Note] /usr/libexec/mysqld: Shutdown complete
mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

检查/var/log/syslog/var/log/messages(取决于您运行的发行版)将显示真正的问题。

$ sudo egrep 'kernel|oom' /var/log/syslog

...或messages...应该显示一些以这样开头的条目:

kernel: pcscd invoked oom-killer: gfp_mask=0xd0, order=0, oomkilladj=0

Apache 的内存消耗如此之大,以至于系统面临整体不稳定的风险,因此牺牲了“某些东西”。那个“东西”很可能是 MySQL 服务器守护进程mysqld

kernel: Out of memory: Killed process 3044, UID 27, (mysqld)

MySQL 通常会尝试自行重新启动,就您所知,这也可能偶尔会发生……但除非 Apache 的内存需求迅速下降,否则不允许 MySQL 从系统请求足够的内存,并且会放弃。

优化桌子有其有效的应用...但是,在这种情况下,如果我正确地识别了您的问题,这将非常类似于在沉没的船上重新布置躺椅 泰坦尼克号。 它可能会为您节省一些磁盘空间,但在运行时也会花费您一些备用磁盘空间,因为某些存储引擎会创建一个全新的表副本,然后重命名副本并删除旧表。无论如何,它不太可能对内存消耗产生任何有意义的影响。

【讨论】:

  • 这正是我想要的,再次感谢迈克尔。你给了我一些新的线索来追求和更多地煽动我的数据库。非常详细的答案。