Documentation Home

B.3.3.3 MySQL 老是崩溃怎么办

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

首先,您应该尝试找出问题是否出在mysqld服务器死机或您的问题是否与您的客户端有关。您可以通过执行mysqladmin version检查您的mysqld服务器已经运行了 多长时间。如果 mysqld 死机并重新启动,您可以通过查看服务器的错误日志找到原因。请参阅 第 5.4.2 节,“错误日志”

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

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

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

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

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

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

  • 某些外部程序在未正确锁定表的情况下 与mysqld 同时操作数据文件或索引文件。

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

  • 您有一个崩溃的数据文件或索引文件,其中包含使mysqld感到困惑的非常损坏的数据。

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

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

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

  • 在启用通用查询日志的情况下启动mysqld(请参阅第 5.4.3 节,“通用查询日志”)。然后尝试根据写入日志的信息确定是否某些特定查询杀死了服务器。大约 95% 的错误都与特定查询有关。通常,这是服务器重新启动之前日志文件中的最后查询之一。请参阅第 5.4.3 节,“一般查询日志”。如果你可以用一个特定的查询重复地杀死 MySQL,即使你在发出它之前检查了所有的表,那么你就已经隔离了这个错误并且应该为它提交一个错误报告。看第 1.6 节,“如何报告错误或问题”

  • 尝试制作一个我们可以用来重复问题的测试用例。参见第 5.9 节,“调试 MySQL”

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

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

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

  • 使用 mysqld--skip-external-locking的 选项。在某些系统上, 锁管理器无法正常工作;该 选项告诉mysqld不要使用外部锁定。(这意味着您不能在同一个数据目录上运行两个 mysqld服务器,并且如果您使用myisamchk则必须小心 。尽管如此,尝试该选项作为测试可能是有益的。) lockd--skip-external-locking

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

  • 在单独的窗口中 运行命令mysqladmin -i 5 statusmysqladmin -i 5 -r status以在运行其他查询时生成统计信息。

  • 尝试以下操作:

    1. gdb(或其他调试器) 启动mysqld 。参见 第 5.9 节,“调试 MySQL”

    2. 运行您的测试脚本。

    3. 在最低的三个级别打印回溯和局部变量。在gdb中,当mysqldgdb中崩溃时,您可以使用以下命令执行此操作 :

      backtrace
      info local
      up
      info local
      up
      info local

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

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

  • 发送一个正常的错误报告。请参阅 第 1.6 节,“如何报告错误或问题”。比平时更详细。因为 MySQL 适用于很多人,所以崩溃可能是由仅存在于您的计算机上的某些东西引起的(例如,与您的特定系统库相关的错误)。

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

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

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