B.4.3.3 如果 MySQLcontinue 崩溃该怎么办
每个 MySQL 版本在发布之前都已经在许多平台上进行了测试。这并不意味着 MySQL 中没有错误,但是如果存在错误,则错误应该很少并且很难找到。如果遇到问题,尝试准确找出导致系统崩溃的原因总是有帮助的,因为您更有可能迅速解决问题。
首先,您应该尝试找出问题是mysqld服务器死了还是您的问题与 Client 端有关。您可以通过执行mysqladmin version来检查mysqld服务器已启动多长时间。如果mysqld已死并重新启动,则可以通过查看服务器的错误日志来找到原因。参见第 5.4.2 节“错误日志”。
在某些系统上,您可以在错误日志中找到可以使用resolve_stack_dump
程序解决的mysqld死亡的堆栈跟踪。参见第 28.5 节“调试和移植 MySQL”。请注意,错误日志中写入的变量值可能并不总是 100%正确。
许多服务器崩溃是由损坏的数据文件或索引文件引起的。在每个 SQL 语句之后且在通知 Client 端结果之前,MySQL 使用write()
系统调用更新磁盘上的文件。 (如果在启用delay_key_write系统变量的情况下运行,则情况并非如此,在这种情况下,将写入数据文件,但不会写入索引文件。)这意味着即使mysqld崩溃,数据文件的内容也是安全的,因为 os 会确保未刷新数据写入磁盘。您可以通过使用--flush选项启动mysqld来强制 MySQL 在每个 SQL 语句之后将所有内容刷新到磁盘。
前面的意思是,除非发生以下情况之一,否则通常不应该损坏 table:
-
MySQL 服务器或服务器主机在更新过程中被杀死。
-
您已找到mysqld中的错误,导致该错误在更新过程中消失。
-
某些外部程序正在与mysqld同时处理数据文件或索引文件,而没有正确锁定 table。
-
您正在使用一个不支持良好文件系统锁的系统上的同一数据目录运行许多mysqld服务器(通常由
lockd
锁 Management 器处理),或者正在运行多个禁用了外部锁定的服务器。 -
您有一个崩溃的数据文件或索引文件,其中包含非常混乱的数据,混淆了mysqld。
-
您在数据存储代码中发现了一个错误。这不太可能,但至少有可能。在这种情况下,您可以尝试通过在 table 的已修复副本上使用ALTER TABLE将存储引擎更改为另一个引擎。
因为很难知道为什么会崩溃,所以首先尝试检查对其他人有用的东西是否对您造成了崩溃。请尝试以下操作:
-
使用mysqladmin shutdown停止mysqld服务器,从数据目录运行myisamchk-静音--force /。MYI以检查所有
MyISAM
table,然后重新启动mysqld。这样可以确保您从干净的状态运行。参见第 5 章,MySQL 服务器 Management。 -
在启用常规查询日志的情况下从mysqld开始(请参阅第 5.4.3 节“常规查询日志”)。然后尝试根据写入日志的信息确定某些特定查询是否杀死了服务器。所有错误中约有 95%与特定查询有关。通常,这是服务器重新启动之前日志文件中的最后一个查询。参见第 5.4.3 节“常规查询日志”。如果您可以通过特定的查询反复杀死 MySQL,即使在发出它之前检查了所有 table,那么您已经隔离了该错误并应提交一个错误报告。参见第 1.7 节“如何报告错误或问题”。
-
尝试做一个测试案例,我们可以用来重复这个问题。参见第 28.5 节“调试和移植 MySQL”。
-
尝试
fork_big.pl
脚本。 (它位于源分发的tests
目录中.) -
通过配置 MySQL 进行调试,可以在出现问题时更容易地收集有关可能的错误的信息。使用-DWITH_DEBUG=1选项将 MySQL 重新配置为 CMake ,然后重新编译。参见第 28.5 节“调试和移植 MySQL”。
-
确保已为 os 应用了最新的修补程序。
-
使用--skip-external-locking选项设置mysqld。在某些系统上,
lockd
锁定 Management 器无法正常工作; --skip-external-locking选项告诉mysqld不要使用外部锁定。 (这意味着您不能在同一数据目录上运行两个mysqld服务器,并且如果使用myisamchk则必须小心。不过,尝试将该选项作为测试可能会很有帮助。) -
如果mysqld似乎正在运行但没有响应,请尝试mysqladmin -u 根进程列 table。有时mysqld即使看起来没有响应也没有挂起。问题可能是所有连接都在使用中,或者可能存在一些内部锁定问题。即使在这些情况下,mysqladmin -u 根进程列 table通常也可以构建连接,并且可以提供有关当前连接数量及其状态的有用信息。
-
在单独的窗口中运行命令mysqladmin -i 5 状态或mysqladmin -i 5 -r 状态,以在运行其他查询时生成统计信息。
-
请尝试以下操作:
-
从 gdb (或其他调试器)中启动mysqld。参见第 28.5 节“调试和移植 MySQL”。
-
运行测试脚本。
-
在三个最低级别上显示回溯和局部变量。在 gdb 中,当mysqld崩溃在 gdb 中时,可以使用以下命令执行此操作:
backtrace
info local
up
info local
up
info local
使用 gdb ,您还可以检查info threads
存在哪些线程,并使用thread N
切换到特定线程,其中* N
*是线程 ID。
-
尝试使用 Perl 脚本模拟您的应用程序,以强制 MySQL 崩溃或行为异常。
-
发送正常的错误报告。参见第 1.7 节“如何报告错误或问题”。比平时更详细。由于 MySQL 适用于许多人,因此崩溃可能是由您计算机上仅存在的某些内容导致的(例如,与您的特定系统库相关的错误)。
-
如果您对包含动态长度行的 table 有问题,并且仅使用VARCHAR列(而不是BLOB或TEXT列),则可以尝试使用ALTER TABLE将所有VARCHAR更改为CHAR。这迫使 MySQL 使用固定大小的行。固定大小的行会占用一些额外的空间,但容错性要大得多。
当前的动态行代码已经使用了几年,几乎没有问题,但是动态长度行本质上更容易出错,因此尝试此策略以查看是否有帮助是一个好主意。
- 诊断问题时,请考虑硬件故障的可能性。硬件损坏可能是数据损坏的原因。对硬件进行故障排除时,请特别注意您的内存和磁盘子系统。