分类: Mysql/postgreSQL
2008-05-12 15:19:13
当你遇到问题时,首先要做的是找出导致问题的程序和设备部件:
· 如果遇到下述征兆之一,或许是因为硬件问题(如内存、主板、CPU或硬盘)或内核问题:
1. 键盘不工作。正常情况下可通过按Caps Lock建进行检查。如果Caps Lock的点亮状态未改变,就需要更换键盘(在此之前,应尝试重启计算机,并检查与键盘相连的所有电缆)。
2. 鼠标指针不移动。
3. 机器未对远程机器的Ping命令做出应答。
4. 与MySQL无关的其他程序工作不正常。
5. 系统意外重启(有问题的用户级程序应不能使系统出现严重问题)。
在该情况下,应检查所有的电缆并运行某些诊断工具,对你的硬件进行检查!此外,还应检查是否有能够解决问题的、适用于你的操作系统的补丁、更新或服务包。请检查所有的库(如glibc)是否是最新的。
使用配备ECC内存的机器以便尽早发现问题总是个好主意。
· 如果键盘已锁定,可从另一台机器登录到你的机器,并执行kbd_mode –a,或许能恢复。
· 请检查系统的日志文件(/var/log/messages或类似物)以找出问题的原因。如果你认为问题出在MySQL中,应检查MySQL的日志文件。请参见5.11节,“MySQL日志文件”。
· 如果你不认为存在硬件问题,应尝试找出导致问题的原因。请使用top、ps、任务管理器或类似程序,以检查哪个程序占用了所有CPU时间或锁定了机器。
· 使用top、df或类似程序检查是否内存不够、磁盘空间不足、文件描述符缺乏、或其他关键资源缺少。
· 如果问题是失去控制的进程,应尝试杀死它。如果杀不死进程,或许是因为操作系统中存在缺陷。
如果在检查了所有其他可能性之后,并得出结论问题是由MySQL服务器或MySQL客户端导致的,应创建提供给我方的邮件列表或支持团队的缺陷报告。在缺陷报告中,请详细描述系统的行为,以及你认为发生了什么情况。+3.
还应阐明为什么你认为是MySQL导致了问题。请考虑本章介绍的所有情况。准确阐明当你检查系统时问题是如何出现的。对于程序和日志文件的任何输出和错误消息,请使用“复制和粘贴”方法。
尽量详细描述不工作的程序,以及你所见到的所有征兆。我们过去收到过很多仅说明“系统不工作”的缺陷报告。这不会为我们提供有助于解决问题的信息。
如果程序失败,了解下述信息总是有用的:
· 有嫌疑的程序是否出现了分段故障(是否转储内核)?
· 程序是否占用了所有可用的CPU时间?用top.进行检查。让程序运行一段时间,或许能简单地评估某些事是否是计算密集性的。
· 如果问题是因mysqld服务器导致的,使用mysqladmin -u root ping或mysqladmin -u root processlist是否能获得服务器的响应?
· 当你尝试连接到MySQL服务器(例如,mysql)时,客户端程序给出的信息是什么?客户端是否堵塞?是否获得了来自程序的任何输出?
发送缺陷报告时,请遵循1.7.1.2节,“请教问题或通报缺陷”中给出的说明。
本节列出了用户运行MySQL服务器时常会遇到的一些错误。尽管问题是在你尝试运行客户端时出现的,但对很多问题的解决方案来说,需要更改MySQL服务器的配置。
导致拒绝访问错误的原因很多。该错误常与连接时服务器允许客户端使用的MySQL账户有关。请参见5.7.8节,“拒绝访问错误的原因”。请参见5.7.2节,“权限系统工作原理”。
Unix平台上的MySQL客户端能够以两种不同的方式连接到mysqld服务器:通过文件系统中的文件(默认为/tmp/mysql.sock)使用Unix套接字进行连接,或通过端口号使用TCP/IP进行连接。Unix套接字文件的连接速度比TCP/IP快,但仅能在与相同计算机上的服务器相连时使用。如果未指定指定主机名或指定了特殊的主机名localhost,将使用Unix套接字。
如果MySQL服务器运行在Windows 9x或Me上,仅能通过TCP/IP进行连接。如服务器运行在Windows NT、2000、XP或2003上,而且使用--enable-named-pipe选项启动,如果在运行服务器的机器上运行客户端,也能使用命名管道进行连接。默认情况下,命名管道的名称为MySQL。如果在连接到mysqld时未给定主机名,MySQL客户端首先会尝试连接到命名管道。如果不能工作,将连接到TCP/IP端口。使用“.”作为主机名,可在Windows平台上强制使用命名管道。
错误(2002)“无法连接到…”通常意味着在系统没有运行的MySQL服务器,或在连接到服务器时使用了不正确的Unix套接字文件名或TCP/IP端口号。
首先检查服务器主机上是否有名为mysqld的进程(在Unix平台上使用ps xa | grep mysqld,或在Windows平台上使用任务管理器)。如果没有这类进程,应启动服务器。请参见2.9.2.3节,“启动MySQL服务器以及其故障诊断和排除”。
如果mysqld进程正在运行,可使用下述命令检查。在你的具体设置中,端口号或Unix套接字文件名可能会有所不同。host_ip代表运行服务器的机器的IP编号。
shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h host_ip version
shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version
注意,应与主机名命令一起使用“`”而不是“’”,这会使主机名输出(当前主机名)被代入mysqladmin命令。如果没有主机名命令或正运行在Windows平台上,应以手动方式输入机器的主机名(无“`”符号),后跟-h选项。也可以使用TCP/IP协议用-h 127.0.0.1连接到本地主机。
下面给出了一些“无法连接到本地MySQL服务器”错误的可能原因:
1. Mysqld未运行。请检查操作系统的进程列表以确保mysqld进程正在运行。
2. 你正在具有很多TCP/IP连接的Windows平台上运行MySQL服务器。如果你的客户端经常出现错误,请参见A.2.2.1节,“在Windows上与MySQL服务器的连接失败”,以找出规避方法。
3. 你正在使用MIT-pthreads的系统上运行。如果你正在运行不具有固有线程的操作系统,mysqld将使用MIT-pthreads软件包。请参见2.1.1节,“MySQL支持的操作系统”。但是,并非所有的MIT-pthreads版本均支持Unix套接字文件。在不支持套接字文件的系统上,连接到服务器时,必须明确指定主机名。请使用下述命令来检查是否连接到了服务器:
4. shell> mysqladmin -h `hostname` version
5. 某人移动了mysqld使用的Unix套接字文件(默认为/tmp/mysql.sock)。例如,你可能执行了将旧文件从/tmp目录删除的cron任务。你总能执行mysqladmin version来检查mysqladmin试图使用的Unix套接字文件是否的确存在。在该情况下,更正方式是更改cron任务,不删除mysql.sock文件,或将套接字文件置于其他地方。请参见A.4.5节,“如何保护或更改MySQL套接字文件/tmp/mysql.sock”。
6. 你使用--socket=/path/to/socket选项启动了mysqld服务器,当忘记将套接字文件的新名称通知客户端程序。如果更改了关于服务器的套接字路径,也必须通知MySQL客户端。可在运行客户端程序时使用相同的—socket选项来完成该任务。此外,你还应确保客户端具有访问文件mysql.sock的权限。要想找出套接字文件的位置,可使用:
7. shell> netstat -ln | grep mysql
请参见A.4.5节,“如何保护或更改MySQL套接字文件/tmp/mysql.sock”。
8. 你正在使用Linux而且1个服务器线程已死亡(内核已清除)。在此情况下,在重启MySQL服务器之前,必须杀死其他mysqld线程(例如,使用kill或mysql_zap脚本)。请参见A.4.2节,“如果MySQL依然崩溃,应作些什么”。
9. 服务器或客户端程序不具有访问包含Unix套接字文件的目录或套接字文件本身的恰当权限。在该情况下,必须更改目录或套接字文件的访问权限,以便服务器或客户端程序能够访问它们,或用–socket选项重启mysqld,在该选项中指定服务器能创建、而且客户端可访问的目录下的套接字文件名。
如果遇到错误消息“无法连接到some_host上的MySQL服务器”,可尝试采取下述步骤以找出问题所在:
· 执行“telnet some_host 3306”并按两次回车键,检查服务器是否运行在该主机上(3306是默认的MySQL端口号。如果你的服务器正在监听不同的端口,请更改该值)。如果有1个MySQL服务器正在运行并监听该端口,你应收到包含服务器版本号的回应。如果遇到错误,如“telnet:无法连接到远程主机:拒绝连接”,表示在该定端口上没有运行的服务器。
· 如果服务器正运行在本地主机上,请使用Unix套接字文件,并使用mysqladmin -h localhost variables进行连接。验证服务器监听的TCP/IP端口号(它是port变量的值)。
· 确保你的mysqld服务器未用--skip-networking选项启动。如果使用了该选项,将无法使用TCP/IP连接到它。
· 检查并确认不存在屏蔽了对MySQL访问的防火墙。需要配置诸如ZoneAlarm和Windows XP个人防火墙等应用程序,以允许对MySQL服务器的外部访问。
默认情况下,Windows允许用于使用5000个临时(短命)TCP端口。任何端口关闭后,它将在TIME_WAIT状态保持120秒。与重新初始化全新的连接相比,该状态允许以更低的开销重新使用连接。但是,在该时间逝去前,无法再次使用该端口。
对于小的可用TCP端口堆栈(5000),以及具有TIME_WAIT状态的大量在短时间内打开和关闭的TCP端口,你很可能遇到端口耗尽问题。处理该问题的方法有两种:
· 通过调查连接池以及可能的持久连接,减少快速消耗的TCP端口数。
· 调整Windows注册表中的某些设置(请参见下面)。
要点:下述步骤涉及更改Windows 注册表。更改注册表之前,请备份注册表,并确认你已掌握在出现问题时恢复注册表的方法。关于备份年、恢复和编辑注册表的更多信息,请请参见Microsoft知识库中的下述文献:。
· 启动注册表编辑器(Regedt32.exe)。
· 在注册表中确定下述键值的位置:
· HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
· 在“编辑”菜单上点击“添加值”,然后增加下述注册值:
· Value Name: MaxUserPort
· Data Type: REG_DWORD
· Value: 65534
它用于设置为任何用户提供的临时端口数。有效范围介于5000和65534之间(十进制)。默认值为0x1388(5000,十进制)。
· 在“编辑”菜单上点击“添加值”,然后增加下述注册值:
· Value Name: TcpTimedWaitDelay
· Data Type: REG_DWORD
· Value: 30
它用于设置关闭之前将TCP端口连接保持在TIME_WAIT状态的秒数。有效范围介于0秒和300秒之间。默认值为0x78(120秒)。
· 退出注册表编辑器。
· 重新引导机器。
注释:撤销上述设置十分简单,就像删除你创建的注册表一样。
MySQL 5.1采用了基于密码混编算法的鉴定协议,它与早期客户端(4.1之前)使用的协议不兼容。如果你将服务器升级到4.1之上,用早期的客户端进行连接可能失败,并给出下述消息:
shell> mysql
客户端不支持服务器请求的鉴定协议:请考虑升级MySQL客户端。
要想解决该问题,应使用下述方法之一:
· 升级所有的客户端程序,以使用4.1.1或更新的客户端库。
· 用4.1版之前的客户端连接到服务器时,请使用仍具有4.1版之前风格密码的账户。
· 对于需要使用4.1版之前的客户端的每位用户,将密码恢复为4.1版之前的风格。可以使用SET PASSWORD语句和OLD_PASSWORD()函数完成该任务:
· mysql> SET PASSWORD FOR
· -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');
也可以使用UPDATE和FLUSH PRIVILEGES:
mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd')
-> WHERE Host = 'some_host' AND User = 'some_user';
mysql> FLUSH PRIVILEGES;
用你打算使用的密码替换前例中的“newpwd”。MySQL不能告诉你原来的密码是什么,因此,你需要选择新的密码。
· 通知服务器使用旧的密码混编算法:
1. 使用“--old-passwords”选项启动mysqld。
2. 对于已将密码更新为较长4.1格式的每个账户,为其指定具有旧格式的密码。可以使用下述查询确定这些账户:
3. mysql> SELECT Host, User, Password FROM mysql.user
4. -> WHERE LENGTH(Password) > 16;
对于查询显示的每个账户记录,请使用Host和User值,并使用OLD_PASSWORD()函数以及SET PASSWORD或UPDATE之一指定密码,如前面所介绍的那样。
注释:在早期的PHP版本中,mysql扩展不支持MySQL 4.1.1和更高版中的鉴定协议。无论使用的PHP版本是什么,它均是正确的。如果你打算与MySQL 4.1或更高版本一起使用mysql扩展,需要使用前面介绍的选项之一,配置MySQL,以便与较早的客户端一起使用。mysqli扩展(支持“改进的MySQL”,在PHP 5中增加)与MySQL 4.1和更高版本中使用的改进的密码混编算法兼容,不需要对MySQL进行特殊配置就能使用该MySQL客户端库。关于mysqli扩展的更多信息,请参见。
关于密码混编和鉴定功能的额外背景知识,请参见5.7.9节,“MySQL 4.1中的密码哈希处理”。
shell> mysql -u user_name -p
Enter password:
在某些系统上,当你在选项文件或命令行上指定时,你可能会发现密码能够工作,但是当你在“Enter password:”提示下以交互方式输入密码时,你可能会发现输入的密码不工作。当系统所提供的用于读取密码的库将密码值限定在少数字符时(典型情况下为8个),就会出现该问题。这是与系统库有关的问题,与MySQL无关。要想处理该问题,可将MySQL密码更改为由8个字符或更少字符构成的值,或将密码置于选项文件中。
如果遇到下述错误,表示mysqld已收到来来自主机“host_name”的很多连接请求,但该主机却在中途中断。
由于出现很多连接错误,主机'host_name'被屏蔽。
可使用'mysqladmin flush-hosts'解除屏蔽。
允许的中断连接请求的数目由max_connect_errors系统变量的值决定。当超出max_connect_errors规定的连接请求时,mysqld将认为某处出错(例如,某人正试图插入),并屏蔽主机的进一步连接请求,直至执行了mysqladmin flush-hosts命令,或发出了FLUSH HOSTS语句为止。请参见5.3.3节,“服务器系统变量”。
在默认情况下,mysqld会在10次连接错误后屏蔽主机。你可以通过下述方式启动服务器来调整该值:
shell> mysqld_safe --max_connect_errors=10000 &
如果在给定主机上遇到该错误,首先应核实该主机的TCP/IP连接是否正确。如果存在网络问题,增加max_connect_errors变量的值不会有任何好处。
当你试图连接到mysqld服务器时遇到“过多连接”错误,这表示所有可用的连接均已被其他客户端使用。
允许的连接数由max_connections系统变量控制。默认值为100。如果需要支持更多的连接,应使用该变量的较大值重启mysqld。
mysqld实际上允许max_connections+1个客户端进行连接。额外的连接保留给具有SUPER权限的账户。通过为系统管理员而不是普通用户授予SUPER权限(普通用户不应具有该权限),系统管理员能够连接到服务器,并使用SHOW PROCESSLIST来诊断问题,即使已连接的无特权客户端数已达到最大值也同样。请参见13.5.4.16节,“SHOW PROCESSLIST语法”。
MySQL能支持的最大连接数取决于给定平台上线程库的质量。Linux或Solaris应能支持500-1000个并发连接,具体情况取决于RAM容量,以及客户端正在作什么。MySQL AB提供的静态Linux库能支持高达4000个连接。
如果使用mysql客户端程序发出了查询,并收到下述错误之一,则表示mysql没有足够内存来保存全部查询结果:
mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
错误2008: MySQL client ran out of memory
要想更正该问题,首先应检查查询是否正确。返回这么多行是否合理?如果不合理,更正查询并再次尝试。否则,应使用“--quick”选项调用mysql。这样,将使用mysql_use_result() C API函数来检索结果集,这类函数能够降低客户端上的负载(但会加重服务器上的负载)。
在本节中,还介绍了出现查询错误期间,与丢失了服务器连接有关的事宜。
MySQL服务器不可用错误的最常见原因是服务器超时以及连接已关闭。在该情况下,通常能见到下述错误代码之一(具体的错误代码与操作系统有关):
错误代码 |
描述 |
CR_SERVER_GONE_ERROR |
客户端无法将问题发送至服务器。 |
CR_SERVER_LOST |
写入服务器时客户端未收到错误,但也未获得问题的完整答案(或任何答案)。 |
在默认情况下,如果未发生任何事,8小时后服务器将关闭连接。也可以在启动mysqld时,通过设置wait_timeout变量更改时间限制。请参见5.3.3节,“服务器系统变量”.
如果有1个脚本,你仅需要再次发出查询,让客户端再次进行自动连接即可。其中,假定在客户端中启用了自动再连接功能(对于mysql命令行客户端,这是默认设置)。
MySQL服务器不可用错误的一些其他常见原因如下:
· 你(或db系统管理员)使用KILL语句或mysqladmin kill命令杀死了正在运行的线程。
· 你试图在关闭了与服务器的连接后运行查询。这表明应更正应用程序中的逻辑错误。
· 你在客户端一侧遇到TCP/IP连接超时错误。如果你使用了命令:mysql_options(..., MYSQL_OPT_READ_TIMEOUT,...)或mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...),就可能出现该问题。在该情况下,增加超时值可能有助于问题的解决。
· 你在服务器端遇到超时错误,而且禁止了客户端中的自动再连接功能(MYSQL结构中的再连接标志等于0)。
· 你正在使用Windows客户端,而且在发出命令之前服务器撤销了连接(或许是因为已超过wait_timeout)。
在Windows平台上出现问题的原因,在某些情况下,将TCP/IP连接写入服务器时,MySQL未收到来自操作系统的错误,但当试图从连接读取答案时出现错误。
在该情况下,即使MYSQL结构中的再连接标志等于1,MySQL也不会执行自动再连接并再次发出查询,这是因为它不知道服务器是否收到原始查询。
对此的解决方式是:如果自上一次查询以来经过了较长时间,在连接上执行mysql_ping(正是MyODBC所作的);或在mysqld服务器上将wait_timeout设置得很高,使之实际上不存在超时。
· 如果你向服务器发出了不正确或过大的查询,也会遇到这类问题。如果mysqld收到过大或无序的信息包,它会认为客户端出错,并关闭连接。如果需要执行较大的查询(例如,正在处理大的BLOB列),可通过设置服务器的max_allowed_packet变量,增加查询限制值,该变量的默认值为1MB。或许,你还需增加客户端上的最大信息包大小。关于设置信息包大小的更多信息,请参见A.2.9节,“信息包过大”。
· 如果你的客户端低于4.0.8而且你的服务器高于4.0.8,当你接收16MB或更大的信息包时,可能会丢失连接。
· 如果MySQL是用“--skip-networking”选项启动的,也会见到MySQL服务器不可用错误。
· 你遇到了执行查询时服务器宕机的缺陷。
通过执行mysqladmin version并检查服务器的正常工作时间,可检查服务器是否宕机并重启。如果客户端连接是因mysqld崩溃和重启而断开的,应将重点放在查找崩溃你方面。首先应再次检查发出的查询是否再次杀死了服务器。请参见A.4.2节,“如果MySQL依然崩溃,应作些什么”。
用“--log-warnings=2”选项启动mysqld,可获得关于连接的更多信息。这样,就能将某些断开连接错误记录到hostname.err文件中。请参见5.11.1节,“错误日志”。
如果你打算创建与该问题有关的缺陷报告,务必包含下述信息:
1. 指明MySQL服务器是否宕机。通过服务器错误日志可发现这方面的信息。请参见A.4.2节,“如果MySQL依然崩溃,应作些什么”。
2. 如果特定查询杀死了mysqld,而且在运行查询前用CHECK TABLE检查了涉及的表,你是否能提供可重复的测试范例?请参见E.1.6节,“如果出现表崩溃,请生成测试案例”。
3. 在MySQL服务器中,系统变量wait_timeout的值是什么?(mysqladmin variables给出了该变量的值)。
4. 你是否尝试使用“--log”选项来运行mysqld,以确定是否在日志中出现问题?
另请参见A.2.10节,“通信错误和失效连接”。
通信信息包是发送至MySQL服务器的单个SQL语句,或发送至客户端的单一行。
在MySQL 5.1服务器和客户端之间最大能发送的可能信息包为1GB。
当MySQL客户端或mysqld服务器收到大于max_allowed_packet字节的信息包时,将发出“信息包过大”错误,并关闭连接。对于某些客户端,如果通信信息包过大,在执行查询期间,了能回遇到“丢失与MySQL服务器的连接”错误。
客户端和服务器均有自己的max_allowed_packet变量,因此,如你打算处理大的信息包,必须增加客户端和服务器上的该变量。
如果你正在使用mysql客户端程序,其max_allowed_packet变量的默认值为16MB。要想设置较大的值,可用下述方式启动mysql:
mysql> mysql --max_allowed_packet=32M
它将信息包的大小设置为32MB。
服务器的默认max_allowed_packet值为1MB。如果服务器需要处理大的查询,可增加该值(例如,如果准备处理大的BLOB列)。例如,要想将该设置为16MB,可采用下述方式启动服务器:
mysql> mysqld --max_allowed_packet=16M
也能使用选项文件来设置max_allowed_packet。要想将服务器的该变量设置为16MB,可在选项文件中增加下行内容:
[mysqld]
max_allowed_packet=16M
增加该变量的值十分安全,这是因为仅当需要时才会分配额外内存。例如,仅当你发出长查询或mysqld必须返回大的结果行时mysqld才会分配更多内存。该变量之所以取较小默认值是一种预防措施,以捕获客户端和服务器之间的错误信息包,并确保不会因偶然使用大的信息包而导致内存溢出。
如果你正是用大的BLOB值,而且未为mysqld授予为处理查询而访问足够内存的权限,也会遇到与大信息包有关的奇怪问题。如果怀疑出现了该情况,请尝试在mysqld_safe脚本开始增加ulimit -d 256000,并重启mysqld。