《MySQL排错指南》——1.7 当服务器无响应的时候

1.7 当服务器无响应的时候

有时候,MySQL客户端会收到严重的错误消息“在请求中丢失与服务器的连接”或者“服务器已停止”。尽管我希望你永远不会遇到这个错误,但是有所准备总是有好处的。由MySQL安装本身引起的这个问题主要有两个原因:服务器问题(最有可能是崩溃)或者滥用连接选项(通常是超时选项或者max_allowed_packet)。

第3章将讨论连接相关的配置。第4章会讨论硬件问题和第三方软件相关的问题。这里简短地介绍一下如果遇到服务器崩溃该做些什么。

首先,确定你的服务器是否真的崩溃。你可以借助进程状态监控器进行确认。如果你在服务器崩溃后运行了mysqld_safe或者其他守护进程重启服务器,错误日志将会包含表明服务器已经重启的消息。当mysqld启动时,它始终会在错误日志文件中输出类似如下的信息:

因此,如果你找到了类似消息,那么服务器已经重启了。如果没有任何消息,并且服务器已经启动并在运行,那么丢失连接的问题最有可能是因为滥用连接选项导致的,这将在第3章进行讨论。

提示 提示

如果你记得MySQL服务器原来是何时启动的,你可以使用状态变量uptime,该变量的值代表服务器已启动的时间,单位是秒:

该信息也可以帮你检查mysqld是否是因为操作系统的重启而失败的。仅需要比较该变量的值和操作系统的启动时间即可。

依赖于错误日志文件是因为我工作经历的原因,比如当客户在服务器崩溃数小时后发现问题,甚至有时候是在mysqld计划重启后才发现问题。
如果你确认服务器已经重启了,你应该再次检查错误日志去搜索崩溃本身的信息。通常,你会从错误日志中获取足够的崩溃信息,从而避免发生同样的情况。第6章将讨论如何调查你可能会遇到的少数困难情况。现在,我们再次回到错误日志文件,来看一下在服务器崩溃情况下的典型内容示例。这里我将摘录出大量信息:

表明崩溃原因的关键行是:

这意味着MySQL服务器在向操作系统申请资源(例如,访问文件或者内存)后终止了,得到了错误代码11。在大多数操作系统里,这个信号代表分段错误(segmentation fault)。你可以在你的操作系统的用户手册中获取更详细的信息。对于UNIX和Linux系统可以执行man命令。在Windows操作系统里,相似的情况通常会产生类似“mysqld got exception 0xc0000005”的日志消息。查找Windows的用户手册可以获取该异常代码的含义。

下面是从某个线程中导致服务器崩溃的请求的相关日志中提取的摘要信息:

为了进一步分析,重新执行查询来检查其是否是崩溃的原因:

提示 提示

当我推荐你重现错误的时候,我假定你是在开发服务器而不是生产服务器中进行的。6.3节将讨论如何安全地在特定环境下进行问题调优。请不要尝试重试示例中的语句,这是一个已知的bug#47780,已经在当前版本修复了。从5.0.88、5.1.41、5.5.0和6.0.14版本开始,该bug已经修复。
当目前为止,你已经找到并确认崩溃的原因,然而你还需要重写请求,从而避免下次服务器再次崩溃。现在,我们可以从日志的堆栈信息中获得帮助:

与错误相关的行是调用Item_subselect和Item_singlerow_subselect的部分:

我是如何确定这是罪魁祸首的呢?在这个示例中,我发现在之前排错过程中的调用。不过经验告诉我,最好还是从头开始排查问题。最前面的几个函数通常是操作系统调用的,这些函数可能会和问题相关,不过在当前环境下没有任何帮助,因为对它们你什么都做不了,接下来是对MySQL库的调用。自上而下地检查这些函数,以便找到哪些是与你相关的。例如,对于String4copy或Item_cache_str5store函数你没什么可做的,但是你可以重写子查询,因此我们从这里开始。

这里,哪怕不去看mysqld的源码,我们也可以找到崩溃的原因。推测子查询可能是问题的所在,这是一个不错的假设,因为子查询可以很容易地转换成JOIN。尝试重写查询然后测试它:

