Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

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

每个 MySQL 版本在发布之前都会在多个平台上进行测试。这并不意味着 MySQL 中没有 bug,但如果存在 bug,它们应该非常少见且难以发现。如果您遇到问题,总是有助于您尝试找到系统崩溃的确切原因,因为这样您更有可能快速解决问题。

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

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

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

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

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

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

  • 您发现了 mysqld 的一个 bug,导致它在更新过程中死亡。

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

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

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

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

因为很难知道为什么某些事情会崩溃,所以首先尝试检查其他人是否可以正常工作,而您却遇到了意外退出。请尝试以下事情:

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

  • 使用启用通用查询日志的mysqld(见第7.4.3节,“通用查询日志”)。然后,尝试从日志文件中确定是否有一些特定的查询杀死了服务器。大约95%的所有bug都与特定的查询相关。通常,这是日志文件中服务器重新启动前的最后一个查询。见第7.4.3节,“通用查询日志”。如果您可以重复地用特定的查询杀死MySQL,即使您已经在发出该查询前检查了所有表,那么您已经隔离了bug并且应该提交一个bug报告。见第1.5节,“如何报告bug或问题”

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

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

  • 为调试配置MySQL,使得在出现错误时更容易收集信息。使用-DWITH_DEBUG=1选项重新配置MySQL,然后重新编译。见第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 崩溃在 gdb 中:

      backtrace
      info local
      up
      info local
      up
      info local

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

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

  • 发送正常的错误报告。请参阅 第 1.5 节,“如何报告错误或问题”。因为 MySQL 对许多人都有效,崩溃可能是由于您的计算机上存在的某些问题(例如,特定系统库相关的错误).

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

    当前的动态行代码已经使用了多年,很少出现问题,但是动态长度行天生容易出错,因此尝试这种策略来查看是否有帮助。

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