A. 问题和常见错误 / A.4. 与管理有关的事宜

A.4. 与管理有关的事宜

A.4.1. 如何复位根用户密码
A.4.2. 如果MySQL依然崩溃,应作些什么
A.4.3. MySQL处理磁盘满的方式
A.4.4. MySQL将临时文件储存在哪里
A.4.5. 如何保护或更改MySQL套接字文件/tmp/mysql.sock
A.4.6. 时区问题

A.4.1. 如何复位根用户密码

如果你从未为MySQL设置根用户密码,服务器在以根用户身份进行连接时不需要密码。但是,建议你为每个账户设置密码。请参见5.6.1节,“通用安全指南”

如果你以前设置了根用户密码,但却忘记了该密码,可设置新的密码。下述步骤是针对Windows平台的。在本节后面的内容中,介绍了针对Unix平台的步骤。

Windows平台下,该步骤是:

以系统管理员身份登录到系统。

如果MySQL服务器正在运行,停止它。对于作为Windows服务运行的服务器,进入服务管理器:

开始菜单->控制面板->管理工具->服务

然后在列表中找出MySQL服务器,并停止它。

如果服务器不是作为服务而运行的,可能需要使用任务管理器来强制停止它。

创建1个文本文件,并将下述命令置于单一行中:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

用任意名称保存该文件。在本例中,该文件为C:\mysql-init.txt

打开控制台窗口,进入DOS命令提示:

开始菜单->运行-> cmd

假定你已将MySQL安装到C:\mysql。如果你将MySQL安装到了另一位置,请对下述命令进行相应的调整。

DOS命令提示符下,执行命令:

C:\> C:\mysql\bin\mysqld-nt --init-file=C:\mysql-init.txt

在服务器启动时,执行由“--init-file”选项命名的文件的内容,更改根用户密码。当服务器成功启动后,应删除C:\mysql-init.txt

如果你使用MySQL安装向导安装了MySQL,或许需要指定“--defaults-file”选项:

C:\> C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld-nt.exe
         --defaults-file="C:\Program Files\MySQL\MySQL Server 5.1\my.ini"
         --init-file=C:\mysql-init.txt

使用服务管理器,可找到恰当的“--defaults-file”设置:

开始菜单->控制面板->管理工具->服务

在列表中找出MySQL服务,右击,并选择“属性”选项。在可执行字段的Path(路径)中包含“--defaults-file”设置。

停止MySQL服务器,然后在正常模式下重启它。如果以服务方式运行服务器,应从Windows服务窗口启动它。如果以手动方式启动了服务器,能够像正常情形下一样使用命令。

应能使用新密码进行连接。

Unix环境下,重置根用户密码的步骤如下:

Unix根用户身份、或以运行mysqld服务器的相同身份登录到系统。

找到包含服务器进程ID.pid文件。该文件的准确位置和名称取决于你的分发版、主机名和配置。常见位置是/var/lib/mysql//var/run/mysqld//usr/local/mysql/data/一般情况下,文件名的扩展名为.pid,并以mysqld或系统的主机名开始。

在下述命令中使用.pid文件的路径名,向mysqld进程发出正常的kill(而不是kill -9),可停止MySQL服务器:

shell> kill `cat /mysql-data-directory/host_name.pid`

