Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


B.3.3.3 如果 MySQL 持续崩溃该怎么办

每个 MySQL 版本在发布前都经过了多种平台的测试。这并不意味着 MySQL 没有 bug,但如果有 bug,应该很少且难以找到。如果你遇到问题,总是帮助你快速解决问题,如果你能找到确切的问题原因。

首先,你应该尝试找出问题是否是 mysqld 服务器崩溃还是你的客户端问题。你可以通过执行 mysqladmin version 来检查 mysqld 服务器已经运行了多长时间。如果 mysqld 已经崩溃并重新启动,你可能可以在服务器错误日志中找到原因。见 第 7.4.2 节,“错误日志”

在某些系统上,你可以在错误日志中找到 mysqld 崩溃的栈追踪。注意,错误日志中写入的变量值可能不总是正确的。

如果您发现mysqld在启动时在 InnoDB 恢复过程中失败,请参阅第17.20.2节,“恢复故障排除”

许多意外的服务器退出是由损坏的数据文件或索引文件所致。MySQL 在每个 SQL 语句执行后使用 write() 系统调用将文件写入磁盘(除非您启用了delay_key_write 系统变量,在这种情况下数据文件被写入,但索引文件不被写入)。这意味着,即使mysqld崩溃,操作系统也会确保未刷新的数据被写入磁盘。您可以强制 MySQL 在每个 SQL 语句执行后将所有内容写入磁盘,通过使用mysqld 命令行选项 --flush

前面的意思是,通常情况下,您不应该出现损坏的表除非以下情况之一发生:

  • MySQL 服务器或服务器主机在更新过程中被杀死。

  • 您发现了mysqld 的bug,导致它在更新过程中崩溃。

  • 某外部程序正在同时操作数据文件或索引文件,而没有正确锁定表。mysqld

  • 您正在使用同一个数据目录的多个mysqld 服务,或者您在不支持文件系统锁定的系统上运行了多个服务,并且外部锁定已被禁用。

  • 您遇到了崩溃的数据文件或索引文件,该文件包含非常损坏的数据,混淆了mysqld

  • 您发现了存储引擎代码中的bug。这不太可能,但至少是可能的。在这种情况下,您可以使用ALTER TABLE在修复后的表副本上更换存储引擎。

因为很难知道什么原因会导致崩溃,首先尝试检查是否其他人也遇到了相同的问题。请尝试以下几件事:

  • 使用mysqld命令停止服务器,运行mysqladmin shutdown,从数据目录中运行myisamchk --silent --force */*.MYI来检查所有 MyISAM 表,然后重新启动mysqld。这样可以确保你从一个干净的状态运行。见第7章,MySQL 服务器管理.

  • 使用mysqld命令启动常规查询日志(见第7.4.3节,“常规查询日志”),然后尝试从日志中确定是否某个特定的查询杀死了服务器。通常,这是服务器重启前日志文件中的最后一个查询。见第7.4.3节,“常规查询日志”。如果你可以重复使用特定的查询杀死 MySQL,即使你在执行它前已经检查了所有表,那么你就找到了bug,应该提交一个bug报告。见第1.6节,“如何报告bug或问题”.

  • 尝试创建一个可以重复问题的测试用例。见第7.9节,“调试 MySQL”

  • 尝试使用 fork_big.pl 脚本。它位于源代码分发的 tests 目录中。

  • 为调试 MySQL 配置使得如果出现错误时更容易收集信息。使用-DWITH_DEBUG=1 选项重新编译 CMake,然后重新编译。见第7.9节,“调试 MySQL”

  • 确保已经应用了最新的操作系统补丁。

  • 使用--skip-external-locking选项来mysqld. 在某些系统上,lockd锁管理器不工作正常;--skip-external-locking选项告诉mysqld不要使用外部锁定。 (这意味着您不能在同一个数据目录上运行两个mysqld服务器,并且如果使用myisamchk,需要小心。然而,这也许是一个测试的好机会。)

  • 如果mysqld似乎在运行但未响应,尝试mysqladmin -u root processlist。有时mysqld即使未响应也可能不是挂起的状态。问题可能是所有连接都在使用,或者存在一些内部锁定问题。mysqladmin -u root processlist通常即使在这些情况下也能建立连接,并提供当前连接数和状态的有用信息。

  • 在另一个窗口中运行命令mysqladmin -i 5 statusmysqladmin -i 5 -r status,以在运行其他查询时生产统计信息。

  • 尝试以下操作:

    1. gdb(或另一个调试器)启动mysqld。见第7.9节,“调试 MySQL”

    2. 运行您的测试脚本。

    3. 打印回溯和局部变量的三个最低层次。在gdb中,您可以使用以下命令在mysqld崩溃时执行:

      backtrace
      info local
      up
      info local
      up
      info local

      使用gdb,您也可以使用info threads命令来检查存在的线程,然后使用thread N将线程切换到特定的线程,其中N是线程ID。

  • 尝试使用Perl脚本模拟您的应用程序,强制MySQL退出或不正常工作。

  • 发送一个正常的错误报告。见第1.6节,“报告错误或问题”。因为MySQL对很多人有效,崩溃可能是您的计算机上唯一存在的问题(例如,相关于您的特定系统库)。

  • 如果您遇到包含动态长度行的表问题,并且只使用VARCHAR列(不包括BLOBTEXT列),可以尝试将所有VARCHAR更改为CHAR使用ALTER TABLE。这样强制MySQL使用固定大小行。固定大小行需要一些额外空间,但对数据损坏更加容忍。

    当前动态行代码已经使用了几年,很少出现问题,但是动态长度行本质上更容易出错,所以尝试这个策略来看是否有帮助。

  • 在诊断问题时,考虑硬件故障的可能性。硬件故障可能是数据损坏的原因。在排查硬件故障时,特别注意内存和磁盘子系统。