新查询并没有崩溃,因此你需要做的就是把应用程序中的查询改成等价的形式。

你刚刚学到了一些MySQL问题排查中的重要事情:当遇到未知的错误时首先应该做的是检查错误日志文件。始终要打开日志。
这里我想补充一点关于bug的内容。当你遇到崩溃并确定了原因的时候,应检查一下MySQL的bug数据库,看看有无类似的问题。如果你找到可能与你相关的bug,确认它是否修复了。如果已经修复了,那么把你的服务器升级到bug已修复的版本(或者更新的版本)。这样做可以节约你的时间,因为你不再需要修改有问题的语句了。

如果你没找到与你相关的bug,尝试下载最新的MySQL版本,然后再执行查询。如果bug再次出现,请把它提交给我们。使用最新的稳定版本是非常重要的,因为它包含当前修复的所有bug,许多老的问题在这里不会重现。第6章中会讨论如何在沙盒环境下安全地测试崩溃的情形。

不仅是特定的查询会引起崩溃,而且服务器运行的环境也有可能引起崩溃。最常见的原因就是缺少可用的内存(RAM)。特别当用户分配超大缓冲区时最容易发生。正如我之前提到的那样,mysqld始终需要比所有缓冲区容量总和略多的内存。通常情况下,错误日志文件包含可用内存的粗略估计。它看起来如下所示:

这种估计不是精确的,不过仍然值得确认。上面展示的信息表明mysqld可以使用高达20GB的内存。虽然现在你可以很容易地获得强大的计算机,但是仍有必要确认你是否真的拥有20GB内存。

该环境中的另一个问题是,有其他的应用程序与MySQL服务器一起运行。在生产环境中,最好为MySQL指定一台专门的服务器,因为其他应用程序可能会占用你希望MySQL使用的资源。第4章将讨论如何调试其他应用程序对mysqld的影响。

时间: 2024-08-02 10:28:02

《MySQL排错指南》——1.7 当服务器无响应的时候的相关文章

《MySQL排错指南》导读

前言 MySQL排错指南我从2006年5月开始,作为首席技术支持工程师在MySQL AB公司MySQL支持团队的bug校验组工作,然后我到了Sun公司,最后是在Oracle公司.在日常工作中,我经常遇到用户受困于某个问题而不知所措的情况.虽然有已经被证实可用的方法去定位并快速修复问题,但是用户往往很难从大量的信息中筛选出这些可用的信息.尽管有数以千百计的著名书籍.博文和网页都详细介绍了MySQL服务器方方面面的问题,但这正是我感觉困难的地方:这些信息都关注于如何让MySQL服务器正常地工作,而忽

《MySQL排错指南》——第4章 MySQL环境

第4章 MySQL环境 MySQL排错指南MySQL服务器在运行环境中不是孤立的.即使它运行在专用服务器环境中,你依然需要考虑硬件资源和操作系统限制.在共享环境中,MySQL服务器仍然会受到其他进程的影响.关于MySQL操作系统层面的调优,这个主题可以另写一本书了.所以本章不深入讨论,只是从排错角度切入并展开.MySQL的其中一个优势就是能运行在不同环境中,但这也导致了本章很难将其细化说明.最终我决定写下你需要关心的部分,剩下的留给你去查找操作系统对应的手册来决定如何调优.

《MySQL排错指南》——第1章 基础

第1章 基础 MySQL排错指南当解决疑难问题的时候,为了节约时间,你可以从最简单的情况开始,然后一步步从简入繁.在MySQL支持团队工作的时候,我每个月解决成百上千的问题.其中的大部分都是从零散的请求信息开始的,最终的解决方案可能也很基础,我们将会从一些示例中看到这点.不过有些时候,我们确实会遭遇很大的挑战.所以,我们应时刻牢记从最基础的开始. 典型的基础类问题不外乎执行一个查询但是返回非预期的结果.这类问题的表现形式可能是很明显的错误,也可能是在你明知有匹配记录的情况下却没有返回结果,或者其

