如果你从未为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”。
应能使用新密码进行连接。
正式发布之前,每个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不使用外部锁定。(这意味着,你不能在相同的数据目录上运行2个mysqld服务器,如果使用myisamchk,必须谨慎。然而,尝试将该选项用作测试也是有益的)。
当mysqld看上去正在运行但并未响应时,是否运行了mysqladmin -u root processlist?某些时候,即使你认为mysqld处于闲置状态时,实际情况并非如此。问题可能是因为所有连接均已使用,或存在某些内部锁定问题。即使在该情况下,mysqladmin -u root processlist通常能够进行连接,并能提供关于当前连接数以及其状态的有用信息。
在运行其他查询的同时,在单独的窗口中运行命令mysqladmin -i 5 status或mysqladmin -i 5 -r status,以生成统计信息。
尝试采用下述方法:
从gdb(或另一个调试器)启动mysqld。请参见E.1.3节,“在gdb环境下调试mysqld”。
运行测试脚本。
在3个较低层面上输出backtrace(向后跟踪)和局部变量。在gdb中,当mysqld在gdb内崩溃时,可使用下述命令完成该任务:
backtrace
info local
up
info local
up
info local
使用gdb,你还能检查与info线程共存的线程,并切换至特定的线程N,其中,N是线程ID。
尝试用Perl脚本模拟你的应用程序,强制MySQL崩溃或行为异常。
发送正常的缺陷报告。请参见1.7.1.3节,“如何通报缺陷和问题”。应比通常的报告更详细。由于MySQL是为很多人提供服务的,它可能因仅存在于你的计算机上的某事崩溃(例如,与你的特定系统库有关的错误)。
如果你遇到与包含动态长度行的表有关的问题,而且你仅使用VARCHAR列(而不是BLOB或TEXT列),可尝试用ALTER TABLE将所有VARCHAR列更改为CHAR列。这样,就会强制MySQL使用固定大小的行。固定大小的行占用的空间略多,但对损坏的容忍度更高。
目前的动态行代码在MySQL AB已使用多年,很少遇到问题,但从本质上看,动态长度行更倾向于出现错误,因此,不妨尝试采用该策略以查看它是否有帮助,这不失为一个好主意。
诊断问题时不要将你的服务器硬件排除在外。有缺陷的硬件能够导致数据损坏。对硬件进行故障诊断与排除操作时,尤其应注意RAM和硬盘驱动器。
在本节中,介绍了MySQL响应磁盘满错误的方式(如“设备上无剩余空间”),以及响应超配额错误的方式(如“写入失败”或“达到了用户屏蔽限制”)。
本节介绍的内容与写入MyISAM表有关。它也适用于写入二进制日志文件和二进制索引文件,但对“row”和“record”的应用应被视为“event”。
出现磁盘满状况时,MySQL将:
每分钟检查一次,查看是否有足够空间写入当前行。如果有足够空间,将继续,就像什么也未发生一样。
每10分钟将1个条目写入日志文件,提醒磁盘满状况。
为了减轻问题,可采取下述措施:
要想继续,仅需有足够的磁盘空间以插入所有记录。
要想放弃线程,必须使用mysqladmin kill。下次检查磁盘时将放弃线程(1分钟)。
其他线程可能会正在等待导致磁盘满状况的表。如果有数个“已锁定”的线程,杀死正在磁盘满状况下等待的某一线程,以便允许其他线程继续。
对前述行为的例外是,当你使用REPAIR TABLE或OPTIMIZE TABLE时,或当索引是在LOAD DATA INFILE或ALTER TABLE语句后、在批操作中创建的。所有这些语句能创建大的临时文件,如果保留这些文件,会导致系统其他部分出现大问题。如果在MySQL执行这类操作的同时磁盘已满,它将删除大的临时文件,并将表标注为崩溃。但对于ALTER TABLE例外,旧表保持不变。
MySQL使用环境变量TMPDIR的值作为保存临时文件的目录的路径名。如果未设置TMPDIR,MySQL将使用系统的默认值,通常为/tmp、/var/tmp或/usr/tmp。如果包含临时文件目录的文件系统过小,可对mysqld使用“—tmpdir”选项,在具有足够空间的文件系统内指定1个目录。
在MySQL 5.1中,“—tmpdir”选项可被设置为数个路径的列表,以循环方式使用。在Unix平台上,路径用冒号字符“:”隔开,在Windows、NetWare和OS/2平台上,路径用分号字符“;”隔开。注意,为了有效分布负载,这些路径应位于不同的物理磁盘上,而不是位于相同磁盘的不同分区中。
如果MySQL服务器正作为复制从服务器使用,不应将“--tmpdir”设置为指向基于内存的文件系统的目录,或当服务器主机重启时将清空的目录。对于复制从服务器,需要在机器重启时仍保留一些临时文件,以便能够复制临时表或执行LOAD DATA INFILE操作。如果在服务器重启时丢失了临时文件目录下的文件,复制将失败。
MySQL会以隐含方式创建所有的临时文件。这样,就能确保中止mysqld时会删除所有临时文件。使用隐含文件的缺点在于,在临时文件目录所在的位置中,看不到占用了文件系统的大临时文件。
进行排序时(ORDER BY或GROUP 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会在与原始表目录相同的目录下创建临时表。
对于服务器用来与本地客户端进行通信的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
如果遇到与SELECT NOW()有关的问题,它返回GMT值而不是当地时间,就应通知服务器你的当前失去。如果UNIX_TIMESTAMP()返回错误值,上述方式同样适用。应为服务器所运行的环境进行这类设置,例如,在mysqld_safe或mysql.server中。请参见附录F:环境变量。
也可以对mysqld_safe使用“--timezone=timezone_name”选项,为服务器设置失去。也可以在启动mysqld之前,通过设置TZ环境变量完成该设置。
“--timezone”或TZ的允许值与系统有关。关于可接受的值,请参见操作系统文档。