注意,cat命令使用符号“`”而不是“’”:这会使cat的输出代入到kill命令中。

创建文本文件,并将下述命令放在文件内的1行上:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

用任意名称保存文件。对于本例,文件为~/mysql-init

用特殊的“--init-file=~/mysql-init”选项重启MySQL服务器:

shell> mysqld_safe --init-file=~/mysql-init &

文件init-file的内容在服务器启动时执行,更改根用户密码。服务器成功启动后,应删除~/mysql-init

应能使用新密码进行连接。

作为可选方式,在任何平台上,可使用mysql客户端设置新密码(但该方法不够安全):

停止mysqld,并用“--skip-grant-tables --user=root”选项重启它Windows用户可省略--user=root部分)。

使用下述命令连接到mysqld服务器:

shell> mysql -u root

mysql客户端发出下述语句:

mysql> UPDATE mysql.user SET Password=PASSWORD('newpwd')
    ->                   WHERE User='root';
mysql> FLUSH PRIVILEGES;

用打算使用的实际根用户密码替换“newpwd”。

应能使用新密码进行连接。

A.4.2. 如果MySQL依然崩溃,应作些什么

正式发布之前,每个MySQL版本均在很多平台上进行了测试。这不表示MySQL中不存在缺陷,但是,如果存在缺陷,它们应很少,而且很难发现。如果你遇到问题,如果你尝试找出导致系统崩溃的准确原因,这始终很有帮助,这是因为,如果这样的话,快速解决问题的机会很大。

首先,应尝试找出问题是否与mysqld服务器有关,或是否与客户端有关。通过执行mysqladmin version,可检查mysqld服务器运行了多长时间。如果mysqld宕机并重启,应查看服务器的错误日志以找出原因。请参见5.11.1节,“错误日志”

在某些系统上,在错误日志中,可发现mysqld宕机的堆栈跟踪,可使用resolve_stack_dump程序解决它。请参见E.1.4节,“使用堆栈跟踪”。注意,错误日志中的变量值并非始终是100%正确的。

很多服务器崩溃是因损坏的数据文件或索引文件而导致的,每次执行完SQL语句之后并在向客户端通告结果之前,MySQL将使用write()系统调用更新磁盘上的文件(如果你使用了“--delay-key-write”选项,情况并非如此,此时将写入数据文件而不是索引文件)。这意味着,即使mysqld崩溃,数据文件的内容也是安全的,这是因为操作系统能保证将未刷新的数据写入磁盘。使用“--flush”选项启动mysqld,这样,每次执行完SQL语句后,可强制MySQL将所有内容写入磁盘。

前述介绍表明,在正常情况下不会出现损坏的表,除非出现了下述情况之一:

在更新过程中,MySQL服务器或服务器主机被停止。

你发现了mysqld中存在的1个缺陷,该缺陷导致mysqld在更新中途中止。

mysqld操作的同时,某些外部程序正在操控数据文件或索引文件,未恰当锁定表。

你正使用系统上的相同数据目录运行很多mysqld服务器,该系统不支持良好的文件系统锁定(通常是由lockd锁定管理器负责的),或使用“--skip-external-locking”选项运行了多个服务器。

崩溃的数据文件或索引文件,其中包含导致mysqld混乱的损坏很严重的数据。

在数据存储节点发现缺陷。这种可能性不大,但至少是可能的。在该情况下,可在修复的表副本上,通过使用ALTER TABLE尝试将表类型更改为另一种存储引擎。

由于很难得知为什么某事会出现崩溃,首先请检查用于其他方面的事项是否崩溃。请尝试采取下述措施:

mysqladmin shutdown停止mysqld服务器,从数据目录运行myisamchk --silent --force */*.MYI,检查所有的MyISAM表,并重启mysqld。这样,就能确保从干净的状态运行服务器。请参见第5章:数据库管理

使用“--log”选项启动mysqld,并根据写入日志的信息确定是否某些特殊的查询杀死了服务器。约95%的缺陷与特定的查询有关。正常情况下,这是服务器重启前日志文件中最够数个查询中的1个。请参见5.11.2节,“通用查询日志”。如果能够用特殊查询重复杀死MySQL,即使在发出查询前检查了所有表的情况下也同样,那么你就应能确定缺陷,并应提交关于该缺陷的缺陷报告。请参见1.7.1.3节,“如何通报缺陷和问题”

尝试提供一个测试范例,我们应能利用该范例重复问题。请参见E.1.6节,“如果出现表崩溃,请生成测试案例”

请在mysql-test目录下并根据MySQL基准进行测试。请参见27.1.2节,“MySQL测试套件”。它们能相当良好地测试MySQL。你也可以为基准测试增加代码,以模拟你的应用程序。基准测试可在源码分发版的sql-bench目录下找到,对于二进制分发版,可在MySQL安装目录下的sql-bench目录下找到。

尝试使用fork_big.pl脚本(它位于源码分发版的测试目录下)。

如果你将MySQL配置为调试模式,如果某事出错,可更为容易地搜集关于可能错误的信息。如果将MySQL配置为调试模式,可生成1个安全的内存分配程序,可使用它发现某些错误。此外,它还提供了很多输出,这类输出与出现的问题相关。在configure上使用“--with-debug”或“--with-debug=full”选项重新配置MySQL,然后再编译它。请参见E.1节,“调试MySQL服务器”

确保为你的操作系统应用了最新的补丁。

mysqld使用“--skip-external-locking”选项。在某些系统上,lockd锁定管理器不能正确工作,--skip-external-locking”选项通知mysqld不使用外部锁定。(这意味着,你不能在相同的数据目录上运行2mysqld服务器,如果使用myisamchk,必须谨慎。然而,尝试将该选项用作测试也是有益的)。

mysqld看上去正在运行但并未响应时,是否运行了mysqladmin -u root processlist?某些时候,即使你认为mysqld处于闲置状态时,实际情况并非如此。问题可能是因为所有连接均已使用,或存在某些内部锁定问题。即使在该情况下,mysqladmin -u root processlist通常能够进行连接,并能提供关于当前连接数以及其状态的有用信息。

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

尝试采用下述方法:

gdb(或另一个调试器)启动mysqld。请参见E.1.3节,“在gdb环境下调试mysqld

运行测试脚本。

3个较低层面上输出backtrace(向后跟踪)和局部变量。在gdb中,当mysqldgdb内崩溃时,可使用下述命令完成该任务:

backtrace
info local
up
info local
up
info local

使用gdb,你还能检查与info线程共存的线程,并切换至特定的线程N,其中,N是线程ID

尝试用Perl脚本模拟你的应用程序,强制MySQL崩溃或行为异常。

发送正常的缺陷报告。请参见1.7.1.3节,“如何通报缺陷和问题”。应比通常的报告更详细。由于MySQL是为很多人提供服务的,它可能因仅存在于你的计算机上的某事崩溃(例如,与你的特定系统库有关的错误)。

如果你遇到与包含动态长度行的表有关的问题,而且你仅使用VARCHAR(而不是BLOBTEXT列),可尝试用ALTER TABLE将所有VARCHAR列更改为CHAR列。这样,就会强制MySQL使用固定大小的行。固定大小的行占用的空间略多,但对损坏的容忍度更高。

目前的动态行代码在MySQL AB已使用多年,很少遇到问题,但从本质上看,动态长度行更倾向于出现错误,因此,不妨尝试采用该策略以查看它是否有帮助,这不失为一个好主意。

诊断问题时不要将你的服务器硬件排除在外。有缺陷的硬件能够导致数据损坏。对硬件进行故障诊断与排除操作时,尤其应注意RAM和硬盘驱动器。

A.4.3. MySQL处理磁盘满的方式

在本节中,介绍了MySQL响应磁盘满错误的方式(如“设备上无剩余空间”),以及响应超配额错误的方式(如“写入失败”或“达到了用户屏蔽限制”)。

本节介绍的内容与写入MyISAM表有关。它也适用于写入二进制日志文件和二进制索引文件,但对row”和“record”的应用应被视为“event”。

出现磁盘满状况时,MySQL将:

每分钟检查一次,查看是否有足够空间写入当前行。如果有足够空间,将继续,就像什么也未发生一样。

10分钟将1个条目写入日志文件,提醒磁盘满状况。

为了减轻问题,可采取下述措施:

要想继续,仅需有足够的磁盘空间以插入所有记录。

要想放弃线程,必须使用mysqladmin kill。下次检查磁盘时将放弃线程(1分钟)。

其他线程可能会正在等待导致磁盘满状况的表。如果有数个“已锁定”的线程,杀死正在磁盘满状况下等待的某一线程,以便允许其他线程继续。

对前述行为的例外是,当你使用REPAIR TABLEOPTIMIZE TABLE时,或当索引是在LOAD DATA INFILEALTER TABLE语句后、在批操作中创建的。所有这些语句能创建大的临时文件,如果保留这些文件,会导致系统其他部分出现大问题。如果在MySQL执行这类操作的同时磁盘已满,它将删除大的临时文件,并将表标注为崩溃。但对于ALTER TABLE例外,旧表保持不变。

A.4.4. MySQL将临时文件储存在哪里

MySQL使用环境变量TMPDIR的值作为保存临时文件的目录的路径名。如果未设置TMPDIRMySQL将使用系统的默认值,通常为/tmp/var/tmp/usr/tmp。如果包含临时文件目录的文件系统过小,可对mysqld使用“—tmpdir”选项,在具有足够空间的文件系统内指定1个目录。

MySQL 5.1中,“—tmpdir”选项可被设置为数个路径的列表,以循环方式使用。在Unix平台上,路径用冒号字符“:”隔开,在WindowsNetWareOS/2平台上,路径用分号字符“;”隔开。注意,为了有效分布负载,这些路径应位于不同的物理磁盘上,而不是位于相同磁盘的不同分区中。

如果MySQL服务器正作为复制从服务器使用,不应将“--tmpdir”设置为指向基于内存的文件系统的目录,或当服务器主机重启时将清空的目录。对于复制从服务器,需要在机器重启时仍保留一些临时文件,以便能够复制临时表或执行LOAD DATA INFILE操作。如果在服务器重启时丢失了临时文件目录下的文件,复制将失败。

MySQL会以隐含方式创建所有的临时文件。这样,就能确保中止mysqld时会删除所有临时文件。使用隐含文件的缺点在于,在临时文件目录所在的位置中,看不到占用了文件系统的大临时文件。

进行排序时(ORDER BYGROUP BY),MySQL通常会使用1个或多个临时文件。所需的最大磁盘空间由下述表达式决定:

(length of what is sorted + sizeof(row pointer))
* number of matched rows
* 2

row pointer”(行指针)的大小通常是4字节,但在以后,对于大的表,该值可能会增加。

对于某些SELECT查询,MySQL还会创建临时SQL表。它们不是隐含表,并具有SQL_*形式的名称。

ALTER TABLE会在与原始表目录相同的目录下创建临时表。

A.4.5. 如何保护或更改MySQL套接字文件/tmp/mysql.sock

对于服务器用来与本地客户端进行通信的Unix套接字文件,其默认位置是/tmp/mysql.sock。这有可能导致问题,原因在于,在某些版本的Unix上,任何人都能删除/tmp目录下的文件。

在大多数Unix版本中,可对/tmp目录进行保护,使得文件只能被其所有这或超级用户(根用户)删除。为此,以根用户身份登录,并使用下述命令在/tmp目录上设置粘着位:

shell> chmod +t /tmp

通过执行ls -ld /tmp,可检查是否设置了粘着位。如果最后一个许可字符是“t”,表明设置了粘着位。

另一种方法是改变服务器创建Unix套接字文件的位置。如果进行了这类操作,还应让客户端程序知道文件的位置。能够以多种不同方式指定文件位置:

在全局或局部选项文件中指定路径。例如,将下述行置于文件/etc/my.cnf中:

[mysqld]
socket=/path/to/socket
 
[client]
socket=/path/to/socket

请参见4.3.2节,“使用选项文件”

在运行客户端程序时,在命令行上为mysqld_safe指定--socket”选项。

MYSQL_UNIX_PORT环境变量设置为Unix套接字文件的路径。

重新从源码编译MySQL,以使用不同的默认Unix套接字文件位置。运行configure时,用“--with-unix-socket-path”选项定义文件路径。请参见2.8.2节,“典型配置选项

用下述命令连接服务器,能够测试新的套接字位置是否工作:

shell> mysqladmin --socket=/path/to/socket version

A.4.6. 时区问题

如果遇到与SELECT NOW()有关的问题,它返回GMT值而不是当地时间,就应通知服务器你的当前失去。如果UNIX_TIMESTAMP()返回错误值,上述方式同样适用。应为服务器所运行的环境进行这类设置,例如,在mysqld_safemysql.server中。请参见附录F:环境变量

也可以对mysqld_safe使用“--timezone=timezone_name”选项,为服务器设置失去。也可以在启动mysqld之前,通过设置TZ环境变量完成该设置。

--timezone”或TZ的允许值与系统有关。关于可接受的值,请参见操作系统文档。