《MySQL排错指南》——1.1 语法错误

1.1 语法错误 这个错误听起来十分简单,但仍可能很难发现.我建议你像处理其他问题一样,非常细心地查找可能出现的SQL语法错误. 类似如下错误,很容易被发现: 在这个示例中,很显然用户少转入了个"m",错误消息也很清楚(输出结果根据页面设置进行宽度调整): 遗憾的是,不是所有的语法错误都这么显而易见.我曾经处理过一个问题,它的查询语句是这样的: 这是一个版本迁移导致的问题:该语句在5.0版本中运行正常,但是在5.1版本中出现错误.问题的原因在于,在5.1版本中,"access

《MySQL排错指南》——4.1 物理硬件限制

4.1 物理硬件限制 对性能有不切实际的期望是通常会犯的错.我们要求MySQL服务器在忽略硬件组件延迟的情况下进行优化.因此,理解什么导致了延迟很重要. 下面列出了影响MySQL服务器的硬件资源: 内存CPU内核数量磁盘I/O网络带宽我们依次讨论每个细节. 4.1.1 内存 内存对于MySQL是非常宝贵的资源.服务器在没有磁盘交换的情况下运行很快.理想情况是数据驻留在内存中.因此,在物理内存的限制内合理配置缓冲区是非常重要的.关于这一点,1.6.4小节和3.9.3小节提供了更多详细的介绍和指导.

《MySQL排错指南》——1.3 当错误可能由之前的更新引起时

1.3 当错误可能由之前的更新引起时 如果SELECT查询返回了非预期的结果集,这并不总是意味着查询语句本身有错误,也有可能是因为你以为已经进行了插入.更新或者删除等操作,而事实上它们并未生效. 在你调查这种可能之前,你应该先完全仔细检查前一节讨论的SELECT语句编写错误的问题.在SELECT语句编写正确并且能够返回你想要的值的情况下,现在我开始调查由数据本身的问题导致错误的可能性.为了确认问题是由数据本身而非SELECT语句产生的,我尝试精简语句,使其变成某个独立表的简单查询.如果是小表,那

《MySQL排错指南》——1.9 许可问题

1.9 许可问题 MySQL有复杂的权限方案,这使得你可以精确地设置哪些用户和主机可以或不可以执行这个或那个操作.从5.5版本开始,MySQL也有了可插拔式的身份验证模式. 尽管它有很多优势,但是这个方案很复杂.例如,让user1@hostA.user2@hostA和user1@hostB不同会很容易混淆它们的权限.当用户名相同而主机名变化的时候更是如此. MySQL允许在对象和连接层面设置访问规则.可以限制某个用户对于特定的表.列等的访问权限. 用户通常会遇到两类权限问题: 应该有权限连接到服

《MySQL排错指南》——1.2 SELECT返回错误结果

1.2 SELECT返回错误结果 这是用户反馈的另一个非常常见的问题,主要的现象有:用户看不到更新的结果.展示的顺序错误或者查询到了非预期的结果. 这个问题主要有两方面的原因:一方面是你的SELECT查询有误:另一方面是数据库中的数据和你想象的不同.我先介绍第一种情况. 在我规划本节示例的时候,我考虑要么使用真实的示例,要么使用我自己设计的小场景.真实的示例可能占用大量篇幅,但是我自己设计的示例可能对你没有什么帮助,因为没有人会写出那样的代码.因此,我选择使用典型的真实示例作为示例,只是大幅简化

《MySQL排错指南》——1.4 获取查询信息

1.4 获取查询信息 正如前一节看到的一样,数据库会返回一些关于每个查询的重要信息,有些信息直接展现在MySQL的访问客户端中,而有些信息则需要通过如SHOW WARNINGS等命令才能得到.当从应用程序中调用SQL语句的时候,获取这些返回信息并确认没有异常情况发生同样重要.所有语言的MySQL API都提供了获取服务器返回信息的接口.本节将讨论这些接口.这里仅涉及C的API,因为我必须选择一种语言的API,并且大部分其他语言的API都是基于C的API的[2]. 受影响的行数我们从之前见过的输出