文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  如果 MySQL 不断崩溃该怎么办

B.3.3.3 如果 MySQL 不断崩溃该怎么办

每个 MySQL 版本在发布之前都会在许多平台上进行测试。这并不意味着 MySQL 中没有错误,但如果有错误,它们应该很少,并且很难找到。如果您遇到问题,尝试找出究竟是什么导致系统崩溃总是有帮助的,因为您有更大的机会快速解决问题。

首先,您应该尝试确定问题是 mysqld 服务器崩溃还是与您的客户端有关。您可以通过执行 mysqladmin version 来检查 mysqld 服务器的运行时间。如果 mysqld 已崩溃并重新启动,您可以在服务器的错误日志中找到原因。请参阅 第 7.4.2 节“错误日志”

在某些系统上,您可以在错误日志中找到 mysqld 崩溃位置的堆栈跟踪。请注意,错误日志中写入的变量值可能并不总是 100% 正确。

如果您发现 mysqldInnoDB 恢复期间启动失败,请参阅 第 17.20.2 节“故障排除恢复失败”

许多意外的服务器退出是由损坏的数据文件或索引文件引起的。MySQL 在每个 SQL 语句之后和客户端收到结果通知之前,使用 write() 系统调用更新磁盘上的文件。(如果您在启用了 delay_key_write 系统变量的情况下运行,则情况并非如此,在这种情况下,数据文件会被写入,但索引文件不会。)这意味着即使 mysqld 崩溃,数据文件内容也是安全的,因为操作系统会确保将未刷新的数据写入磁盘。您可以通过使用 --flush 选项启动 mysqld,强制 MySQL 在每个 SQL 语句之后将所有内容刷新到磁盘。

以上内容意味着,除非发生以下情况之一,否则通常不会出现损坏的表:

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

  • 您在 mysqld 中发现了一个错误,导致它在更新过程中崩溃。

  • 某些外部程序在 mysqld 运行时,在没有正确锁定表的情况下操作数据文件或索引文件。

  • 您在一个不支持良好文件系统锁(通常由 lockd 锁管理器处理)的系统上运行多个使用相同数据目录的 mysqld 服务器,或者您在禁用外部锁定的情况下运行多个服务器。

  • 您有一个崩溃的数据文件或索引文件,其中包含非常混乱的数据,导致 mysqld 出现混乱。

  • 您在数据存储代码中发现了一个错误。这不太可能,但至少有可能。在这种情况下,您可以尝试通过对修复后的表副本使用 ALTER TABLE 将存储引擎更改为其他引擎。

因为很难知道是什么原因导致崩溃,所以首先尝试检查对其他人有效的东西是否会导致您遇到意外退出。尝试以下操作:

  • 使用 mysqladmin shutdown 停止 mysqld 服务器,从数据目录运行 myisamchk --silent --force */*.MYI 以检查所有 MyISAM 表,然后重新启动 mysqld。这可以确保您从一个干净的状态开始运行。请参阅 第 7 章“MySQL 服务器管理”

  • 在启用常规查询日志的情况下启动 mysqld(请参阅 第 7.4.3 节“常规查询日志”)。然后尝试从写入日志的信息中确定是哪个特定查询导致服务器崩溃。大约 95% 的错误都与某个特定查询有关。通常,这是服务器重新启动之前日志文件中的最后几个查询之一。请参阅 第 7.4.3 节“常规查询日志”。如果您可以在发出某个特定查询之前检查所有表,但仍然可以重复导致 MySQL 崩溃,那么您已经隔离了该错误,应该为此提交错误报告。请参阅 第 1.6 节“如何报告错误或问题”

  • 尝试创建一个我们可以用来重现问题的测试用例。请参阅 第 7.9 节“调试 MySQL”

  • 尝试运行 fork_big.pl 脚本。(它位于源代码发行版的 tests 目录中。)

  • 配置 MySQL 以进行调试,以便在出现问题时更轻松地收集有关可能错误的信息。使用 -DWITH_DEBUG=1 选项重新配置 MySQL 到 CMake,然后重新编译。请参阅 第 7.9 节“调试 MySQL”

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

  • mysqld 使用 --skip-external-locking 选项。在某些系统上,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 中,当 mysqldgdb 内部崩溃时,可以使用以下命令执行此操作

      backtrace
      info local
      up
      info local
      up
      info local

      使用 gdb,您还可以使用 info threads 检查哪些线程存在,并使用 thread N 切换到特定线程,其中 N 是线程 ID。

  • 尝试使用 Perl 脚本模拟您的应用程序,以强制 MySQL 退出或出现异常行为。

  • 发送正常的错误报告。请参阅 第 1.6 节 “如何报告错误或问题”。比平时更加详细。因为 MySQL 对许多用户都有效,所以崩溃可能是由您的计算机上才有的东西引起的(例如,与您的特定系统库相关的错误)。

  • 如果您在包含动态长度行的表中遇到问题,并且仅使用 VARCHAR 列(不使用 BLOBTEXT 列),则可以使用 ALTER TABLE 将所有 VARCHAR 更改为 CHAR。这会强制 MySQL 使用固定大小的行。固定大小的行会占用一些额外的空间,但对损坏的容忍度要高得多。

    当前的动态行代码已经使用了几年,很少出现问题,但动态长度行本质上更容易出错,因此尝试这种策略看看它是否有帮助可能是个好主意。

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