վÄÚËÑË÷: ÇëÊäÈëËÑË÷¹ؼü´Ê
µ±ǰҳÃæ: ÔÚÏßÎĵµÊ×ҳ > MySQL 5.1²ο¼ÊֲáÖÐÎİæ

Chapter 5. Database Administration - MySQL 5.1²ο¼ÊֲáÖÐÎİæ

ç¬�5章:数据库管ç��

目录

5.1. MySQL服务器和服务器启动脚æœ�
5.1.1. 服务器端脚本和实用工具概è¿�
5.1.2. mysqld-max扩展MySQL服务å™�
5.1.3. mysqld_safe:MySQL服务器启动脚æœ�
5.1.4. mysql.server:MySQL服务器启动脚æœ�
5.1.5. mysqld_multi:管理多个MySQL服务器的程序
5.2. mysqlmanager:MySQL实例管理å™�
5.2.1. 用MySQL实例管理器启动MySQL服务å™�
5.2.2. 连接到MySQL实例管理器并创建用户账户
5.2.3. MySQL实例管理器命令行选项
5.2.4. MySQL实例管理器配置文ä»�
5.2.5. MySQL实例管理器识别的命令
5.3. mysqld:MySQL服务å™�
5.3.1. mysqld命令行选项
5.3.2. SQL服务器模å¼�
5.3.3. 服务器系统变é‡�
5.3.4. 服务器状态变é‡�
5.4. mysql_fix_privilege_tables:升级MySQL系统è¡�
5.5. MySQL服务器关机进ç¨�
5.6. 一般安全问é¢�
5.6.1. 通用安全指南
5.6.2. 使MySQL在攻击者面前保持安å…�
5.6.3. Mysqld安全相关启动选项
5.6.4. LOAD DATA LOCAL安全问题
5.7. MySQL访问权限系统
5.7.1. 权限系统的作ç”�
5.7.2. 权限系统工作原理
5.7.3. MySQL提供的权é™�
5.7.4. 与MySQL服务器连æŽ�
5.7.5. 访问控制, 阶段1:连接核å®�
5.7.6. 访问控制, 阶段2:请求核å®�
5.7.7. 权限更改何时生效
5.7.8. 拒绝访问错误的原å›�
5.7.9. MySQL 4.1中的密码哈希处理
5.8. MySQL用户账户管理
5.8.1. MySQL用户名和密码
5.8.2. 向MySQL增加新用户账æˆ�
5.8.3. 从MySQL删除用户账户
5.8.4. 限制账户资源
5.8.5. 设置账户密码
5.8.6. 使你的密码安å…�
5.8.7. 使用安全连接
5.9. 备份与恢å¤�
5.9.1. 数据库备ä»�
5.9.2. 示例用备份与恢复策略
5.9.3. 自动恢复
5.9.4. 表维护和崩溃恢复
5.9.5. myisamchk:MyISAM表维护实用工å…�
5.9.6. 建立表维护计åˆ�
5.9.7. 获取关于表的信息
5.10. MySQL本地化和国际应用
5.10.1. 数据和排序用字符é›�
5.10.2. 设置错误消息语言
5.10.3. 添加新的字符é›�
5.10.4. 字符定义数组
5.10.5. 字符串比较支æŒ�
5.10.6. 多字节字符支æŒ�
5.10.7. 字符集问é¢�
5.10.8. MySQL服务器时区支æŒ�
5.11. MySQL日志文件
5.11.1. 错误日志
5.11.2. 通用查询日志
5.11.3. 二进制日å¿�
5.11.4. 慢速查询日å¿�
5.11.5. 日志文件维护
5.12. 在同一台机器上运行多个MySQL服务å™�
5.12.1. 在Windows下运行多个服务器
5.12.2. 在Unix中运行多个服务器
5.12.3. 在多服务器环境中使用客户端程åº�
5.13. MySQL查询高速缓å†�
5.13.1. 查询高速缓冲如何工ä½�
5.13.2. 查询高速缓冲SELECT选项
5.13.3. 查询高速缓冲配ç½�
5.13.4. 查询高速缓冲状态和维护

本章涵盖äº�MySQL安装管理主题,例如配置服务器、管理用户账户和备份ã€�

5.1. MySQL服务器和服务器启动脚æœ�

MySQL服务器,å��mysqld,是åœ�MySQL安装中负责大部分工作的主程序。服务器随附了几个相关脚本,当你安装MySQL时它们可以执行设置操作,或者是帮助你启动和停止服务器的帮助程序ã€�

本节提供了服务器和相关程序的概述,以及服务器启动脚本相关信息。关于配置服务器的信息参è§�5.3节,“mysqld:MySQL服务器â€�ã€�

5.1.1. 服务器端脚本和实用工具概è¿�

MySQL程序采用各种不同的选项。但每个MySQL程序提供一ä¸�--help选项,你可以用来查阅程序选项相关说明。例如,你可以试è¯�mysqld --helpã€�

你可以在命令行中或在选项文件中指定选项来替换所有标准程序中的默认选项。参è§�4.3节,“指定程序选项â€�ã€�

下面简单描述了MySQL服务器和服务器相关程序:

·         mysqld

SQL后台程序(å��MySQL服务å™�)。要想使用客户端程序,该程序必须运行,因为客户端通过连接服务器来访问数据库。参è§�5.3节,“mysqld:MySQL服务器â€�ã€�

·         mysqld-max

包括更多特性的一个服务器版本。参è§�5.1.2节,“mysqld-max扩展MySQL服务器â€�

·         mysqld_safe

服务器启动脚本。如æž�mysqld-max存在,mysqld_safe试图启动它,否则启动mysqld。参è§�5.1.3节,“mysqld_safe:MySQL服务器启动脚本â€�ã€�

·         mysql.server

服务器启动脚本。该脚本用于使用包含为特定级别的运行启动服务的脚本的运行目录的系统。它调用mysqld_safe来启åŠ�MySQL服务器。参è§�5.1.4节,“mysql.server:MySQL服务器启动脚本â€�ã€�

·         mysqld_multi

服务器启动脚本,可以启动或停止系统上安装的多个服务器。参è§�5.1.5节,“mysqld_multi:管理多个MySQL服务器的程序â€�

·         mysql_install_db

该脚本用默认权限创建MySQL授权表。通常只是在系统上首次安装MySQL时执行一次。参è§�2.9.2节,“Unix下安装后的过程â€�ã€�

·         mysql_fix_ privilege_tables

在升级安装后,如果新版本MySQL中的 授权表有更改,则使用该脚本来更改授权表。参è§�2.10.2节,“升级授权表â€�ã€�

服务器主机上还运行其它几个程序:

·         myisamchk

用来描述、检查、优化和维护MyISAM表的实用工具。在5.9.5节,“myisamchk:MyISAM表维护实用工具â€�中描述了myisamchkã€�

·         make_binary_distribution

该程序可以生成编译过çš�MySQL的二进制版本。可以通过FTP上传åˆ�ftp.mysql.comçš�/pub/mysql/upload/,供其它MySQL用户使用ã€�

·         mysqlbug

MySQL 缺陷报告脚本。它可以用来å��MySQL邮件系统发送缺陷报告ã€�(你也可以访问http://bugs.mysql.com/在线创建缺陷报告文件。参è§�1.7.1.3节,“如何通报缺陷和问题â€�ï¼�ã€�

5.1.2. mysqld-max扩展MySQL服务å™�

MySQL-Max服务器是mysqld MySQL服务器的一个版本,包含了更多的特性ã€�

该分发版的使用取决于你的平台ï¼�

·         对于Windowsï¼�MySQL二进制分发版包括标准服务å™� (mysqld.exe)å’�MySQL-Max服务å™�(mysqld-max.exe),因此你不再需要专用分发版。只需要使用一个常è§�Windows分发版,可以ä»�http://dev.mysql.com/downloads/获得。参è§�2.3节,“在Windows上安装MySQLâ€�ã€�

·         对于Linux,如果你使用RPM分发版安è£�MySQL,首先使用常è§�MySQL-server RPM来安装标å‡�mysqld服务器。然后使ç”�MySQL-Max RPM来安è£�mysqld-max服务器ã€�MySQL-Max RPM假定你已经安装了常规服务å™�RPM。关äº�Linux RPM软件包的详细信息,参è§�2.4节,“在Linux下安装MySQLâ€�ã€�

·         所有其å®�MySQL-Max分发版包含一ä¸�mysqld服务器,但具有更多的特性ã€�

你可以从MySQL AB网址http://dev.mysql.com/downloads/找到MySQL-Max二进制版本ã€�

MySQL AB使用下面çš�configure选项构建MySQL-Max服务器:

·         --with-server-suffix=-max

该选项ä¸�mysqld版本字符串添加一ä¸�-max后缀ã€�

·         --with-innodb

该选项启用InnoDB存储引擎支持ã€�MySQL-Max服务器包æ‹�InnoDB支持。在MySQL 4.0及以上版本中,默è®�InnoDB包括在所有二进制分发版中,因此你不需要用MySQL-Max服务器只是用来获å��InnoDB支持ã€�

·         --with-bdb

该选项启用Berkeley DB (BDB)存储引擎支持ã€�

·         --with-blackhole-storage-engine

该选项启用BLACKHOLE存储引擎支持ã€�

·         USE_SYMDIR

启用该定义来ä¸�Windows打开数据库符号链接支持。符号链接支持适用于所æœ�Windows服务器,因此Max服务器不需要支持该特性ã€�

·         --with-ndbcluster

该选项启用NDB Cluster存储引擎支持。目å‰�(5.1.2-alpha)只有Linuxã€�Solariså’�Mac OS X支持Cluster。已有一些用户报告在BSD 操作系统上成功使用了从源码构建的MySQL Cluster,但目前还没有得到官方支持ã€�

MySQL-Max二进制分发版对于想要安装预编译程序的用户很方便。如果你使用源码分发版构å»�MySQL,你可以通过在配置时启用MySQL-Max二进制分发版构建所用的相同的特性来构建你自己的Max-like服务器ã€�

MySQL-Max服务器包æ‹�BerkeleyDB (BDB)存储引擎,但并非所有平台支æŒ�BDBã€�

Solarisã€�Mac OS Xå’�Linux(在大多数平台ä¸�)çš�MySQL-Max服务器包æ‹�NDB CLUSTER存储引擎支持。请注意必须ç”�ndbcluster选项启动服务器,以便使服务器做为MySQL Cluster的一部分来运行ã€�(详细信息参见17.4节,“MySQL簇的配置â€�ï¼�ã€�

下面的表显示äº�MySQL-Max二进制在哪个平台上包æ‹�BDBå’�/æˆ�NDB CLUSTER支持ï¼�

系统

BDB支持

NDB支持

AIX 4.3

N

N

HP-UX 11.0

N

N

Linux-Alpha

N

Y

Linux-IA-64

N

N

Linux-Intel

Y

Y

Mac OS X

N

N

NetWare

N

N

SCO OSR5

Y

N

Solaris-SPARC

Y

Y

Solaris-Intel

N

Y

UnixWare

Y

N

Windows NT/2000/XP

Y

N

要想找出你的服务器支持哪个存储引擎,执行下面的语句:

mysql> SHOW ENGINES;
+------------+---------+----------------------------------------------------------------+
| Engine     | Support | Comment                                                        |
+------------+---------+----------------------------------------------------------------+
| MyISAM     | DEFAULT | Default engine as of MySQL 3.23 with great performance         |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables      |
| HEAP       | YES     | Alias for MEMORY                                               |
| MERGE      | YES     | Collection of identical MyISAM tables                          |
| MRG_MYISAM | YES     | Alias for MERGE                                                |
| ISAM       | NO      | Obsolete storage engine, now replaced by MyISAM                |
| MRG_ISAM   | NO      | Obsolete storage engine, now replaced by MERGE                 |
| InnoDB     | YES     | Supports transactions, row-level locking, and foreign keys     |
| INNOBASE   | YES     | Alias for INNODB                                               |
| BDB        | YES     | Supports transactions and page-level locking                   |
| BERKELEYDB | YES     | Alias for BDB                                                  |
| NDBCLUSTER | NO      | Clustered, fault-tolerant, memory-based tables                 |
| NDB        | NO      | Alias for NDBCLUSTER                                           |
| EXAMPLE    | NO      | Example storage engine                                         |
| ARCHIVE    | YES     | Archive storage engine                                         |
| CSV        | NO      | CSV storage engine                                             |
| FEDERATED  | YES     | Federated MySQL storage engine                                 |
| BLACKHOLE  | YES     | /dev/null storage engine (anything you write to it disappears) |
+------------+---------+----------------------------------------------------------------+
18 rows in set (0.00 sec)

(另参è§�13.5.4.8节,“SHOW ENGINES语法â€�ï¼�ã€�

你还可以使用下面的语句代æ›�SHOW ENGINES,并检查你感兴趣的存储引擎的变量值:

mysql> SHOW VARIABLES LIKE 'have%';
+-----------------------+----------+
| Variable_name         | Value    |
+-----------------------+----------+
| have_archive          | YES      |
| have_bdb              | NO       |
| have_blackhole_engine | YES      |
| have_compress         | YES      |
| have_crypt            | YES      |
| have_csv              | YES      |
| have_example_engine   | NO       |
| have_federated_engine | NO       |
| have_geometry         | YES      |
| have_innodb           | YES      |
| have_isam             | NO       |
| have_ndbcluster       | DISABLED |
| have_openssl          | NO       |
| have_partition_engine | YES      |
| have_query_cache      | YES      |
| have_raid             | NO       |
| have_rtree_keys       | YES      |
| have_symlink          | YES      |
+-----------------------+----------+
18 rows in set (0.01 sec)

SHOW命令的精确输出随使用çš�MySQL版本(和启用的特æ€�)的不同而有变化。第2列的值表示各特性支持的服务器级别,如下所示:

�

含义

YES

 支持该特性并已经激活ã€�

NO

 不支持该特性ã€�

DISABLED

 支持该特性但被禁用ã€�

NO值表示编译的服务器不支持该特性,因此在运行时不能激活ã€�

出现DISABLED值是因为服务器启动时该特性被禁用,或没有给出启用它的所有选项。在后一种情况,host_å��.err错误日志文件应包含该选项被禁用的原因ã€�

如果服务器支æŒ�InnoDBæˆ�BDB存储引擎,你还可以看è§�DISABLED,但在运行启动时使用äº�--skip-innodbæˆ�--skip-bdb选项。对äº�NDB CLUSTER存储引擎ï¼�DISABLED表示服务器支æŒ�MySQL Cluster,但启动时未启用--ndb-cluster选项ã€�

所æœ�MySQL服务器支æŒ�MyISAM表,因为MyISAMæ˜� 默认存储引擎ã€�

5.1.3. mysqld_safe:MySQL服务器启动脚æœ�

åœ�Unixå’�NetWare中推荐使ç”�mysqld_safe来启åŠ�mysqld服务å™�ã€�mysqld_safe增加了一些安全特性,例如当出现错误时重启服务器并向错误日志文件写入运行时间信息。本节后面列出了NetWare的特定行为ã€�

æ³�释:为了保持同旧版本MySQL的向后兼容性,MySQL二进制分发版仍然包括safe_mysqld作为mysqld_safe的符号链接。但是,你不应再依赖它,因为再将来将删掉它ã€�

默认情况下,mysqld_safe尝试启动可执è¡�mysqld-max(如果存在),否则启åŠ�mysqld。该行为的含义是ï¼�

·         åœ�Linux中,MySQL-Max RPM依赖è¯�mysqld_safe的行为ã€�RPM安装可执è¡�mysqld-max,使mysqld_safe从该点起自动使用可执行命令ã€�

·         如果你安装包æ‹�mysqld-max服务器的MySQL-Max分发版,后面升级到非-Maxçš�MySQL版本ï¼�mysqld_safe仍然试图运行旧的 mysqld-max服务å™�。升级时,你应手动删除旧çš�mysqld-max服务å™�以确ä¿�mysqld_safe运行新的mysqld服务å™�ã€�

要想越过默认行为并显式指定你想要运行哪个服务器,ä¸�mysqld_safe指定--mysqldæˆ�--mysqld-version选项ã€�

mysqld_safe的许多选项ä¸�mysqld的相同的。参è§�5.3.1节,â€�mysqld命令行选项â€�ã€�

所有在命令行中ä¸�mysqld_safe指定的选项被传递给mysqldã€�如果你想要使ç”�mysqld不支持的mysqld_safeçš�选项,不要在命令行中指定。相反,在选项文件çš�[mysqld_safe]组内将它们列出来。参è§�4.3.2节,“使用选项文件â€�ã€�

mysqld_safe从选项文件çš�[mysqld]ã€�[server]å’�[mysqld_safe]部分读取所有选项。为了保证向后兼容性,它还读取 [safe_mysqld]部分,尽管在MySQL 5.1安装中你应将这部分重新命名为[mysqld_safe]ã€�

mysqld_safe支持下面的选项ï¼�

·         --help

显示帮助消息并退出ã€�

·         --autoclose

(只在NetWareä¸�)åœ�NetWare中,mysqld_safe可以保持窗口。当你关æŽ�mysqld_safe NLM时,窗口不按默认设置消失。相反,它提示用户输入:

*<NLM has terminated; Press any key to close the screen>*

如果你想è®�NetWare自动关闭窗口,在mysqld_safe中使ç”�--autoclose选项ã€�

·         --basedir=path

MySQL安装目录的路径ã€�

·         --core-file-size=size

mysqld能够创建的内核文件的大小。选项值传递给ulimit -cã€�

·         --datadir=path

数据目录的路径ã€�

·           --defaults-extra-file=path

除了通用选项文件所读取的选项文件名。如果给出,必须首选该选项ã€�

·         --defaults-file=path

读取的代替通用选项文件的选项文件名。如果给出,必须首选该选项ã€�

·         --ledir=path

包含mysqld程序的目录的路径。使用该选项来显式表示服务器位置ã€�

·         --log-error=path

将错误日志写入给定的文件。参è§�5.11.1节,“错误日志â€�ã€�

·         --mysqld=prog_name

想要启动的服务器程序å��(åœ�ledir目录)。如果你使用MySQL二进制分发版但有二进制分发版之外的数据目录需要该选项ã€�

·         --mysqld-version =suffix

该选项类似--mysqld选项,但你只指定服务器程序名的后缀。基本名假定ä¸�mysqldã€�例如,如果你使用--mysqld-version =maxï¼�mysqld_safe启动ledir目录中的mysqld-max程序。如æž�--mysqld-version的参数为空,mysqld_safe使用目录中的mysqldã€�

·         --nice=priority

使用nice程序根据给定值来设置服务器的调度优先级ã€�

·         --no-defaults

不要读任何选项文件。如果给出,必须首选该选项ã€�

·         --open-files-limit=count

mysqld能够打开的文件的数量。选项值传递给 ulimit -n。请注意你需要用root启动mysqld_safe来保证正确工作!

·         --pid-file=path

进程ID文件的路径ã€�

·         --port=port_num

 用来帧听TCP/IP连接的端口号。端口号必须ä¸�1024或更大值,除非MySQLä»�root系统用户运行ã€�

·         --skip-character-set-client-handshake

忽略客户端发送的字符集信息,使用服务器的默认字符集ã€�(选择该选项ï¼�MySQL的动作与MySQL 4.0相同ï¼�ã€�

·         --socket=path

用于本地连接çš�Unix套接字文件ã€�

·         --timezone=zone

为给定的选项值设ç½�TZ时区环境变量。从操作系统文档查阅合法的时区规定格式ã€�

·         --user={user_name | user_id}

以用户名user_name或数字用æˆ�ID user_id运行mysqld服务å™�ã€�(本文中的â€�用户”指系统登录账户,而不æ˜� 授权表中çš�MySQL用户ï¼�ã€�

执行mysqld_safe时,必须先给å‡�--defaults-fileæˆ�--defaults-extra-option,或不使用选项文件。例如,该命令将不使用选项文件ï¼�

mysqld_safe --port=port_num --defaults-file=file_name

相反,使用下面的命令ï¼�

mysqld_safe --defaults-file=file_name --port=port_num

一般情å†�mysqld_safe脚本可以启动从源码或二进åˆ�MySQL分发版安装的服务器,即使这些分发版将服务器安装到稍微不同的位置ã€�(参见2.1.5节,“安装布局â€�ï¼�ã€� mysqld_safe期望下面的其中一个条件是真的ï¼�

·         可以根据调用mysqld_safe的目录找到服务器和数据库。在二进制分发版中,mysqld_safe看上去在binå’�data目录的工作目录下。对于源码分发版,为libexecå’�var目录。如果你ä»�MySQL安装目录执行mysqld_safe应满足该条件(例如,二进制分发版为/usr/local/mysql)ã€�

·         如果不能根据工作目录找到服务器和数据库,mysqld_safe试图通过绝对路径对它们定位。典型位置为/usr/local/libexecå’�/usr/local/var。实际位置由构建分发版时配置的值确定如æž�MySQL安装到配置时指定的位置,它们应该是正确的ã€�

因为mysqld_safe试图通过工作目录找到服务器和数据库,只要你从MySQL安装目录运行mysqld_safeï¼�可以å°�MySQL二进制分发版安装到其它位置:

shell> cd mysql_installation_directory
shell> bin/mysqld_safe &

如果mysqld_safe失败,即使从MySQL安装目录调用仍然失败,你可以指定--ledirå’�--datadir选项来指示服务器和数据库在你的系统中的安装目录ã€�

一般情况,你不应编è¾�mysqld_safe脚本。相反,应使用命令行选项æˆ�my.cnf选项文件çš�[mysqld_safe]部分的选项来配ç½�mysqld_safe。一般不需要编è¾�mysqld_safe来正确启动服务器。但是,如果你编辑,将来升级MySQL后会覆盖你修改的mysqld_safe版本,因此你应对你修改的版本进行备份以便将来重装ã€�

åœ�NetWare中,mysqld_safe是一ä¸�NetWare Loadable Module (NLM),从åŽ�Unix shell脚本移植。它执行ï¼�

1.    检查系统和选项ã€�

2.    检æŸ�MyISAM表ã€�

3.    保持MySQL服务器窗口ã€�

4.    启动并监è§�mysqld,如果因错误终止则重启ã€�

5.    å°�mysqldçš�错误消息发送到数据目录中的host_name.err 文件ã€�

6.    å°�mysqld_safe的屏幕输出发送到数据目录中的host_name.safe文件ã€�

5.1.4. mysql.server:MySQL服务器启动脚æœ�

åœ�Unix中的MySQL分发版包æ‹�mysql.server脚本。它可以用于使用System V-style运行目录来启动和停止系统服务的系统,例如Linuxå’�Solaris。它还用äº�MySQLçš�Mac OS X Startup Itemã€�

mysql.server位于MySQL源码æ �MySQL安装目录下的support-files目录中ã€�

如果你使ç”�Linux 服务å™�RPM软件åŒ�(MySQL-server-VERSION.rpm)ï¼�mysql.server脚本将安装到/etc/init.d目录下,名为mysql。你不需è¦� 手动安装。关äº�Linux RPM软件包的详细信息参见2.4节,“在Linux下安装MySQLâ€�ã€�

一些卖方提供的RPM软件包安装的启动脚本用其它名,例å¦�mysqldã€�

如果你从不自动安è£�mysql.server的源码分发版或二进制分发版格式安è£�MySQL,也可以手动安装。相关说明参è§�2.9.2.2节,“自动启动和停止MySQLâ€�ã€�

mysql.serverä»� [mysql.server]和选项文件çš�[mysqld]部分读取选项ã€�(为了保证向后兼容性,它还读取 [safe_mysqld]部分,尽管在MySQL 5.1安装中你应将这部分重新命名为[mysqld_safe]ï¼�ã€�

5.1.5. mysqld_multi:管理多个MySQL服务器的程序

mysqld_multi可以管理多个帧听不同Unix套接字文件和TCP/IP端口的连接的mysqld 进程。它可以启动或停止服务器,或报告它们的当前状态ã€�

程序寻找my.cnf中的[mysqldN]ç»�(æˆ�--config-file选项指定的文ä»�)ã€�N 可以为任何正整数。在下面的讨论中该数字指选项组号,或GNR。组号区别各选项组,并用ä½�mysqld_multi的参数来指定想要启动、停止哪个服务器或获取哪个服务器的状态报告。这些组中的选项与将用来启动mysqldçš�[mysqld]组中的相同ã€�(例如,参è§�2.9.2.2节,“自动启动和停止MySQLâ€�ï¼�ã€�但是,当使用多个服务器时,需要每个服务器使用自己的选项值,例如Unix套接字文件和TCP/IP端口号。关于在多服务器环境中,每个服务器对应唯一选项的详细信息,参见5.12节,“在同一台机器上运行多个MySQL服务器â€�ã€�

要想调用mysqld_multi,使用下面的语法ï¼�

shell> mysqld_multi [options] {start|stop|report} [GNR[,GNR] ...]

startã€�stopå’�report表示你想要执行的操作。你可以在单个服务器或多个服务器上执行指定的操作,取决于选项名后面的GNR 列。如果没有该列,mysqld_multi为选项文件中的所有服务器执行该操作ã€�

每个GNR值代表一个选项组号或组号范围ã€�GNR值应为选项文件中组名末尾的号。例如,ç»�[mysqld17]çš�GNRä¸�17。要想指定组号的范围,用破折号间隔开ç¬�1个和最å��1个号ã€�GNRå€�10-13代表ç»�[mysqld10]åˆ�[mysqld13]。可以在命令行中指定多个组或组范围,用逗号间隔开ã€�GNR列不能有空格字符(空格æˆ�tab);空格字符后面的内容将被忽略掉ã€�

该命令使用选项ç»�[mysqld17]启动单个服务器:

shell> mysqld_multi start 17

该命令停止多个服务器,使用选项ç»�[mysql8]å’�[mysqld10]è‡�[mysqld13]ï¼�

shell> mysqld_multi stop 8,10-13

使用该命令列出设置选项文件的示例:

shell> mysqld_multi --example

mysqld_multi支持下面的选项ï¼�

·         --config-file=name

指定选项文件名。这关系åˆ�mysqld_multi从哪里寻æ‰�[mysqldN]选项组。没有该选项,从通用my.cnf文件读所有选项。选项不影å“� mysqld_multi从哪里读取自己的选项,总是从通用my.cnf文件çš�[mysqld_multi]组读取ã€�

·         --example

显示示例选项文件ã€�

·         --help

显示帮助消息并退出ã€�

·         --log=name

指定日志文件名。如果该文件存在,后面为日志输出ã€�

·         --mysqladmin=prog_name

用来停止服务器的mysqladmin二进制ã€�

·         --mysqld=prog_name

可用çš�mysqld二进制。请注意你还可以将该选项的值指定为mysqld_safe。选项被传递给 mysqldã€�确保åœ�PATH环境变量设定值或mysqld_safe中有mysqld所在目录ã€�

·         --no-log

按照标准输出打印日志信息,不要写入日志文件。默认情况下,输出写入日志文件ã€�

·         --password=password

调用mysqladmin时使用的MySQL账户的密码。请注意该密码值不是可选项,不象其å®�MySQL程序ã€�

·         --silent

禁用警告ã€�

·         --tcp-ip

通过TCP/IP端口而不æ˜�Unix套接字文件来连接每个MySQL服务器ã€�(如果找不到套接字文件ï¼� 服务器仍然可以运行,但只能通过 TCP/IP端口访问ï¼�ã€�默认情况下,使用Unix套接字文件进行连接。该选项影响stopå’�report操作ã€�

·         --user=user_name

调用mysqladmin时使用的MySQL账户的用户名ã€�

·         --verbose

更详细ã€�

·         --version

显示版本信息并退出ã€�

关于mysqld_multi的一些注解:

·         确保停止mysqld服务å™�(ç”�mysqladmin程序)çš�MySQL账户在各个服务器中的用户名和密码相同。并且应确保账户具有SHUTDOWN权限。如果你想要管理的服务器的管理账户有许多不同的用户名或密码,你需要在每个服务器上创建一个账户,并具有相同的用户名和密码。例如,你可以执行下面的命令为每个服务器设置一个普é€�multi_admin账户ï¼�

·                shell> mysql -u root -S /tmp/mysql.sock -proot_password
·                mysql> GRANT SHUTDOWN ON *.*
·                    -> TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass'ï¼�

参见5.7.2节,“权限系统工作原理â€�。你必须为每ä¸�mysqld服务器执行该操作。当连接时适当更改连接参数。请注意账户名的主机部分必须允许你用multi_admin从你想要运行mysqld_multi的主机进行连接ã€�

·         如果你使ç”�mysqld_safe来启åŠ�mysqld(例如ï¼�--mysqld=mysqld_safe)ï¼�--pid-file选项很重要。每ä¸�mysqld应有自己的进ç¨�ID文件。使ç”�mysqld_safe而不使用mysqld的好处是mysqld_safeâ€�守护”其mysqld进程,如果用kill â€�9发送的信号或由于其它原因(例如分段故障)进程终止,则重启进程。请注意mysqld_safe脚本需要你从某个位置启动它。这说明运行mysqld_multi前你必须进入某个目录。如果启动时有问题,请参è§�mysqld_safe脚本。特别是要检查下列行ï¼�

·                ----------------------------------------------------------------
·                MY_PWD=`pwd`
·                # Check if we are starting this relative (for the binary release)
·                if test -d $MY_PWD/data/mysql -a -f ./share/mysql/english/errmsg.sys -a \
·                -x ./bin/mysqld
·                ----------------------------------------------------------------

参见5.1.3节,“mysqld_safe:MySQL服务器启动脚本â€�。上述行执行的测试应成功,否则你可能遇到了问题ã€�

·         每个mysqldçš�Unix套接字文件和TCP/IP端口号必须不同ã€�

·         你可能想要为mysqld使用--user选项,但为此你需要用Unix root用户运行mysqld_multi脚本。选项文件中有选项不要紧;如果你不是超级用户,并且你用自己çš�Unix账户重启mysqld进程,你只会得到警告ã€�

·         重要:确ä¿�mysqld进程启动所ç”�Unix账户可以完全访问数据目录ã€�不要使用Unix root账户,除非你知道你在做什么ã€�

·         非常重要:使ç”�mysqld_multi前,确保理解传递给mysqld服务器的选项的含义以及你为什ä¹�想要独立çš�mysqld进程。应清楚 在相同的数据目录下使用多ä¸�mysqld服务å™�的危险。使用单独的数据目录,除非你知道你在做什么。在线程系统中,在相同的数据目录下启动多个服务器不会得到超性能。参è§�5.12节,“在同一台机器上运行多个MySQL服务器â€�ã€�

下面的示例显示了你如何设置选项文件来使ç”�mysqld_multi。专门省去第1个和ç¬�5ä¸�[mysqldN]组来说明你的选项文件可以稍有不同。这样给你更大的灵活性ã€�mysqld程序重启或停止的顺序由它们在选项文件中的顺序决定ã€�

# This file should probably be in your home dir (~/.my.cnf)
# or /etc/my.cnf
# Version 2.1 by Jani Tolonen
 
[mysqld_multi]
mysqld     = /usr/local/bin/mysqld_safe
mysqladmin = /usr/local/bin/mysqladmin
user       = multi_admin
password   = multipass
 
[mysqld2]
socket     = /tmp/mysql.sock2
port       = 3307
pid-file   = /usr/local/mysql/var2/hostname.pid2
datadir    = /usr/local/mysql/var2
language   = /usr/local/share/mysql/english
user       = john
 
[mysqld3]
socket     = /tmp/mysql.sock3
port       = 3308
pid-file   = /usr/local/mysql/var3/hostname.pid3
datadir    = /usr/local/mysql/var3
language   = /usr/local/share/mysql/swedish
user       = monty
 
[mysqld4]
socket     = /tmp/mysql.sock4
port       = 3309
pid-file   = /usr/local/mysql/var4/hostname.pid4
datadir    = /usr/local/mysql/var4
language   = /usr/local/share/mysql/estonia
user       = tonu
 
[mysqld6]
socket     = /tmp/mysql.sock6
port       = 3311
pid-file   = /usr/local/mysql/var6/hostname.pid6
datadir    = /usr/local/mysql/var6
language   = /usr/local/share/mysql/japanese
user       = jani

参见4.3.2节,“使用选项文件â€�ã€�

5.2. mysqlmanager:MySQL实例管理å™�

MySQL实例管理å™�(IM)是通过TCP/IP端口运行的后台程序,用来监视和管ç��MySQL数据库服务器实例ã€�MySQL实例管理å™� 适合Unix-类操作系统和Windowsã€�

可以åœ�mysqld_safe脚本使用MySQL实例管理器来启动和停æ­�MySQL服务器,甚至可以从一个远程主æœ�ã€�MySQL实例管理器还执行mysqld_multi脚本的功èƒ�(和大多数语法)。下面为MySQL实例管理器的详细描述ã€�

5.2.1. 用MySQL实例管理器启动MySQL服务å™�

一般情况,ç”�mysql.server脚本启动MySQL Database Serverï¼�MySQL数据库服务器),通常驻留åœ�/etc/init.d/ 文件夹。默认情况下该脚本调ç”�mysqld_safe脚本。但是,你可以在脚本中将use_mysqld_safe变量设置ä¸�0(é›�)以便使用MySQL实例管理器来启动服务器ã€�

在这种情况下ï¼�Instance Manager的行为取决于MySQL配置文件中的选项。如果没有配置文件,MySQL实例管理器创å»�mysqld实例并试图用默认(编译嵌入çš�)配置来启动。这说明如果mysqld没有安装åˆ� 默认位置ï¼�IM不能猜出它的位置。如果你已经在非标准位置安装äº�MySQL服务器,你应使用配置文件。参è§�2.1.5节,“安装布局â€�ã€�

如果有配置文件,IM将分析配置文件搜ç´�[mysqld]部分(例如[mysqld]ã€�[mysqld1]ã€�[mysqld2]ç­�)。每个部分指定一个实例。启动时IM将启动所有找到的实例ã€�IM关闭时默认停止所有实例ã€�

请注意有一个特殊选项mysqld-path(mysqld-path = path-to-mysqld- binary),只能用IM识别。使用该变量è®�IM知道mysqld二进制驻留在哪儿。你还应该为服务器设ç½�basedirå’�datadir选项ã€�

启用MySQL实例管理器的典型MySQL服务器启åŠ�/关闭循环为:

·          ç”�/etc/init.d/mysql脚本启动MySQL实例管理器ã€�

·          MySQL实例管理器启动所有实例并监视它们ã€�

·         如果某个服务器实例失败,MySQL实例管理器重启它ã€�

·         如果MySQL实例管理器被关闭(例如ç”�/etc/init.d/mysql stop命令),所有实例被MySQL实例管理器关闭ã€�

5.2.2. 连接到MySQL实例管理器并创建用户账户

使用MySQL客户ç«�-服务器协议来处理å��MySQL实例管理器之间的通信。你不能使用标准mysql客户端程序和MySQL C API来连æŽ�IMã€�IM支持客户端工具和mysql-4.1或以后的版本所分发的库所用的MySQL客户ç«�-服务器协议版本ã€�

IM将用户信息保存到密码文件中。密码文件的默认位置ä¸�/etc/mysqlmanager.passwdã€�

密码应类似于ï¼�

petr:*35110DC9B4D8140F5DE667E28C72DD2597B5C848

要想生成密码ç”�--passwd选项调用IM。则输出可以重定向到/etc/mysqlmanager.passwd文件以添加新用户。下面为示例命令ã€�

./mysqlmanager --passwd >> /etc/mysqlmanager.passwd
Creating record for new user.
Enter user name: mike
Enter password: <password>
Re-type password: <password>

下面的行将加åˆ�/etc/mysqlmanager.passwdï¼�

mike:*00A51F3F48415C7D4E8908980D443C29C69B60C9

如果/etc/mysqlmanager.passwd文件中没有该条,则不能连æŽ�IMã€�

5.2.3. MySQL实例管理器命令行选项

MySQL实例管理器支持许多命令行选项。执è¡�./mysqlmanager --help命令可以简单列出。有下面的选项ï¼�

·         --helpï¼�-?

显示帮助消息并退出ã€�

·         --bind-address=name

绑定地址用于连接ã€�

·         --default-mysqld-path=name

åœ�Unix中,如果实例部分没有路径,则为寻æ‰�MySQL服务器二进制的地点。例如:default-mysqld-path = /usr/sbin/mysqld

·         --defaults-file=file_name

从给定文件读Instance Managerå’�MySQL服务器设定值。所æœ�Instance Manager更改的配置将加入该文件。只能用äº�Instance Manager的第一选项ã€�

·         --install

åœ�Windows中,å°�Instance Manager安装ä¸�Windows服务ã€�

·         --log=name

IM日志文件的路径。结å��--run-as-service选项使用ã€�

·         --monitoring-interval=Seconds

监视实例的间隔,单位为秒ã€�Instance Manager将尝试连接每个监视的实例来检查它们是否是活动çš�/没有挂起。出现故障,IM将重启几æ¬�(实际上是多次)实例。可以用nonguarded选项为特定实例禁用该行为。如果未给定任何值, 默认使用20秒ã€�

·         --passwdï¼�-P

编写passwd文件并退出ã€�

·         --password-file=name

从该文件中寻æ‰�Instance Manager用户和密码。默认文件是/etc/mysqlmanager.passwdã€�

·         --pid-file=name

使用的进ç¨�ID文件。默认情况下,该文件文件名为mysqlmanager.pidã€�

·         -- port=port_num

用于连接的端口号ã€�(IANA分配çš� 默认端口号为2273)ã€�

·         --print-defaults

打印当前的默认值并退出。只能用ä½�Instance Manager的第一选项ã€�

·         --remove

åœ�Windows中,删掉Instance Manager Windows服务。假定前面已经用--install运行äº�Instance Managerã€�

·         --run-as-service

使完善进程变为后台程序并启动。完善进程很简单,不易崩溃。出现故障后它将自己重启IMã€�

·         --socket=name

Unix中用于连接的套接字文件。默认情况下,文件名ä¸�/tmp/mysqlmanager.sockã€�

·         --standalone

åœ�Windows中以单机模式运行Instance Managerã€�

·         --user=name

启动并运è¡�mysqlmanager的用户名。建议使用运è¡�mysqld服务å™�的用户账户来运行mysqlmanagerã€�

·         --version, -V

输出版本信息并退出ã€�

5.2.4. MySQL实例管理器配置文ä»�

Instance Manager使用标准my.cnf文件。它使用[manager]部分为自己读取选项并读å��[mysqld]部分来创建实例ã€�[manager]部分包含上述列出的选项。下面为[manager]部分示例ï¼�
# MySQL Instance Manager options section
[manager]
default-mysqld-path = /usr/local/mysql/libexec/mysqld
socket=/tmp/manager.sock
pid-file=/tmp/manager.pid
password-file = /home/cps/.mysqlmanager.passwd
monitoring-interval = 2
port = 1999
bind-address = 192.168.1.5

MySQL实例管理器只åœ�Unix中读取并管理/etc/my.cnf文件。在Windows中,MySQL实例管理器从Instance Manager的安装目录读å��my.ini文件。用--defaults-file=file_ name选项可以更改默认选项文件的位置ã€�

实例部分指定启动时给每个实例的选项。这些主要是普é€�MySQL服务器选项,但有一äº�IM-专用选项ï¼�

·         mysqld-path = <path-to-mysqld-binary>

mysqld服务å™�二进制的路径ã€�

·         shutdown-delay = Seconds

IM应等待实例关闭的秒数ã€� 默认ä¸�35秒。超过延迟时间后ï¼�IM假定实例正挂起并试图â€�kill â€�9â€�它。如果你使用å¸�large表的InnoDB,你应当增加该值ã€�

·         nonguarded

如果你想要为某个实例禁用IM监视功能,应设置该选项ã€�

下面给出了几个实例示例ã€�

[mysqld]
mysqld-path=/usr/local/mysql/libexec/mysqld
socket=/tmp/mysql.sock
port=3307
server_id=1
skip-stack-trace
core-file
skip-bdb
log-bin
log-error
log=mylog
log-slow-queries
 
[mysqld2]
nonguarded
port=3308
server_id=2
mysqld-path= /home/cps/mysql/trees/mysql-5.1/sql/mysqld
socket     = /tmp/mysql.sock5
pid-file   = /tmp/hostname.pid5
datadir= /home/cps/mysql_data/data_dir1
language=/home/cps/mysql/trees/mysql-5.1/sql/share/english
log-bin

log=/tmp/fordel.log

5.2.5. MySQL实例管理器识别的命令

一旦你已经ä¸�MySQL实例管理器设置了一个密码文件并ä¸�IM正在运行,你可以连接它。你可以使用mysql客户端工具通过标准MySQL API来连接。以下是MySQL实例管理器目前可以接收的命令的清单和例子ã€�

·         START INSTANCE <instance_name>

该命令将试图启动一个实例:

mysql> START INSTANCE mysqld4;
Query OK, 0 rows affected (0,00 sec)

·         STOP INSTANCE <instance_name>

将试图停止一个实例:

mysql> STOP INSTANCE mysqld4;
Query OK, 0 rows affected (0,00 sec)

·         SHOW INSTANCES

显示所有载入的实例名:

mysql> show instances;
+---------------+---------+
| instance_name | status  |
+---------------+---------+
| mysqld3       | offline |
| mysqld4       | online  |
| mysqld2       | offline |
+---------------+---------+
3 rows in set (0,04 sec)

·         SHOW INSTANCE STATUS <instance_name>

显示选定的实例的状态和版本信息ï¼�

mysql> SHOW INSTANCE STATUS mysqld3;
+---------------+--------+---------+
| instance_name | status | version |
+---------------+--------+---------+
| mysqld3       | online | unknown |
+---------------+--------+---------+
1 row in set (0.00 sec)

·         SHOW INSTANCE OPTIONS <instance_name>

显示实例使用的选项ï¼�

mysql> SHOW INSTANCE OPTIONS mysqld3;
+---------------+---------------------------------------------------+
| option_name   | value                                             |
+---------------+---------------------------------------------------+
| instance_name | mysqld3                                           |
| mysqld-path   | /home/cps/mysql/trees/mysql-4.1/sql/mysqld        |
| port          | 3309                                              |
| socket        | /tmp/mysql.sock3                                  |
| pid-file      | hostname.pid3                                     |
| datadir       | /home/cps/mysql_data/data_dir1/                   |
| language      | /home/cps/mysql/trees/mysql-4.1/sql/share/english |
+---------------+---------------------------------------------------+
7 rows in set (0.01 sec)

·         SHOW <instance_name> LOG FILES

该命令提供实例使用的所有日志文件。结果包含日志文件的路径和日志文件的大小。如果没有在配置文件中指定日志文件的路径 (例如log=/var/mysql.log)ï¼�IM试图猜出它的位置。如æž�IM不能猜出日志文件的位置,你应明确指定日志文件的位置ã€�

mysql> SHOW mysqld LOG FILES;
+-------------+------------------------------------+----------+
| Logfile     | Path                               | Filesize |
+-------------+------------------------------------+----------+
| ERROR LOG   | /home/cps/var/mysql/owlet.err      | 9186     |
| GENERAL LOG | /home/cps/var/mysql/owlet.log      | 471503   |
| SLOW LOG    | /home/cps/var/mysql/owlet-slow.log | 4463     |
+-------------+------------------------------------+----------+
3 rows in set (0.01 sec)

·         SHOW <instance_name> LOG {ERROR | SLOW | GENERAL} size[,offset_from_end]

该命令查找指定的日志文件的一部分。因为大多数用户关注最新的日志消息,用size参数定义你想要从日志末尾开始索取的字节数。你可以指定可é€�offset_from_end参数从日志文件中部索取数据。下面的示例可以索取21个字节的数据,从日志文件末尾开å§�23个字节,2个字节用于结束:

mysql> SHOW mysqld LOG GENERAL 21, 2;
+---------------------+
| Log                 |
+---------------------+
| using password: YES |
+---------------------+
1 row in set (0.00 sec)

·         SET instance_name.option_name=option_value

该命令编辑指定的实例的配置文件以更改/增加实例选项ã€�IM假定配置文件位于/etc/my.cnf。你应检查文件是否存在,并具有合适的权限ã€�

mysql> SET mysqld2.port=3322;
Query OK, 0 rows affected (0.00 sec)

åœ�MySQL服务器重启前,对配置文件进行的更改不会生效。并且,执行FLUSH INSTANCES命令后,才会将这些更改保存到Instance Manager的实例设定值的本地缓存中ã€�

·         UNSET instance_name.option_name

该命令从实例的配置文件删除一个选项ã€�

mysql> UNSET mysqld2.port;
Query OK, 0 rows affected (0.00 sec)

åœ�MySQL服务器重启前,对配置文件进行的更改不会生效。并且,执行FLUSH INSTANCES命令后,才会将这些更改保存到Instance Manager的实例设定值的本地缓存中ã€�

·         FLUSH INSTANCES

该命令强åˆ�IM重读配置文件并清空内部结构。编辑配置文件后应执行该命令。该命令不重启实例:

mysql> FLUSH INSTANCES;
Query OK, 0 rows affected (0.04 sec)

5.3. mysqld:MySQL服务å™�

mysqldæ˜�MySQL服务器。下面讨è®�MySQL服务器的配置ï¼�

·         服务器支持的启动选项

·         如何设置服务å™�SQL模式

·         服务器系统变é‡�

·         服务器状态变é‡�

5.3.1. mysqld命令行选项

当启åŠ�mysqld服务å™�时,你可以使ç”�4.3节,“指定程序选项â€�中描述的方法指定程序选项。最常用的方法是在选项文件中或在命令行提供选项。但是,在大多数情况下,希望服务器每次运行时使用相同的选项。最好的方法是确保将它们列在选项文件中。参è§�4.3.2节,“使用选项文件â€�ã€�

mysqldä»�[mysqld]å’�[server]组读取选项ã€�mysqld_safeä»�[mysqld]ã€�[server]ã€�[mysqld_safe]å’�[safe_mysqld]组读取选项ã€�mysql.serverä»� [mysqld]å’�[mysql.server]组读取选项。嵌入式MySQL服务器通常ä»�[server]ã€�[embedded]å’�[xxxxx_SERVER]组读取选项,其ä¸�xxxxx是服务器嵌入的应用程序名ã€�

mysqld接受许多命令行选项。执è¡�mysqld --help可以简单列出来。要想看全部列表列,使用命令mysqld --verbose --helpã€�

下面列出了一些最常用的服务器选项。其它的选项在其它地方描述:

·         影响安全的选项:参è§�5.6.3节,“Mysqld安全相关启动选项â€�ã€�

·         SSL-相关选项:参è§�5.8.7.6节,“SSL命令行选项â€�ã€�

·         二进制日志控制选项:参è§�5.11.3节,“二进制日志â€�ã€�

·         复制相关选项:参è§�6.8节,“复制启动选项â€�ã€�

·         特定存储引擎相关选项:参è§�15.1.1节,“MyISAM启动选项â€�ã€�15.5.3节,“BDB启动选项â€�å’�15.2.4节,“InnoDB启动选项â€�ã€�

你还可以将变量名作为一个选项,设置服务器系统变量的值,如本节后面所述ã€�

·         --helpï¼�-?

显示简短的帮助消息并退出。使ç”�--verboseå’�--help选项来看全部内容ã€�

·         --allow-suspicious-udfs

该选项控制是否用户定义的函数只有一ä¸�xxx符,用作可载入的主函数。默认情况下,该选项被关闭,只有至少有一个附属符çš�UDF  可以载入。这样可以防止从未包含合æ³�UDF的共享文件装载函数。参è§�27.2.3.6节,“用户定义函数安全注意事项â€�ã€�

·         --ansi

使用标准(ANSI)SQL语法代替MySQL语法。参è§�1.8.3节,“在ANSI模式下运行MySQLâ€�。使ç”�--sql-mode选项可以更精确控制服务器SQL模式ã€�

·         --basedir=path, -b path

MySQL安装目录的路径。通常所有路径根据该路径来解析ã€�

·         --bind-address=IP

待绑定的IP地址ã€�

·         --bootstrap

mysql_install_db脚本使用该选项来创å»�MySQL授权表,不需要启åŠ�MySQL服务器ã€�

·         --console

将错误日志消息写å…�stderrå’�stdout,即使指定了--log-error。在Windows中,如果使用该选项ï¼�mysqld不关闭控制台窗口ã€�

·         --character-sets-dir=path

字符集安装的目录。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --chroot=path

通过chroot()系统调用在启动过程中å°�mysqld服务器放入一个封闭环境中。这是推荐的一个安全措施。请注意使用该选项可以 限制LOAD DATA INFILEå’�SELECT ... INTO OUTFILEã€�

·         --character-set-server=charset

使用charset作为 默认服务器字符集。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --core-file

如果mysqld终止,写内核文件。在某些系统中,你还必须ä¸�mysqld_safe指定--core-file-size 选项。参è§�5.1.3节,“mysqld_safe:MySQL服务器启动脚本â€�。请注意对于一些系统,例如Solaris,如果你使用--user选项不会获得内核文件ã€�

·         --collation-server=collation

使用collation作为 默认服务器校对规则。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --datadir=path, -h path

数据目录的路径ã€�

·         --debug[=debug_options], -# [debug_options]

如果MySQL配置äº�--with-debug,你可以使用该选项来获得一个跟踪文件,跟踪mysqld正进行的操作ã€�debug_options字符串通常ä¸�'d:t:oï¼�file_name'。参è§�E.1.2节,“创建跟踪文件â€�ã€�

·         (DEPRECATED) --default-character-set=charset

使用char设置作为 默认字符集。由äº�--character-set-server,反对使用该选项。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --default-collation=collation

使用collation 作为默认校对规则。由äº�--collation-server,反对使用该选项。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --default-storage-engine=type

该选项ä¸�--default-table-type的同义词ã€�

·         --default-table-type=type

设置表的默认类型。参è§�ç¬�15章:存储引擎和表类型ã€�

·         --default-time-zone=type

设置默认服务器时区。该选项设置全局time_zone系统变量。如果未给出该选项ï¼� 默认时区与系统时区相å��(ç”�system_time_zone系统变量值给å®�)ã€�

·         --delay-key-write[= OFF | ON | ALL]

如何使用DELAYED KEYS选项。键写入延迟会造成再次å†�MyISAM表时键缓冲区不能被清空ã€�OFF禁用延迟的键写入ã€�ON启用ç”�DELAYED KEYS选项创建的表的延迟的键写入ã€�ALL延迟所æœ�MyISAM表的键写入。参è§�7.5.2节,“调节服务器参数â€�。参è§�15.1.1节,“MyISAM启动选项â€�ã€�

æ³�释:如果你将该变量设置为ALL,你不应从另一个正使用MyISAM表的程序中使ç”�MyISAMè¡�(例如从另一ä¸�MySQL服务器或ç”�myisamchk)。这样操作会导致索引破坏ã€�

·         --des-key-file=file_name

从该文件è¯�DES_ENCRYPT()å’�DES_DECRYPT()使用çš� 默认键ã€�

·         --enable-named-pipe

启用命名管道支持。该选项只适用Windows NTã€�2000ã€�XPå’�2003系统,并且只适用支持命名管道连接çš�mysqld-ntå’�mysqld-max-nt服务器ã€�

 

·         --exit-info[=flags], -T [flags]

这是不同标志的一个位掩码,你可以用来调试mysqld服务å™�。不要使用该选项,除非你确切知道它在做什么!

·         --external-locking

启用系统锁定。请注意如果你在lockd不能完全工作的系统上使用该选项(例如åœ�Linuxä¸�)ï¼�mysqld容易死锁。该选项以前å��--enable-lockingã€�

æ³�释:如果你在许多MySQL进程中使用该选项来更æ–�MyISAM表,你必须确保满足下述条件:

o        使用正被另一个进程更新的表的查询的缓存不可使用ã€�

o        不应在共享表中使ç”�--delay-key-write=ALLæˆ�DELAY_KEY_WRITE=1ã€�

最简单的方法是结合使ç”�--external-lockingå’�--delay-key-write=OFF --query-cache-size=0ã€�

(默认不能实现,因为在许多设置中,结合使用上述选项很有用)ã€�

·         --flush

执行SQL语句后向硬盘上清空更改。一般情况执è¡�SQL语句å�� MySQL向硬盘写入所有更改,让操作系统处理与硬盘的同步。参è§�A.4.2节,“如果MySQL依然崩溃,应作些什么â€�ã€�

·         --init-file=file

启动时从该文件读SQL语句。每个语句必须在同一行中并且不应包括注释ã€�

·         --language=lang_name, -L lang_name

用给定语言给出客户端错误消息ã€�lang_name可以为语言名或语言文件安装目录的全路径名。参è§�5.10.2节,“设置错误消息语言â€�ã€�

·         --large-pages

一些硬ä»�/操作系统架构支持大于 默认å€�(通常4 KB)的内存页。实际支持取决于使用的硬件和OS。大量访问内存的应用程序通过使用较大的页,降低了Translation Lookaside Buffer (TLB)损失,可以改善性能ã€�

目前ï¼�MySQL只在Linux中支持大页面(åœ�Linux中被称作HugeTLB)。我们已经计划将该支持扩展到FreeBSDã€�Solaris和其它可能的平台ã€�

åœ�Linux中可以使用大页面前,需要配ç½�HugeTLB内存池。参è€�Linux内核源码中的hugetlbpage.txt文件ã€�

默认情况下该选项被禁用ã€�

·         ---log[=file], -l [file]

日志连接和对文件的查诀€‚参è§�5.11.2节,“通用查询日志â€�。如果你不指定文件名ï¼�MySQL使用host_name.log作为文件名ã€�

·         --log-bin=[file]

二进制日志文件。将更改数据的所有查询记入该文件。用于备份和复制。参è§�5.11.3节,“二进制日志â€�。建议指定一个文件名(原因参见A.8.1节,“MySQL中的打开事宜â€�),否åˆ�MySQL使用host_name-bin作为日志文件基本名ã€�

·         --log-bin-index[=file]

二进制日志文件名的索引文件。参è§�5.11.3节,“二进制日志â€�。如果你不指定文件名,并且如果你没有åœ�--log-bin中指定,MySQL使用host_name-bin.index作为文件名ã€�

·         --log-bin-trust-routine-creators[={0|1}]

没有参数或参数为1,该选项将系统变é‡�log_bin_trust_routine_creators设置ä¸�1。为参数 0时,该选项将系统变量设置为0ã€�log_bin_trust_routine_creators影响MySQL如何对保存的程序的创建强加限制。参è§�20.4节,“存储子程序和触发程序的二进制日志功能â€�ã€�

·         --log-error[=file]

该文件的日志错误和启动消息。参è§�5.11.1节,“错误日志â€�。如果你不指定文件名ï¼�MySQL使用host_name.err作为文件名。如果文件名没有扩展名,则加ä¸�.err扩展名ã€�

·         --log-isam[=file]

将所æœ�MyISAM更改记入该文ä»�(只有调试MyISAM时才使用)ã€�

·         (DEPRECATED) --log-long-format

记录激活的更新日志、二进制更新日志、和慢查询日志的大量信息。例如,所有查询的用户名和时间戳将记录下来。不赞成选用该选项,因为它现在代表 默认记录行为ã€�(参见--log-short-format描述ï¼�ã€�--log-queries-not-using-indexes选项适合将未使用索引的查询记录到慢查询日志中ã€�

·         --log-queries-not-using-indexes

如果你结å��--log-slow-queries使用该选项,未使用索引的查询也被记录到慢查询日志中。参è§�5.11.4节,“慢速查询日志â€�ã€�

·         --log-short-format

记录激活的更新日志、二进制更新日志、和慢查询日志的少量信息。例如,用户名和时间戳不记录下来ã€�

·         ---log-slow-admin-statements

将慢管理语句例如OPTIMIZE TABLEã€�ANALYZE TABLEå’�ALTER TABLE记入慢查询日志ã€�

·         --log-slow-queries[=file]

将所有执行时间超è¿�long_query_time 秒的查询记入该文件。参è§�5.11.4节,“慢速查询日志â€�。详细信息参è§�--log-long-formatå’�--log-short-format选项描述ã€�

 

·         --log-warnings, -W

将警告例å¦�Aborted connection...打印到错误日志。建议启用该选项,例如,如果你使用复åˆ� (你可以得到关于所发生事情的详细信息,例如关于网络故障和重新连接的消息)。默认情况下启用该选项;要想禁用它,使ç”�--skip-log-warnings。中断的连接不会记入错误日志,除非值大äº�1。参è§�A.2.10节,“通信错误和失效连接â€�ã€�

·         --low-priority-updates

表修æ”�(INSERT, REPLACE, DELETE, UPDATE)比选择的优先级要低。也可以通过{INSERT | REPLACE | DELETE | UPDATE} LOW_PRIORITY ... 来降低某个查询的优先级来实现,或通过SET LOW_PRIORITY_UPDATES=1来更改一个线程的优先级。参è§�7.3.2节,“表锁定事宜â€�ã€�

·          --memlock

å°�mysqld 进程锁定在内存中。在支持mlockall()系统调用的系统上有效,例å¦�Solaris。如果操作系统使mysqld在硬盘上交换时出现问题,可以为你提供帮助。请注意使用该选项时需要以root运行服务器,但从安全考虑并不是一个好注意ã€�

·         --myisam-recover [=option[,option...]]]

将存储引æ“�MyISAM设置为恢复模式。该选项值是DEFAULTã€�BACKUPã€�FORCEæˆ�QUICK值的任何组合。如果你指定多个值,用逗号间隔开。你还可以使ç”�""值来禁用该选项。使用如果该选项,当mysqld打开MyISAM表时,检查是否表标记为崩溃或没有正确关闭ã€�(只有ç”�--skip-external-lockingare运行时,最后的选项才工作)ã€� 如果是这种情况,mysqld则检æŸ� 表。如果表被破坏,mysqld试图维护它ã€�

下面的选项影响维护工作ï¼�

选项

描述

DEFAULT

与没有使ç”�--myisam-recover选项相同ã€�

BACKUP

如果在恢复过程中,数据文件被更改了,å°�tbl_name.MYD文件备份ä¸�tbl_name-datetime.BAKã€�

FORCE

即使.MYD文件将丢掉多个行也进行恢复ã€�

QUICK

如果没有删除块,不要检查表中的行ã€�

在表自动修复前,MySQL错误日志添加一条注解。如果你不想用户干涉干涉大多数问题,你应使用BACKUP,FORCE选项。该选项强制维护表,即使一些行将会被删除也不例外,但它保持旧的数据文件做为备份,以便你可以在后来进行检查ã€�

·         --ndb-connectstring=connect_string

当使ç”�NDB存储引擎时,可以指出通过设置连接字符串选项来分发群集配置的管理服务器。相关语法参è§�17.4.4.2节,“MySQL簇连接字符串â€�ã€�

·         --ndbcluster

如果二进制支æŒ�NDB CLUSTER存储引擎,使用该选项可以代替禁用MySQL Cluster支持çš� 默认设置。参è§�ç¬�17章:MySQLç°�ã€�

·         --old-passwords

强制服务器为新密码生成短(4.1å‰�)密码哈希。如果服务器必须支持旧客户端程序,为保证兼容性这很有用。参è§�5.7.9节,“MySQL 4.1中的密码哈希处理â€�ã€�

·         --one-thread

只使用一个线ç¨�(用于åœ�Linux中调è¯�)。只有服务器启用了调试,该选项才可用。参è§�E.1节,“调试MySQL服务器â€�ã€�

·         --open-files-limit=count

用来更改mysqld文件描述符的数量。如果没有设置或设置ä¸�0,则mysqld通过setrlimit()使用该值来保存文件描述符。如果该值为0,则mysqld 保存max_connections*5æˆ�max_connections + table_cache*2(取较大è€�)个文件。如æž�mysqld给出你错è¯�"打开的文件太多ã€�",你应试试增加该值ã€�

·         --pid-file=path

mysqld_safe使用的进ç¨�ID文件的路径ã€�

·         --port=port_num, -P port_num

帧听TCP/IP连接时使用的端口号ã€�

·         --safe-mode

跳过一些优化阶段ã€�

·         (DEPRECATED) --safe-show-database

参见5.7.3节,“MySQL提供的权限â€�ã€�

·         --safe-user-create

启用后如果用户没æœ�mysql.user表或表中列的INSERT权限,则用户不能ç”�GRANT语句创建新用户ã€�

·         --secure-auth

不允许使用旧(4.1之前)密码的账户进行鉴定ã€�

·         --shared-memory

启用本地客户端的共享内存连接。该选项只用äº�Windowsã€�

·         --shared-memory-base-name=name

共享内存连接名。该选项只用äº�Windowsã€�

·         --skip-bdb

禁用BDB存储引擎。这样可以节省内存,并可能加速某些操作。如果你需è¦�BDB表则不要使用该选项ã€�

·         --skip-concurrent-insert

关闭在同一时间åœ�MyISAM表中选择和插入的能力ã€�(只有你发现缺陷时才使用该选项ï¼�ã€�

·         --skip-external-locking

不要使用系统锁定。要想使ç”�myisamchk,你必须关闭服务器ã€�(参见1.4.3节,“MySQL稳定性â€�ï¼�ã€� 要避免该需求,使用MySQL Monitor中的CHECK TABLEå’�REPAIR TABLE来检查并维护MyISAM表ã€�

·         --skip-grant-tables

该选项使服务器不使用权限系统。该权限允许访问服务器的用户不受限制地访é—�所æœ�数据åº�。你可以从系统外壳命令行执行mysqladmin flush-privilegesæˆ�mysqladmin reload命令,或执行MySQL FLUSH PRIVILEGES语句让运行的服务器重新开始使ç”� 授权表ã€�

·         --skip-host-cache

为了更快地在名称-IP之间进行解析,不要使用内部主机名缓存。相反,每次客户端连接时查询DNS服务器。参è§�7.5.6节,“MySQL如何使用DNSâ€�ã€�

·         --skip-innodb

禁用InnoDB存储引擎。这样可以节省内存,并可能加速某些操作。如果你需è¦�BDB表则不要使用该选项ã€�

·         --skip-name-resolve

不要解析正检查客户端连接的主机名。只使用IP号。如果你使用该项ï¼� 授权表中的所æœ�Host列值必须为IP号或localhost。参è§�7.5.6节,“MySQL如何使用DNSâ€�ã€�

·         --skip-ndbcluster

禁用NDB CLUSTER存储引擎。这是支æŒ�NDB CLUSTER存储引擎的二进制的默认设置,说明只有ç”�--ndbcluster选项显式覆盖--skip-ndbcluster选项时,系统才为该存储引擎分配内存和其它资源。使用示例参è§�17.4.3节,“MySQL簇的快速测试设置â€�ã€�

·         --skip-networking

不帧å��TCP/IP连接。必须通过命名管道或共享内å­�(åœ�Windowsä¸�)æˆ�Unix套接字文ä»�(åœ�Unixä¸�)完成mysqld的相互操作。对于只允许本地客户端的系统,大力推荐该选项。参è§�7.5.6节,“MySQL如何使用DNSâ€�ã€�

·         --standalone

只适合基于Windows-NT的系统;指导MySQL服务器不做为服务来运行ã€�

·         --symbolic-links, --skip-symbolic-links

启用或禁用符号链接支持。在Windowså’�Unix中,该选项的作用是不同的:

o        åœ�Windows中,启用符号链接,你可以通过创建包含实际目录路径çš�directory.sym文件来建立数据库目录的符号链接。参è§�7.6.1.3节,“在Windows平台上使用关于数据库的符号链接â€�ã€�

åœ�Unix中,启用符号链接表示你可以用CREATE TABLE语句çš�INDEX DIRECTORYæˆ�DATA DIRECTORY选项å°�MyISAM索引文件或数据文件链接到另一个目录。如果你删除或重新命名表,符号链接所指的文件也被删除或重新命名。参è§�13.1.5节,“CREATE TABLE语法â€�ã€�

·         --skip-safemalloc

如果MySQL配置äº�--with-debug=full,所æœ�MySQL程序在内存分配和释放时检查内存是否溢出。检查很慢,因此如果你不需要你可以ç”�--skip-safemalloc选项来避免ã€�

·         --skip-show-database

使用该选项,只允许具有SHOW DATABASES权限的用户执è¡�SHOW DATABASES语句,该语句显示所有数据库名。不使用该选项,允许所有用户执è¡�SHOW DATABASES,但只向具有SHOW DATABASES权限或部分数据库权限的用户显示每个数据库名。请注意全局权限为数据库的一种权限ã€�

·         --skip-stack-trace

不跟踪写堆栈。当调试运行mysqld时该选项有用。在一些系统中,你还必须使用该选项来获得内核文件。参è§�E.1节,“调试MySQL服务器â€�ã€�

·         --skip-thread-priority

在快速响应中禁用线程优先级ã€�

·         --socket=path

åœ�Unix中,该选项指定用于本地连接çš�Unix套接字文件ã€� 默认值是/tmp/mysql.sock。在Windows中,该选项指定本地连接所使用的管道名ã€� 默认值是MySQLã€�

·         --sql-mode=value[,value[,value...]]

å°�MySQL设置ä¸�SQL模式。参è§�5.3.2节,“SQL服务器模式â€�ã€�

·         --temp-pool

该选项使服务器创建的大多数临时文件使用一系列文件名,而不是每个新文件使用唯一的文件名。这样解决了åœ�Linux内核中用 不同的名创建许多新文件的问题。在以前ï¼�Linux似乎“泄漏”内存,因为它被直接分配åˆ�directory entry缓存而不是硬盘缓存ã€�

·         --transaction-isolation=level

设置默认事务隔离级别,可ä»�READ-UNCOMMITTEDã€�READ-COMMITTEEã€�REPEATABLE-READæˆ�SERIALIZABLE。参è§�13.4.6节,“SET TRANSACTION语法â€�ã€�

·         --tmpdir=path, -t path

创建临时文件的目录路径。默è®�/tmp目录在太小不能容纳临时表的分区时该选项很有用。该选项接受round-robin模式的几个路径。在Unix中路径应用冒å��(â€�:â€�) 间隔开,在Windowsã€�NetWareå’�OS/2中用分号(â€�ï¼�â€�) 间隔开。如æž�MySQL服务器为复制从机,你不应è®�--tmpdir指向基于内存的文件系统中的目录或服务器主机重启时会清除的目录。复制从机需要临时文件,机器重启时可以复制临时表或执è¡�LOAD DATA INFILE操作。如果服务器重启时临时文件目录中的文件丢失,复制失败ã€�

·         --user={user_name | user_id}, -u {user_name | user_id}

ç”�user_name或数字用æˆ�ID user_id运行mysqld服务å™�ã€�(â€�用户”指系统登录账户,而不æ˜� 授权表中所列的MySQL用户ï¼�ã€�

ç”�root启动mysqldæ—�强制使用该选项。服务器在启动序列中更改用户ID,让它做为具体用户而不æ˜�root运行。参è§�5.6.1节,“通用安全指南â€�ã€�

要避免用户在my.cnf文件中添åŠ�--user=root选项(使服务器ç”�root运行)时可能出现的安全漏洞ï¼�mysqld只使用指定的ç¬�1ä¸�--user选项,如果有多个--user选项则会出现警告。在命令行选项前处ç��/etc/my.cnfå’�$MYSQL_HOME/my.cnf中的选项,因此建议你åœ�/etc/my.cnf中放一ä¸�--user选项,并指定root之外的其它值。在其它--user选项前先找到/etc/my.cnf中的选项,确保服务器用其它用户运行,如果找到其它--user选项则会出现警告ã€�

·         --version, -V

显示版本信息并退出ã€�

你可以使ç”�--var_name=value形式的选项为服务器系统变量。例如,--key_buffer_size=32M将变é‡�key_buffer_size设为32MBã€�

请注意设置变量时ï¼�MySQL可以自动将它纠正到某个给定范围内,或如果只允许某个值,则将设置值调节到最接近允许的值ã€�

还可以通过--set-variable=var_name=valueæˆ�-O var_name=value语法来设置变量。但是,现在不赞成使用该语法ã€�

5.3.3节,“服务器系统变量â€�完全描述了全部系统变量。调节服务器参数部分包括如何对他们进行优化。参è§�7.5.2节,“调节服务器参数â€�ã€�

你可以用SET语句更改大多数服务器系统变量的值。参è§�13.5.3节,“SET语法â€�ã€�

如果你想ç”�SET 限制启动项可设的最大值,你可以使ç”�--maximum-var_name命令行选项来定义ã€�

5.3.2. SQL服务器模å¼�

MySQL服务器可以以不同çš�SQL模式来操作,并且可以为不同客户端应用不同模式。这样每个应用程序可以根据自己的需求来定制服务器的操作模式ã€�

模式定义MySQL应支持哪äº�SQL语法,以及应执行哪种数据验证检查。这样可以更容易地在不同的环境中使用MySQL,并结合其它数据库服务器使用MySQLã€�

你可以用--sql-mode="modes"选项启动mysqldæ��设置默认SQL模式。如果你想要重设,该值还可以为空(--sql-mode ="")ã€�

你还可以在启动后ç”�SET [SESSION|GLOBAL] sql_mode='modes'语句设置sql_mode变量来更æ”�SQL模式。设ç½� GLOBAL变量时需要拥æœ�SUPER权限,并且会影响从那时起连接的所有客户端的操作。设ç½�SESSION变量只影响当前的客户端。任何客户端可以随时更改自己的会è¯� sql_mode值ã€�

Modesis是用逗号(â€�ï¼�â€�)间隔开的一系列不同的模式。你可以ç”�SELECT @@sql_mode语句查询当前的模式。默认值是ç©�(没有设置任何模式)ã€�

主要重要sql_mode值为ï¼�

·         ANSI

更改语法和行为,使其更符合标å‡�SQLã€�

·         STRICT_TRANS_TABLES

如果不能将给定的值插入到事务表中,则放弃该语句。对于非事务表,如果值出现在单行语句或多行语句的ç¬�1行,则放弃该语句。本节后面给出了更详细的描述ã€�

·         TRADITIONAL

Make MySQL的行为象â€�传统â€�SQL数据库系统。该模式的简单描述是当在列中插入不正确的值时“给å‡�错误而不是警å‘�”ã€�æ³�释:一旦发现错误立即放å¼�INSERT/UPDATE。如果你使用非事务存储引擎,这种方式不是你想要的,因为出现错误前进行的数据更改不会“滚动”,结果是更新“只进行了一部分”ã€�

本手册指â€�严格模式”,表示至少STRICT _TRANS_TABLESæˆ�STRICT _ALL_TABLES被启用的模式ã€�

下面描述了支持的所有模式:

·         ALLOW_INVALID_DATES

在严格模式下不要检查全部日期。只检æŸ�1åˆ�12之间的月份和1åˆ�31之间的日。这åœ�Web应用程序中,当你从三个不同的字段获取年、月、日,并且想要确切保存用户插入的内容(不进行日期验è¯�)时很重要。该模式适用äº�DATEå’�DATETIME列。不适合TIMESTAMP列,TIMESTAMP列需要验证日期ã€�

启用严格模式后,服务器需要合法的月和日,不仅仅是分别åœ�1åˆ�12å’�1åˆ�31范围内。例如,禁用严格模式æ—�'2004-04-31'是合法的,但启用严格模式后是非法的。要想在严格模式允许遮掩固定日期,还应启ç”�ALLOW_INVALID_DATESã€�

·         ANSI_QUOTES

将â€�"’视为识别符引号(â€�`’引号字ç¬�),不要视为字符串的引号字符。在ANSI模式,你可以仍然使用â€�`’来引用识别符。启ç”�ANSI_QUOTES后,你不能用双引号来引用字符串,因为它被解释为识别符ã€�

·         ERROR_FOR_DIVISION_BY_ZERO

在严格模式,åœ�INSERTæˆ�UPDATE过程中,如果被零é™�(æˆ�MOD(Xï¼�0)),则产生错误(否则为警å‘�)。如果未给出该模式,被零除时MySQL返回NULL。如果用åˆ�INSERT IGNOREæˆ�UPDATE IGNORE中,MySQL生成被零除警告,但操作结果为NULLã€�

·         HIGH_NOT_PRECEDENCE

NOT操作符的优先顺序是表达式例如NOT a BETWEEN b AND c被解释为NOT (a BETWEEN b AND c)。在一些旧版本MySQL中, 表达式被解释ä¸�(NOT a) BETWEEN b AND c。启ç”�HIGH_NOT_PRECEDENCESQL模式,可以获得以前的更高优先级的结果ã€�

mysql> SET sql_mode = '';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
        -> 0
mysql> SET sql_mode = 'broken_not';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
        -> 1

·         IGNORE_SPACE

允许函数名和â€�(’之间有空格。强制将所有函数名视为保存的字。结果是,如果你想要访问保存为字的数据库、表或列名,你必须引用它。例如,因为æœ�USER()函数ï¼�mysql数据库中çš�user表名和该表内çš�User列被保存下来,因此你必须引用它们ï¼�

SELECT "User" FROM mysql."user";

·         NO_AUTO_CREATE_USER

防止GRANT自动创建新用户,除非还指定了密码ã€�

·         NO_AUTO_VALUE_ON_ZERO

NO_AUTO_VALUE_ON_ZERO影响AUTO_INCREMENT列的处理。一般情况,你可以向该列插入NULLæˆ�0生成下一个序列号ã€�NO_AUTO_VALUE_ON_ZERO禁用0,因此只æœ�NULL可以生成下一个序列号ã€�

如果å°�0保存到表çš�AUTO_INCREMENT列,该模式会很有用ã€�(不推荐采用该惯例)。例如,如果你用mysqldump转储表并重载ï¼�MySQL遇到0值一般会生成新的序列号,生成的表的内容与转储的表不同。重载转储文件前启用NO_AUTO_VALUE_ON_ZERO可以解决该问题ã€�mysqldump在输出中自动包括启用NO_AUTO_VALUE_ON_ZERO的语句ã€�

·         NO_BACKSLASH_ESCAPES

禁用反斜线字ç¬�(â€�\â€�)做为字符串内的退出字符。启用该模式,反斜线则成为普通字符ã€�

·         NO_DIR_IN_CREATE

创建表时,忽视所æœ�INDEX DIRECTORYå’�DATA DIRECTORY指令。该选项对从复制服务器有用ã€�

·         NO_ENGINE_SUBSTITUTION

如果需要的存储引擎被禁用或未编译,可以防止自动替换存储引擎ã€�

·         NO_FIELD_OPTIONS

不要åœ�SHOW CREATE TABLE的输出中打印MySQL专用列选项。该模式在可移植模式ï¼�portability mode)下用于mysqldumpã€�

·         NO_KEY_OPTIONS

不要åœ�SHOW CREATE TABLE的输出中打印MySQL专用索引选项。该模式在可移植模式ï¼�portability mode)下用于mysqldumpã€�

·         NO_TABLE_OPTIONS

不要åœ�SHOW CREATE TABLE的输出中打印MySQL专用表选项(例å¦�ENGINE)。该模式在可移植模式ï¼�portability mode)下用于mysqldumpã€�

·         NO_UNSIGNED_SUBTRACTION

在减运算中,如果某个操作数没有符号,不要将结果标记为UNSIGNED。请注意这样ä½�UNSIGNED BIGINT不能100%用于上下文中。参è§�12.8节,“Cast函数和操作符â€�ã€�

 

·         NO_ZERO_DATE

在严格模式,不要å°� '0000-00-00'做为合法日期。你仍然可以ç”�IGNORE选项插入零日期。在非严格模式,可以接受该日期,但会生成警告ã€�

·         NO_ZERO_IN_DATE

在严格模式,不接受月或日部分ä¸�0的日期。如果使ç”�IGNORE选项,我们为类似的日期插å…�'0000-00-00'。在非严格模式,可以接受该日期,但会生成警告ã€�

·         ONLY_FULL_GROUP_BY

不要è®�GROUP BY部分中的查询指向未选择的列ã€�

·         PIPES_AS_CONCAT

å°�||视为字符串连接操作符(+ï¼�(å��CONCAT()),而不视为ORã€�

·         REAL_AS_FLOAT

å°�REAL视为FLOAT的同义词,而不æ˜�DOUBLE的同义词ã€�

·         STRICT_TRANS_TABLES

为所有存储引擎启用严格模式。非法数据值被拒绝。后面有详细说明ã€�

·         STRICT_TRANS_TABLES

为事务存储引擎启用严格模式,也可能为非事务存储引擎启用严格模式。后面有详细说明ã€�

严格模式控制MySQL如何处理非法或丢失的输入值。有几种原因可以使一个值为非法。例如,数据类型错误,不适合列,或超出范围。当新插入的行不包含某列的没有显示定ä¹�DEFAULT子句的值,则该值被丢失ã€�

对于事务表,当启ç”�STRICT_ALL_TABLESæˆ�STRICT_TRANS_TABLES模式时,如果语句中有非法或丢失值,则会出现错误。语句被放弃并滚动ã€�

对于非事务表,如果插入或更新的第1行出现坏值,两种模式的行为相同。语句被放弃,表保持不变。如果语句插入或修改多行,并且坏值出现在ç¬�2或后面的行,结果取决于启用了哪个严格选项ï¼�

·         对于STRICT_ALL_TABLESï¼�MySQL返回错误并忽视剩余的行。但是,在这种情况下,前面的行已经被插入或更新。这说明你可以部分更新,这可能不是你想要的。要避免这点,最好使用单行语句,因为这样可以不更改表即可以放弃ã€�

·         对于STRICT_TRANS_TABLESï¼�MySQL将非法值转换为最接近该列的合法值并插入调整后的值。如果值丢失,MySQL在列中插入隐å¼� 默认值。在任何情况下,MySQL都会生成警告而不是给出错误并继续执行语句ã€�13.1.5节,“CREATE TABLE语法â€�描述了隐式默认值ã€�

严格模式不允许非法日期,例如'2004-04-31'。它不允许禁止日期使用“零”部分,例如'2004-04-00'或â€�é›�”日期。要想禁止,应在严格模式基础上,启用NO_ZERO_IN_DATEå’�NO_ZERO_DATE SQL模式ã€�

如果你不使用严格模式(即不启用STRICT_TRANS_TABLESæˆ�STRICT_ALL_TABLES模式),对于非法或丢失的值,MySQL将插入调整后的值并给出警告。在严格模式,你可以通过INSERT IGNOREæˆ�UPDATE IGNORE来实现。参è§�13.5.4.22节,“SHOW WARNINGS语法â€�ã€�

下面的特殊模式快速组合了前面所列的模式ã€�

其中包括大多数最新版æœ�MySQL中的所有模式值。旧版本中,组合模式不包括新版本中没有的不适用的具体模式值ã€�

·         ANSI

等同REAL_AS_FLOATã€�PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACE。参è§�1.8.3节,“在ANSI模式下运行MySQLâ€�ã€�

·         DB2

等同PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACEã€�NO_KEY_OPTIONSã€�NO_TABLE_OPTIONSã€�NO_FIELD_OPTIONSã€�

·         MAXDB

等同PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACEã€�NO_KEY_OPTIONSã€�NO_TABLE_OPTIONSã€�NO_FIELD_OPTIONSã€� NO_AUTO_CREATE_USERã€�

·         MSSQL

等同PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACEã€�NO_KEY_OPTIONSã€�NO_TABLE_OPTIONSã€� NO_FIELD_OPTIONSã€�

·         MYSQL323

等同NO_FIELD_OPTIONSã€�HIGH_NOT_PRECEDENCEã€�

·         MYSQL40

等同NO_FIELD_OPTIONSã€�HIGH_NOT_PRECEDENCEã€�

·         ORACLE

等同PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACEã€�NO_KEY_OPTIONSã€�NO_TABLE_OPTIONSã€�NO_FIELD_OPTIONSã€�NO_AUTO_CREATE_USERã€�

·         POSTGRESQL

等同PIPES_AS_CONCATã€�ANSI_QUOTESã€�IGNORE_SPACEã€�NO_KEY_OPTIONSã€�NO_TABLE_OPTIONSã€�NO_FIELD_OPTIONSã€�

·         TRADITIONAL

等同STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USERã€�

5.3.3. 服务器系统变é‡�

服务器将维护许多表示其配置的系统变量。所有变量均有默认值。可以在命令行中或选项文件设置选项在服务器启动时对它们进行设置。大多数可以在运行时使用SET语句来设置ã€�

mysqld服务å™�维护两种变量。全局变量影响服务器的全局操作。会话变量影响具体客户端连接相关操作ã€�

服务器启动时,将所有全局变量初始化为默认值。可以在选项文件或命令行中指定的选项来更改这些默认值。服务器启动后,通过连接服务器并执行SET GLOBAL var_name语句可以更改动态全局变量。要想更改全局变量,必须具æœ�SUPER权限ã€�

服务器还为每个客户端连接维护会话变量。连接时使用相应全局变量的当前值对客户端会话变量进行初始化。客户可以通过SET SESSION var_name语句来更改动态会话变量。设置会话变量不需要特殊权限,但客户可以只更改自己的会话变量,而不更改其它客户的会话变量ã€�

任何访问全局变量的客户端都可以看见对全局变量的更改。但是,它只影响在更改后连接的从该全局变量初始化相应会话变量的客户端。它不会影响已经连接上的客户端的会话变量(甚至是执è¡�SET GLOBAL语句的客户端)ã€�

当使用启动选项设置变量时,变量值可以使用后缀Kã€�Mæˆ�G分别表示千字节、兆字节æˆ�gigabytes。例如,下面的命令启动服务器时的键值缓冲区大小ä¸�16 megabytesï¼�

mysqld --key_buffer_size=16M

后缀的大小写美关系;16Må’�16m是同样的ã€�

运行时,使用SET语句来设置系统变量。此时,不能使用后缀,但值可以采取下列表达式ï¼�

mysql> SET sort_buffer_size = 10 * 1024 * 1024;

要想显式指定是否设置全局或会话变量,使用GLOBALæˆ�SESSION选项ï¼�

mysql> SET GLOBAL sort_buffer_size = 10 * 1024 * 1024;
mysql> SET SESSION sort_buffer_size = 10 * 1024 * 1024;

两个选项均没有,则语句设置会话变量ã€�

5.3.3.1节,“动态系统变量â€�中列出了可以在运行时设置的变量ã€�

如果你想ç”�SET语句限制系统变量可设的最大值,可以在服务器启动时通过--maximum-var_name形式的选项来指定。例如,要想防止query_cache_size的值运行时超过32MB,使用选项--maximum-query_cache_size=32Mã€�

你可以通过SHOW VARIABLES语句查看系统变量及其值。详细信息参è§�9.4节,“系统变量â€�ã€�

mysql> SHOW VARIABLES;
+---------------------------------+-------------------------------------------+
| Variable_name                   | Value                                     |
+---------------------------------+-------------------------------------------+
| auto_increment_increment        | 1                                         |
| auto_increment_offset           | 1                                         |
| automatic_sp_privileges         | ON                                        |
| back_log                        | 50                                        |
| basedir                         | /home/jon/bin/mysql/                      |
| binlog_cache_size               | 32768                                     |
| bulk_insert_buffer_size         | 8388608                                   |
| character_set_client            | latin1                                    |
| character_set_connection        | latin1                                    |
| character_set_database          | latin1                                    |
| character_set_results           | latin1                                    |
| character_set_server            | latin1                                    |
| character_set_system            | utf8                                      |
| character_sets_dir              | /home/jon/bin/mysql/share/mysql/charsets/ |
| collation_connection            | latin1_swedish_ci                         |
| collation_database              | latin1_swedish_ci                         |
| collation_server                | latin1_swedish_ci                         |
| completion_type                 | 0                                         |
| concurrent_insert               | 1                                         |
| connect_timeout                 | 5                                         |
| datadir                         | /home/jon/bin/mysql/var/                  |
| date_format                     | %Y-%m-%d                                  |
| datetime_format                 | %Y-%m-%d %H:%i:%s                         |
| default_week_format             | 0                                         |
| delay_key_write                 | ON                                        |
| delayed_insert_limit            | 100                                       |
| delayed_insert_timeout          | 300                                       |
| delayed_queue_size              | 1000                                      |
| div_precision_increment         | 4                                         |
| engine_condition_pushdown       | OFF                                       |
| expire_logs_days                | 0                                         |
| flush                           | OFF                                       |
| flush_time                      | 0                                         |
| ft_boolean_syntax               | + -><()~*:""&|                            |
| ft_max_word_len                 | 84                                        |
| ft_min_word_len                 | 4                                         |
| ft_query_expansion_limit        | 20                                        |
| ft_stopword_file                | (built-in)                                |
| group_concat_max_len            | 1024                                      |
| have_archive                    | YES                                       |
| have_bdb                        | NO                                        |
| have_blackhole_engine           | YES                                       |
| have_compress                   | YES                                       |
| have_crypt                      | YES                                       |
| have_csv                        | YES                                       |
| have_example_engine             | NO                                        |
| have_federated_engine           | NO                                        |
| have_geometry                   | YES                                       |
| have_innodb                     | YES                                       |
| have_isam                       | NO                                        |
| have_ndbcluster                 | DISABLED                                  |
| have_openssl                    | NO                                        |
| have_partition_engine           | YES                                       |
| have_query_cache                | YES                                       |
| have_raid                       | NO                                        |
| have_rtree_keys                 | YES                                       |
| have_symlink                    | YES                                       |
| init_connect                    |                                           |
| init_file                       |                                           |
| init_slave                      |                                           |
| innodb_additional_mem_pool_size | 1048576                                   |
| innodb_autoextend_increment     | 8                                         |
| innodb_buffer_pool_awe_mem_mb   | 0                                         |
| innodb_buffer_pool_size         | 8388608                                   |
| innodb_checksums                | ON                                        |
| innodb_commit_concurrency       | 0                                         |
| innodb_concurrency_tickets      | 500                                       |
| innodb_data_file_path           | ibdata1:10M:autoextend                    |
| innodb_data_home_dir            |                                           |
| innodb_doublewrite              | ON                                        |
| innodb_fast_shutdown            | 1                                         |
| innodb_file_io_threads          | 4                                         |
| innodb_file_per_table           | OFF                                       |
| innodb_flush_log_at_trx_commit  | 1                                         |
| innodb_flush_method             |                                           |
| innodb_force_recovery           | 0                                         |
| innodb_lock_wait_timeout        | 50                                        |
| innodb_locks_unsafe_for_binlog  | OFF                                       |
| innodb_log_arch_dir             |                                           |
| innodb_log_archive              | OFF                                       |
| innodb_log_buffer_size          | 1048576                                   |
| innodb_log_file_size            | 5242880                                   |
| innodb_log_files_in_group       | 2                                         |
| innodb_log_group_home_dir       | ./                                        |
| innodb_max_dirty_pages_pct      | 90                                        |
| innodb_max_purge_lag            | 0                                         |
| innodb_mirrored_log_groups      | 1                                         |
| innodb_open_files               | 300                                       |
| innodb_support_xa               | ON                                        |
| innodb_sync_spin_loops          | 20                                        |
| innodb_table_locks              | ON                                        |
| innodb_thread_concurrency       | 20                                        |
| innodb_thread_sleep_delay       | 10000                                     |
| interactive_timeout             | 28800                                     |
| join_buffer_size                | 131072                                    |
| key_buffer_size                 | 8388600                                   |
| key_cache_age_threshold         | 300                                       |
| key_cache_block_size            | 1024                                      |
| key_cache_division_limit        | 100                                       |
| language                        | /home/jon/bin/mysql/share/mysql/english/  |
| large_files_support             | ON                                        |
| large_page_size                 | 0                                         |
| large_pages                     | OFF                                       |
| license                         | GPL                                       |
| local_infile                    | ON                                        |
| locked_in_memory                | OFF                                       |
| log                             | ON                                        |
| log_bin                         | ON                                        |
| log_bin_trust_routine_creators  | OFF                                       |
| log_error                       | /home/jon/bin/mysql/var/master1.err       |
| log_slave_updates               | OFF                                       |
| log_slow_queries                | OFF                                       |
| log_warnings                    | 1                                         |
| long_query_time                 | 10                                        |
| low_priority_updates            | OFF                                       |
| lower_case_file_system          | OFF                                       |
| lower_case_table_names          | 0                                         |
| max_allowed_packet              | 1048576                                   |
| max_binlog_cache_size           | 4294967295                                |
| max_binlog_size                 | 1073741824                                |
| max_connect_errors              | 10                                        |
| max_connections                 | 100                                       |
| max_delayed_threads             | 20                                        |
| max_error_count                 | 64                                        |
| max_heap_table_size             | 16777216                                  |
| max_insert_delayed_threads      | 20                                        |
| max_join_size                   | 4294967295                                |
| max_length_for_sort_data        | 1024                                      |
| max_relay_log_size              | 0                                         |
| max_seeks_for_key               | 4294967295                                |
| max_sort_length                 | 1024                                      |
| max_tmp_tables                  | 32                                        |
| max_user_connections            | 0                                         |
| max_write_lock_count            | 4294967295                                |
| multi_range_count               | 256                                       |
| myisam_data_pointer_size        | 6                                         |
| myisam_max_sort_file_size       | 2147483647                                |
| myisam_recover_options          | OFF                                       |
| myisam_repair_threads           | 1                                         |
| myisam_sort_buffer_size         | 8388608                                   |
| ndb_autoincrement_prefetch_sz   | 32                                        |
| ndb_cache_check_time            | 0                                         |
| ndb_force_send                  | ON                                        |
| ndb_index_stat_cache_entries    | 32                                        |
| ndb_index_stat_enable           | ON                                        |
| ndb_index_stat_update_freq      | 20                                        |
| ndb_use_exact_count             | ON                                        |
| ndb_use_transactions            | ON                                        |
| net_buffer_length               | 16384                                     |
| net_read_timeout                | 30                                        |
| net_retry_count                 | 10                                        |
| net_write_timeout               | 60                                        |
| new                             | OFF                                       |
| old_alter_table                 | OFF                                       |
| old_passwords                   | OFF                                       |
| open_files_limit                | 1024                                      |
| optimizer_prune_level           | 1                                         |
| optimizer_search_depth          | 62                                        |
| pid_file                        | /home/jon/bin/mysql/var/hostname.pid1     |
| port                            | 3306                                      |
| preload_buffer_size             | 32768                                     |
| protocol_version                | 10                                        |
| query_alloc_block_size          | 8192                                      |
| query_cache_limit               | 1048576                                   |
| query_cache_min_res_unit        | 4096                                      |
| query_cache_size                | 0                                         |
| query_cache_type                | ON                                        |
| query_cache_wlock_invalidate    | OFF                                       |
| query_prealloc_size             | 8192                                      |
| range_alloc_block_size          | 2048                                      |
| read_buffer_size                | 131072                                    |
| read_only                       | OFF                                       |
| read_rnd_buffer_size            | 262144                                    |
| relay_log_purge                 | ON                                        |
| relay_log_space_limit           | 0                                         |
| rpl_recovery_rank               | 0                                         |
| secure_auth                     | OFF                                       |
| server_id                       | 1                                         |
| skip_external_locking           | ON                                        |
| skip_networking                 | OFF                                       |
| skip_show_database              | OFF                                       |
| slave_compressed_protocol       | OFF                                       |
| slave_load_tmpdir               | /tmp/                                     |
| slave_net_timeout               | 3600                                      |
| slave_skip_errors               | OFF                                       |
| slave_transaction_retries       | 10                                        |
| slow_launch_time                | 2                                         |
| socket                          | /tmp/mysql.sock                           |
| sort_buffer_size                | 2097144                                   |
| sql_mode                        |                                           |
| sql_notes                       | ON                                        |
| sql_warnings                    | ON                                        |
| storage_engine                  | MyISAM                                    |
| sync_binlog                     | 0                                         |
| sync_frm                        | ON                                        |
| sync_replication                | 0                                         |
| sync_replication_slave_id       | 0                                         |
| sync_replication_timeout        | 10                                        |
| system_time_zone                | EST                                       |
| table_cache                     | 64                                        |
| table_lock_wait_timeout         | 50                                        |
| table_type                      | MyISAM                                    |
| thread_cache_size               | 0                                         |
| thread_stack                    | 196608                                    |
| time_format                     | %H:%i:%s                                  |
| time_zone                       | SYSTEM                                    |
| timed_mutexes                   | OFF                                       |
| tmp_table_size                  | 33554432                                  |
| tmpdir                          |                                           |
| transaction_alloc_block_size    | 8192                                      |
| transaction_prealloc_size       | 4096                                      |
| tx_isolation                    | REPEATABLE-READ                           |
| updatable_views_with_limit      | YES                                       |
| version                         | 5.1.2-alpha-log                           |
| version_comment                 | Source distribution                       |
| version_compile_machine         | i686                                      |
| version_compile_os              | suse-linux                                |
| wait_timeout                    | 28800                                     |
+---------------------------------+-------------------------------------------+
218 rows in set (0.03 sec)

此处描述了大多数系统变量。没有版本的变量在所æœ�MySQL 5.1 发布中适用。关于其使用历史信息,请参见MySQL 5.0参考指å��å’�MySQL 4.1参考指å��ã€�InnoDB系统变量列于 15.2.4节,“InnoDB启动选项â€�ã€�

若没有另行规定,缓冲区大小、长度和堆栈大小的单位均为字节ã€�

关于这些变量的调节信息参è§�7.5.2节,“调节服务器参数â€�ã€�

·         auto_increment_increment

auto_increment_incrementå’�auto_increment_offset用于主服务器-主服务器(master-to-master)复制,并可以用来控åˆ�AUTO_INCREMENT列的操作。两个变量均可以设置为全局或局部变量,并且假定每个值都可以ä¸�1åˆ�65,535之间的整数值。将其中一个变量设置为0会使该变量为1。如果试图将这些变量设置为大äº�65,535或小äº�0的值,则会将该值设置为65,535。如果向å°�auto_increment_incrementæˆ�auto_increment_offset设置为非整数值,则会给出错误,并且变量的实际值在这种情况下保持不变ã€�

这两个变量影å“�AUTO_INCREMENT列的方式ï¼�

o        auto_increment_increment控制列中的值的增量值。例å¦�:

o                       mysql> SHOW VARIABLES LIKE 'auto_inc%';
o                       +--------------------------+-------+
o                       | Variable_name            | Value |
o                       +--------------------------+-------+
o                       | auto_increment_increment | 1     |
o                       | auto_increment_offset    | 1     |
o                       +--------------------------+-------+
o                       2 rows in set (0.00 sec)
o                      
o                       mysql> CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
o                       Query OK, 0 rows affected (0.04 sec)
o                      
o                       mysql> SET @auto_increment_increment=10;
o                       Query OK, 0 rows affected (0.00 sec)
o                      
o                       mysql> SHOW VARIABLES LIKE 'auto_inc%';
o                       +--------------------------+-------+
o                       | Variable_name            | Value |
o                       +--------------------------+-------+
o                       | auto_increment_increment | 10    |
o                       | auto_increment_offset    | 1     |
o                       +--------------------------+-------+
o                       2 rows in set (0.01 sec)
o                      
o                       mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
o                       Query OK, 4 rows affected (0.00 sec)
o                       Records: 4  Duplicates: 0  Warnings: 0
o                      
o                       mysql> SELECT col FROM autoinc1;
o                       +-----+
o                       | col |
o                       +-----+
o                       |   1 |
o                       |  11 |
o                       |  21 |
o                       |  31 |
o                       +-----+
o                       4 rows in set (0.00 sec)

(注明如何使用SHOW VARIABLES来获取这些变量的当前值)ã€�

o        auto_increment_offset确定AUTO_INCREMENT列值的起点。假定在与前面的例子的相同的会话中执行下面的命令ï¼�

o                       mysql> SET @auto_increment_offset=5;
o                       Query OK, 0 rows affected (0.00 sec)
o                      
o                       mysql> SHOW VARIABLES LIKE 'auto_inc%';
o                       +--------------------------+-------+
o                       | Variable_name            | Value |
o                       +--------------------------+-------+
o                       | auto_increment_increment | 10    |
o                       | auto_increment_offset    | 5     |
o                       +--------------------------+-------+
o                       2 rows in set (0.00 sec)
o                      
o                       mysql> CREATE TABLE autoinc2 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
o                       Query OK, 0 rows affected (0.06 sec)
o                      
o                       mysql> INSERT INTO autoinc2 VALUES (NULL), (NULL), (NULL), (NULL);
o                       Query OK, 4 rows affected (0.00 sec)
o                       Records: 4  Duplicates: 0  Warnings: 0
o                      
o                       mysql> SELECT col FROM autoinc2;
o                       +-----+
o                       | col |
o                       +-----+
o                       |   5 |
o                       |  15 |
o                       |  25 |
o                       |  35 |
o                       +-----+
o                       4 rows in set (0.02 sec)
o                      

如果auto_increment_offset的值大äº�auto_increment_increment的值,åˆ�auto_increment_offset的值被忽略ã€�

如果其中一个或两个变量被更改了,然后更改插入到包含AUTO_INCREMENT列的表中的新行,结果可能看上去有问题,由于计ç®�AUTO_INCREMENT系列值时没有考虑列内已经存在的值,并且插入的下一个值是列内最小的值,大于AUTO_INCREMENT列内已有的最大值。换句话说,数值的计算方法为:

auto_increment_offset+ N * auto_increment_increment

其中N为系列内的正整数å€�[1,2,3,...]。例如:

mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 10    |
| auto_increment_offset    | 5     |
+--------------------------+-------+
2 rows in set (0.00 sec)
 
mysql> SELECT col FROM autoinc1;
+-----+
| col |
+-----+
|   1 |
|  11 |
|  21 |
|  31 |
+-----+
4 rows in set (0.00 sec)
 
mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> SELECT col FROM autoinc1;
+-----+
| col |
+-----+
|   1 |
|  11 |
|  21 |
|  31 |
|  35 |
|  45 |
|  55 |
|  65 |
+-----+
8 rows in set (0.00 sec)

auto_increment_incrementå’�auto_increment_offset所示的值可以生成系åˆ�5 + N * 10,即,[5,15,25,35,45,...]。在INSERTå‰�col 列内最大的值为31,AUTO_INCREMENT数列的下一个值为35,因此col中插入的值从该点开始,结果å¦�SELECT查询所示ã€�

一定要记住不可能将这两个变量的结果限制到一个表中,因此不会替代其它数据库管理系统提供的序列;这些变量控åˆ�MySQL服务器上allè¡�AUTO_INCREMENT列的所有行为。如果某个变量设为全局变量,则只有通过局部设置将全局值更改和覆盖后或mysqld重启后其作用方可改变;如果局部设置,则新值影响所有表çš�AUTO_INCREMENT列,在这个会话期间当前用户在这些表中插入了新行,除非在会话期间更改了这些值ã€�

auto_increment_incrementçš� 默认值为1。参è§�6.12节,“多服务器复制中的Auto-Incrementâ€�ã€�

·         auto_increment_offset

该变量的默认值为1。详è§�auto_increment_increment的描述ã€�

·         back_log

MySQL有的主要连接请求的数量。当ä¸�MySQL线程在短时间内得到许多连接请求时发挥作用。主线程需要花一些时é—�(尽管很少)来检查连接并启动一个新线程ã€�back_log值说æ˜�MySQL临时停止响应新请求前在短时间内可以堆起多少请求。如果你需要在短时间内允许大量连接,可以增加该数值ã€�

换句话说,该值为“进â€�TCP/IP连接帧听队列的大小。操作系统有该队列自己的限制值。本手册ä¸�Unix listen()系统调用页应有更详细的信息。该变量最大值请查阅OS文档。企图将back_log设置为高于你的操作系统限值是徒劳无益的ã€�

·         basedir

MySQL安装基准目录。可以用--basedir选项设置该变量ã€�

·         bdb_cache_size

ä¸�BDB表缓存索引和行分配的缓冲区的大小。如果你不使ç”�BDB表,你应ç”�--skip-bdb启动mysqld以便不浪费该缓存ã€�

·         bdb_home

BDB表基准目录。应ä¸�datadir变量的值相同ã€�

·         bdb_log_buffer_size

ä¸�BDB表缓存索引和行分配的缓冲区的大小。如果你不使ç”�BDB表,你应将该值设置为0或用--skip-bdb启动mysqld以便不浪费该缓存ã€�

·         bdb_logdir

BDB存储引擎写它日志文件的目录。可以用--bdb-logdir选项设置该变量ã€�

·         bdb_max_lock

åœ�BDB表下可以激活的最大锁æ•�(默认ä¸�10,000)。如果当你执行长事务或当mysqld必须检查许多行来计算查询时出现下面的错误,你应增加该值:

bdb: Lock table is out of available locks
Got error 12 from ...

·         bdb_shared_data

如果你正使用--bdb-shared-data应为ONã€�

·         bdb_tmpdir

--bdb-tmpdir选项的值ã€�

 

·         binlog_cache_size

在事务过程中容纳二进制日å¿�SQL语句的缓存大小。二进制日志缓存是服务器支持事务存储引擎并且服务器启用了二进制日å¿�(--log-bin选项)的前提下为每个客户端分配的内存。如果你经常使用大的,多语句事务,你可以增加该值以获得更有的性能ã€�Binlog_cache_useå’�Binlog_cache_disk_use状态变量可以用来调整该变量的大小。参è§�5.11.3节,“二进制日志â€�ã€�

·         bulk_insert_buffer_size

MyISAM 使用专用树状缓存来使INSERT ... SELECTã€�INSERT ... VALUES (...)ã€�(...)ã€� ...å’�LOAD DATA INFILE的大块插入更快。该变量用每线程的字节数限制缓存树的大小。将它设置为0禁用优化ã€�æ³�释:只有向非空表添加数据时才使用该缓存ã€� 默认值是8MBã€�

·         character_set_client

来自客户端的语句的字符集ã€�

·         character_set_connection

用于没有字符集导入符的文字和数字-字符串转换ã€�

·         character_set_database

默认数据库使用的字符集。当默认数据库更改时,服务器则设置该变量。如果没有默认数据库,变量的值同character_set_serverã€�

·         character_set_results

用于向客户端返回查询结果的字符集ã€�

·         character_set_ server

服务器的默认字符集ã€�

·         character_set_system

服务器用来保存识别符的字符集。该值一定是utf8ã€�

·         character_sets_dir

字符集安装目录ã€�

·         collation_connection

连接字符集的校对规则ã€�

·         collation_database

默认数据库使用的校对规则。当默认数据库改变时服务器则设置该变量。如果没有默认数据库,变量的值同collation_serverã€�

·         collation_server

服务器的默认校对规则ã€�

·         completion_type

事务结束类型ï¼�

o        如果该值为0(默认)ï¼�COMMITå’�ROLLBACK不受影响ã€�

o        如果该值为1ï¼�COMMITå’�ROLLBACK分别等同äº�COMMIT AND CHAINå’�ROLLBACK AND CHAINã€�(新事务用刚刚结束的事务相同的间隔等级立即启动ï¼�ã€�

o        如果该值为2ï¼�COMMITå’�ROLLBACK分别等同äº�COMMå®�RELEASEå’�ROLLBACK RELEASEã€�(事务终止后,服务器断开ï¼�ã€�

·         concurrent_insert

如果ä¸�ON(默认å€�)ï¼�MySQL允许INSERTå’�SELECT语句在中间没有空数据块的MyISAM表中并行运行。你可以ç”�--safeæˆ�--skip-new启动mysqld关闭该选项ã€�

该变量为整数,有3个值:

�

描述

0

å…�

1

(默认)在没有空数据块的MyISAM表中启用并行插入

2

为所æœ�MyISAM表启用并行插入。如果表有空记录或正被另一线程使用,新行将插入到表的最后。如果表未使用,MySQL将进行普通读锁定并将新行插入空记录ã€�

·         connect_timeout

mysqld服务å™�ç”�Bad handshake响应前等待连接包的秒数ã€�

·         datadir

MySQL数据目录。可以用--datadir选项设置该变量ã€�

·         date_format

该变量未使用ã€�

·         datetime_format

该变量未使用ã€�

·         default_week_format

WEEK() 函数使用的默认模式ã€�

·         delay_key_write

该选项只适用MyISAM表。它具有下述值可以影å“�CREATE TABLE语句使用çš�DELAY_KEY_WRITE表选项的处理ã€�

选项

描述

OFF

DELAY_KEY_WRITE被忽略ã€�

ON

MySQLåœ�CREATE TABLE中用DELAY_KEY_WRITE选项。这æ˜� 默认值ã€�

ALL

用启ç”�DELAY_KEY_WRITE选项创建表的相同方法对所有新打开表的进行处理ã€�

如果启用äº�DELAY_KEY_WRITE,说明使用该项的表的键缓冲区在每次更新索引时不被清空,只有关闭表时才清空。遮掩盖可以大大加快键的写操作,但如果你使用该特性,你应ç”�--myisam-recover选项启动服务器,为所æœ�MyISAM表添加自动检æŸ�(例如ï¼�--myisam-recover=BACKUP,FORCE)。参è§�5.3.1节,â€�mysqld命令行选项â€�å’�15.1.1节,“MyISAM启动选项â€�ã€�

请注æ„�--external-locking不为使用延迟键写入的表提供索引破坏保护ã€�

·         delayed_insert_limit

插入delayed_insert_limit 延迟行后ï¼�INSERT DELAYED 处理器线程检查是否有挂起çš�SELECT语句。如果有,在继续插入延迟的行之前,允许它们先执行ã€�

·         delayed_insert_timeout

INSERT DELAYED处理器线程终止前应等å¾�INSERT语句的时间ã€�

·         delayed_queue_size

这是各个表中处理INSERT DELAYED语句时队列中行的数量限制。如果队列满了,执行INSERT DELAYED语句的客户端应等待直到队列内再有空间ã€�

·         div_precision_increment

该变量说明用/操作符执行除操作的结果可增加的精确度的位数ã€� 默认值是4。最小和最大值分别为0å’�30。下面的示例说明了增åŠ� 默认值的结果ã€�

mysql> SELECT 1/7;
+--------+
| 1/7    |
+--------+
| 0.1429 |
+--------+
mysql> SET div_precision_increment = 12;
mysql> SELECT 1/7;
+----------------+
| 1/7            |
+----------------+
| 0.142857142857 |
+----------------+

·         engine_condition_pushdown

该变量适用äº�NDB。默认值为0(OFF):如果你执行类似查询SELECT * FROM t WHERE mycol = 42,其ä¸�mycol为没有索引的列,当满了的表扫描每ä¸�NDB节点时,执行该查诀€‚每个节点使ç”�WHERE条件将每一行发送给MySQL服务器。如æž�engine_condition_pushdown被设置为1(ON),该条件â€�pushed down”给存储引擎并发送给NDB节点。每个节点都执行扫描,并只向MySQL服务器发送回匹配条件的行ã€�

·         expire_logs_days

二进制日志自动删除的天数。默认值为0,表示“没æœ�自动删除”。启动时和二进制日志循环时可能删除ã€�

·         flush

如果ç”�--flush选项启动mysqld该值为ONã€�

·         flush_time

如果设为非零值,每隔flush_time秒则关闭所有表以释放硬盘资源并同步未清空的数据。我们建议只åœ�Windows 9xæˆ�Me,或有最小资源的系统中使用该选项ã€�

·         ft_boolean_syntax

使用IN BOOLEAN MODE执行的布尔全文搜索支持的操作符系列。参è§�12.7.1节,“布尔全文搜索â€�ã€�

默认变量值为 '+ -><()~*:""&|'。更改这些值的规则是:

o        操作符函数由其在字符串内的位置决定ã€�

o        替换值必须是14个字符ã€�

o        每个字符必须ä¸�ASCII码非文字数字字符ã€�

o        ç¬�1个或ç¬�2个字符必须为空格ã€�

o        除非语句在第11个字符和ç¬�12个字符处引用了操作符,否则不允许复制。这两个字符可以不相同,但这是唯一可能的两个ã€�

o        位置10ã€�13å’�14(默认设置为â€�:’、â€�&’和â€�|â€�)保留用于将来扩展ã€�

·         ft_max_word_len

FULLTEXT索引中所包含的字的最大长度ã€�

æ³�释:更改该变量后必须重建FULLTEXT索引。应使用REPAIR TABLE tbl_name QUICKã€�

·         ft_min_word_len

FULLTEXT索引中所包含的字的最小长度ã€�

æ³�释:更改该变量后必须重建FULLTEXT索引。应使用REPAIR TABLE tbl_name QUICKã€�

·         ft_query_expansion_limit

使用WITH QUERY EXPANSION进行全文搜索的最大匹配数ã€�

·         ft_stopword_file

用于读取全文搜索的停止字清单的文件。该文件中的所有字都会用到;注释不重要。默认情况下,使用内嵌式停止字清å��(å¦�myisam/ft_static.c文件中所定义)。将该变量设置为空字符串('')则禁用停止字过滤ã€�

æ³�释:更改该变量或停止字文件的内容后必须重å»�FULLTEXT索引。应使用REPAIR TABLE tbl_name QUICKã€�

·         group_concat_max_len

允许çš�GROUP_CONCAT()函数结果的最大长度ã€�

·         have_archive

如果mysqld支持ARCHIVE表则ä¸�YES,否则为NOã€�

·         have_bdb

如果mysqld支持BDB表则ä¸�YES。如果使ç”�--skip-bdb则为DISABLEDã€�

·         have_blackhole_engine

如果mysqld支持BLACKHOLE表则ä¸�YES,否则为NOã€�

·         have_compress

是否zlib压缩库适合该服务器。如果不适合,不能使ç”�COMPRESS()å’�UNCOMPRESS()函数ã€�

·         have_crypt

是否crypt()系统调用适合该服务器。如果不适合,不能使ç”�CRYPT()函数ã€�

·         have_csv

如果mysqld支持ARCHIVE表则ä¸�YES,否则为NOã€�

·         have_example_engine

如果mysqld支持EXAMPLE表则ä¸�YES,否则为NOã€�

have_federated_engine

如果mysqld支持FEDERATED表则ä¸�YES,否则为NOã€�

·         have_geometry

是否服务器支持空间数据类型ã€�

·         have_innodb

如果mysqld支持InnoDB表则ä¸�YES。如果使ç”�--skip-innodb则为DISABLEDã€�

·         have_isam

åœ�MySQL 5.1ä¸�,只是为了向后兼容显示该值,并且总是NO,因为不再支æŒ�ISAM表ã€�

·         have_ndbcluster

如果mysqld支持NDB CLUSTER表则ä¸�YES。如果使用了--skip-ndbcluster则为DISABLEDã€�

·         have_partition_engine

如果mysqld支持分区则为YES。在MySQL 5.1.1中加入ã€�

·         have_openssl

如果mysqld支持客户ç«�/服务器协议的SSL(加密)则为YESã€�

·         have_query_cache

如果mysqld支持查询缓存则为YESã€�

·         have_raid

如果mysqld支持RAID选项则为YESã€�

·         have_rtree_keys

RTREE索引是否可用ã€�(用于MyISAM表的空间索引ï¼�ã€�

·         have_symlink

是否启用符号链接支持。在Unix中需要用于支æŒ�DATA DIRECTORYå’�INDEX DIRECTORY表选项ã€�

·         init_connect

服务器为每个连接的客户端执行的字符串。字符串由一个或多个SQL语句组成。要想指定多个语句,用分号间隔开。例如,每个客户端开始时默认启用autocommit模式。没有全局服务器变量可以规å®�autocommit默认情况下应禁用,但可以ç”�init_connect来获得相同的效果ï¼�

SET GLOBAL init_connect='SET AUTOCOMMIT=0';

还可以在命令行或选项文件中设置该变量。要想使用选项文件设置变量,应包括下述行:

[mysqld]
init_connect='SET AUTOCOMMIT=0'

请注æ„�init_connect的内容并不为拥有SUPER权限的用户执行;实际是内容设置错è¯�(包含错误查询,例如语法错è¯�),这样使所有连接失败。不ä¸�SUPER用户执行,使SUPER用户可以打开连接并固å®�init_connectã€�

·         init_file

启动服务器时ç”�--init-file选项指定的文件名。文件中包含服务器启动时要执行的SQL语句。每个语句必须在同一行中并且不能包括注释ã€�

·         init_slave

该变量类ä¼�init_connect,但是每æ¬�SQL线程启动时从服务器应执行该字符串。该字符串的格式ä¸�init_connect变量相同ã€�

·         innodb_xxx

InnoDB系统变量列入15.2.4节,“InnoDB启动选项â€�ã€�

·         interactive_timeout

服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为åœ�mysql_real_connect()中使ç”�CLIENT_INTERACTIVE选项的客户端。又è§�wait_timeoutã€�

·         join_buffer_size

用于完全联接的缓冲区的大å°�(当不使用索引的时候使用联接操ä½�)。一般情况获得快速联接的最好方法是添加索引。当增加索引时不可能通过增加join_buffer_size值来获得快速完全联接。将为两个表之间的每个完全联接分配联接缓冲区。对于多个表之间不使用索引的复杂联接,需要多联接缓冲区ã€�

·         key_buffer_size

MyISAM表的索引块分配了缓冲区,由所有线程共享ã€�key_buffer_size是索引块缓冲区的大小。键值缓冲区即为键值缓存ã€�

key_buffer_size的最大允许设定值为4GB。有效最大值可以更小,取决于可用物ç��RAM和操作系统或硬件平台强加的每个进程的RAM限制ã€�

增加该值,达到你可以提供的更好的索引处ç��(所有读和多个写操作)。通常为主要运è¡�MySQL的机器内存的25%。但是,如果你将该值设得过å¤�(例如,大于总内存的50%),系统将转换为页并变得极慀€�MySQL依赖操作系统来执行数据读取时的文件系统缓存,因此你必须为文件系统缓存留一些空间ã€�

同时写多行时要想速度更快,应使用LOCK TABLES。参è§�13.4.5节,“LOCK TABLES和UNLOCK TABLES语法â€�ã€�

你可以通过执行SHOW STATUS语句并检æŸ�Key_read_requestsã€�Key_readsã€�Key_write_requestså’�Key_writes状态变量来检查键值缓冲区的性能。参è§�13.5.4节,“SHOW语法â€�ã€�

Key_reads/Key_read_requests比例一般应小于0.01。如果你使用更新和删除,Key_writes/Key_write_requests比例通常接近1,但如果你更新时会同时影响到多行或如果你正使ç”�DELAY_KEY_WRITE表选项,可能小得多ã€�

ç”�key_buffer_size结合Key_blocks_unused状态变量和缓冲区块大小,可以确定使用的键值缓冲区的比例。从key_cache_block_size服务器变量可以获得缓冲区块大小。使用的缓冲区的比例为:

1 - ((Key_blocks_unused * key_cache_block_size) / key_buffer_size)

该值为约数,因为键值缓冲区的部分空间被分配用作内部管理结构ã€�

可以创建多个MyISAM键值缓存ã€�4GB限制可以适合每个缓存,而不是一个组。参è§�7.4.6节,“MyISAM键高速缓冲â€�ã€�

·         key_cache_age_threshold

该值控制将缓冲区从键值缓存热子链(sub-chain)降级到温子链(sub-chain)。如果值更低,则降级更快。最小值为100ã€� 默认值是300。参è§�7.4.6节,“MyISAM键高速缓冲â€�ã€�

·         key_cache_block_size

键值缓存内块的字节大小。默认值是1024。参è§�7.4.6节,“MyISAM键高速缓冲â€�ã€�

·         key_cache_division_limit

键值缓存缓冲区链热子链和温子链的划分点。该值为缓冲区链用于温子链的百分比。允许的值的范围ä¸�1åˆ�100ã€� 默认值是100。参è§�7.4.6节,“MyISAM键高速缓冲â€�ã€�

·         language

错误消息所用语言ã€�

·          large_file_support

mysqld编译时是否使用了大文件支持选项ã€�

·         large_pages

说明是否启用了大页面支持ã€�

·         license

服务器的许可类型ã€�

·         local_infile

是否LOCAL支持LOAD DATA INFILE语句ã€�

·         locked_in_memory

是否ç”�â€�memlockå°�mysqld锁在内存中ã€�

·         log

是否启用将所有查询记录到常规查询日志中。参è§�5.11.2节,“通用查询日志â€�ã€�

·         log_bin

是否启用二进制日志。参è§�5.11.3节,“二进制日志â€�ã€�

·         log_bin_trust_routine_creators

若启用了二进制记录,则该变量适用。它控制是否可以信任保存的程序的作者不会创建向二进制日志写入不安全事件的程序。如果设置为0(默认情况),不允许用户创建或修改保存的程序,除非他们不仅拥æœ�CREATE ROUTINEæˆ�ALTER ROUTINE权限还拥æœ�SUPER权限ã€�

设置ä¸�0还强制限制,程序必须ç”�DETERMINISTIC 特征或用READS SQL DATAæˆ�NO SQL特征声明。如果变量设置为1,MySQL不对保存程序的创建强加限制ã€�

参见20.4节,“存储子程序和触发程序的二进制日志功能â€�ã€�

·         log_error

错误日志的位置ã€�

·         log_slave_updates

是否从服务器从主服务器收到的更新应记入从服务器自己的二进制日志。要想生效,必须启用从服务器的二进制记录。参è§�6.8节,“复制启动选项â€�ã€�

·         log_slow_queries

是否记录慢查诀€‚用long_query_time变量的值来确定“慢查询”。参è§�5.11.4节,“慢速查询日志â€�ã€�

·         log_warnings

是否产生其它警告消息。默认情况下启用。放弃的连接不记入错误日志,除非值大äº�1ã€�

·         long_query_time

如果查询时间超过该值,则增åŠ�Slow_queries状态变量。如果你正使ç”�--log-slow-queries选项,则查询记入慢查询日志文件。用实际时间测量该值,而不æ˜�CPU时间,因此低于轻负载系统阈值的查询可能超过重负载系统的阈值。参è§�5.11.4节,“慢速查询日志â€�ã€�

·         low_priority_updates

如果设置ä¸�1,所æœ�INSERTã€�UPDATEã€�DELETEå’�LOCK TABLE WRITE语句将等待直到受影响的表没有挂起çš�SELECTæˆ�LOCK TABLE READ。该变量以前叫做sql_low_priority_updatesã€�

·         lower_case_file_system

该变量说明是否数据目录所在的文件系统对文件名的大小写敏感ã€�ON说明对文件名的大小写不敏感,OFF表示敏感ã€�

·           lower_case_table_names

如果设置ä¸�1,表名用小写保存到硬盘上,并且表名比较时不对大小写敏感。如果设置为2,按照指定的保存表名,但按照小写来比较。该选项还适合数据库名和表的别名。参è§�9.2.2节,“识别符大小写敏感性â€�ã€�

如果你正使用InnoDB表,你应在所有平台上将该变量设置ä¸�1,强制将名字转换为小写ã€�

如果运行MySQL的系统对文件名的大小写不敏感(例如Windowsæˆ�Mac OS X),你不应将该变量设置ä¸�0。如果启动时没有设置该变量,并且数据目录所在文件系统对文件名的大小写不敏感ï¼�MySQL自动å°�lower_case_table_names设置ä¸�2ã€�

·         max_allowed_packet

包或任何生成çš�/中间字符串的最大大小ã€�

包消息缓冲区初始化为net_buffer_length字节,但需要时可以增长åˆ�max_allowed_packet字节。该值默认很小,以捕获大çš�(可能是错误的)数据包ã€�

如果你使用大çš�BLOB 列或长字符串,你必须增加该值。应同你想要使用的最大的BLOB一样大ã€�max_allowed_packet的协议限制为1GBã€�

·         max_binlog_cache_size

如果多语句事务需要更大的内存,你会得到错è¯�Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storageã€�

·         max_binlog_size

如果二进制日志写入的内容超出给定值,日志就会发生滚动。你不能将该变量设置为大äº�1GB或小äº�4096字节ã€� 默认值是1GBã€�

请注意如果你正使用事务:事务以一个块写入二进制日志,因此不不能被几个二进制日志拆分。因此,如果你有大的事务,二进制日志可能会大äº�max_binlog_sizeã€�

如果max_relay_log_sizeä¸�0, max_binlog_size的值也适用于中继日å¿�ã€�

·         max_connect_errors

如果中断的与主机的连接超过该数目,该主机则阻塞后面的连接。你可以ç”� FLUSH HOSTS语句解锁锁定的主机ã€�

·         max_connections

允许的并行客户端连接数目。增大该值则增加mysqld 需要的文件描述符的数量。关于文件描述符限制的注释参è§�7.4.9节,“MySQL如何打开和关闭表â€�。还可参è§�A.2.6节,“连接数过多â€�ã€�

·         max_delayed_threads

不要启动大于该数目的线程来处ç��INSERT DELAYED语句。如果所æœ�INSERT DELAYED线程已经在使用,你想在新表中插入数据,行 插入时好像未指定DELAYED属性。如果你将该值设置为0,MySQL不会创建线程来处ç��DELAYED行;其结果是完全禁用äº�DELAYEDã€�

·         max_error_count

保存ç”�SHOW ERRORSæˆ�SHOW WARNINGS显示的错误、警告和注解的最大数目ã€�

·         max_heap_table_size

该变量设ç½�MEMORY (HEAP)表可以增长到的最大空间大小。该变量用来计算MEMORY表的MAX_ROWS值。在已有çš�MEMORY表上设置该变量没有效果,除非ç”�CREATE TABLEæˆ�TRUNCATE TABLE等语句重新创建表ã€�

·         max_insert_delayed_threads

该变量为max_delayed_threads的同义词ã€�

·         max_join_size

不允许可能需要检查多äº�max_join_sizeè¡�(为单个表语句)或行组合(为多个表语句)或可能执行大äº�max_join_size次硬盘查询的SELECT语句。通过设置该值,你可以捕获键使用不正确并可能花很长时间的SELECT语句。如果用户想要执行没æœ�WHERE子句的花较长时间或返回数百万行的联接,则设置它ã€�

将该变量设置ä¸�DEFAULT之外的值,å°�SQL_BIG_SELECTS的值重设为0ã€�如果你重新设ç½�SQL_BIG_SELECTS值,max_join_size变量被忽略ã€�

如果查询结果位于查询缓存中,则不检查结果大小,因为前面已经计算了结果,不会要求服务器将它发送给客户端ã€�

该变量以前叫å��sql_max_join_sizeã€�

·         max_length_for_sort_data

确定使用çš�filesort算法的索引值大小的限值。参è§�7.2.12节,“MySQL如何优化ORDER BYâ€�ã€�

·         max_relay_log_size

如果复制从服务器写入中继日志时超出给定值,则滚动中继日志。通过该变量你可以对中继日志和二进制日志设置不同的限制。但是,将该变量设置ä¸�0ï¼�MySQL可以对二进制日志和中继日志使ç”�max_binlog_sizeã€�max_relay_log_size必须设置åœ�4096字节å’�1GB(包括)之间,或ä¸�0ã€� 默认值是0。参è§�6.3节,“复制实施细节â€�ã€�

·         max_seeks_for_key

限制根据键值寻找行时的最大搜索数ã€�MySQL优化器假定当用扫描键在表内搜索匹配的行时,不需要超过该数量的键值搜索,而不管键的实际基数是什ä¹�(参见13.5.4.11节,“SHOW INDEX语法â€�)。将该值设置为较低的å€�(100?),你可以强制MySQL选择键值而不选择表扫描ã€�

·         max_sort_length

当排åº�BLOBæˆ�TEXT值时使用的字节数。只使用每个值的å‰�max_sort_length字节;其它的被忽略ã€�

·         max_tmp_tables

客户端可以同时打开的临时表的最大数ã€�(但该选项还未生效ï¼�ã€�

·         max_user_connections

任何给定çš�MySQL账户允许的最大同时连接数ã€�0值表示“没æœ�限制”ã€�

该变量具有全局范围å’�(只读)会话范围。会话变量的的值与全局变量的值相同,除非当前账户具有非零MAX_USER_CONNECTIONS资源限制。在这种情况下,会话值反应了账户限制ã€�

·         max_write_lock_count

超过写锁定限制后,允许部分读锁定ã€�

·         myisam_data_pointer_size

默认指针大小,单位是字节,当未指å®�MAX_ROWS选项时,CREATE TABLE使用该变量创å»�MyISAM表。该变量不能小于2或大äº�7ã€� 默认值是6。参è§�A.2.11节,“表已满â€�ã€�

·         (DEPRECATED) myisam_max_extra_sort_file_size

æ³�释:MySQL 5.1不支持该变量。详细信息参è§�MySQL 5.0 参考手å†�ã€�

·         myisam_max_sort_file_size

重建MyISAM索引(åœ�REPAIR TABLEã€�ALTER TABLEæˆ�LOAD DATA INFILE过程ä¸�)时,允许MySQL使用的临时文件的最大空间大小。如果文件的大小超过该值,则使用键值缓存创建索引,要慢得多。该值的单位为字节ã€�

·         myisam_recover_options

--myisam-recover选项的值ã€�

·         myisam_repair_threads

如果该值大äº�1,在Repair by sorting过程中并行创å»�MyISAM表索å¼�(每个索引在自己的线程å†�)ã€� 默认值是1ã€�æ³�释:多线程维护仍然是alpha 编码ã€�

·         myisam_sort_buffer_size

当在REPAIR TABLE或用CREATE INDEX创建索引æˆ�ALTER TABLE过程中排åº� MyISAM索引分配的缓冲区ã€�

·         myisam_stats_method

当为MyISAM表搜集关于索引值分发的统计信息时服务器如何处理NULL值。该变量有两个可能的值,nulls_equalå’�nulls_unequal。对äº�nulls_equal,认为所æœ�NULL索引值时相等的,并形成一个数值组,其空间大小等于NULL值的数。对äº�nulls_unequalï¼�NULL值认为是不相等的,每ä¸�NULL形成一个数值组,大小为1ã€�

方法用于生成表统计信息,影响优化器如何选择索引来执行查询,详细描述è§�7.4.7节,“MyISAM索引统计集合â€�ã€�

·         multi_read_range

指定范围选择过程中发送到存储引擎的范围的最大值。默认值是256。向引擎发送多个范围可以大大改进某些选择的性能,特别是å¯�NDBCLUSTER。该引擎需要向所有节点发送范围请求,同时发送许多请求可以大大降低通信成本ã€�

·         named_pipe

(只适用Windows)说明服务器是否支持命名管道连接ã€�

·         net_buffer_length

在查询之间将通信缓冲区重设为该值。一般情况不应改变,但如果内存很小,可以将它设置为期望的客户端发送的SQL语句的长度。如果语句超出该长度,缓冲区自动扩大,直åˆ�max_allowed_packet字节ã€�

·         net_read_timeout

中断读前等待连接的其它数据的秒数。当服务器从客户端读数时ï¼�net_read_timeout指控制何时中断的超时值。当服务器向客户端写时,net_write_timeout指控制何时中断的超时值。又è§�slave_net_timeoutã€�

·         net_retry_count

如果某个通信端口的读操作中断了,在放弃前重试多次。在FreeBSD中该值应设得很高,因为内部中断将发送至所有线程ã€�

·         net_write_timeout

中断写之前等待块写入连接的秒数。又è§�net_read_timeoutã€�

·         new

åœ�MySQL 4.0中使用该变量来打开4.1中的一些行为,并用于向后兼容性。在MySQL 5.1ä¸�,它的值一直是OFF.

·         old_passwords

是否服务器应ä¸�MySQL用户账户使用pre-4.1-style密码。参è§�A.2.3节,“客户端不支持鉴定协议â€�ã€�

·         one_shot

这不是一个变量,但当设置变量是可以使用它。其描述è§�13.5.3节,“SET语法â€�ã€�

·         one_shot

这不是一个变量,但当设置变量是可以使用它。其描述è§�13.5.3节,“SET语法â€�ã€�

·         open_files_limit

操作系统允许mysqld打开的文件的数量。这是系统允许的实际值,可能与你在启动选项中赋ç»�mysqld的值不同。若在系统中MySQL不能更改打开的文件的数量,则该值为0ã€�

·         optimizer_prune_level

在查询优化从优化器搜索空间裁减低希望局部计划中使用的控制方法ã€�0值禁用该方法,以便优化器进行穷举搜索。值为1使优化器根据中间方案中得出的行数来裁减方案ã€�

·         optimizer_search_depth

查询优化器进行的搜索的最大深度。如果值大于查询中的关系数则查询方案比较佳,但生成查询执行方案需要的时间更长。值大于查询中的关系数则返回的执行方案更快,但方案远没有优化。如果设置为0, 系统自动选择合理的值。如果设置为查询中使用的表的最大数åŠ�2,优化器转换为MySQL 5.0.0(和以前的版本)中使用的算法并搜紀€�

·         pid_file

进程ID (PID)文件的路径名。可以用--pid-file选项设置该变量ã€�

·         plugin_dir

插件目录的路径。在MySQL 5.1.2中加入了该变量ã€�

·         port

服务器帧å��TCP/IP连接所用端口。可以用--port选项设置该变量ã€�

·         preload_buffer_size

重载索引时分配的缓冲区大小ã€�

·         protocol_version

MySQL服务器使用的客户ç«�/服务器协议的版本ã€�

·         query_alloc_block_size

为查询分析和执行过程中创建的对象分配的内存块大小。如果内存分段过程中遇到问题,将该变量增加一位会有帮助ã€�

·         query_cache_limit

不要缓存大于该值的结果。默认值是1048576(1MB)ã€�

·         query_cache_min_res_unit

查询缓存分配的最小块的大å°�(字节)ã€� 默认值是4096(4KB)。关于该变量的调节信息参è§�5.13.3节,“查询高速缓冲配置â€�ã€�

·         query_cache_size

为缓存查询结果分配的内存的数量。默认值是0,即禁用查询缓存。请注意即使query_cache_type设置ä¸�0也将分配此数量的内存。详细信息参è§�5.13.3节,“查询高速缓冲配置â€�ã€�

·         query_cache_type

设置查询缓存类型。设ç½�GLOBAL值可以设置后面的所有客户端连接的类型。客户端可以设置SESSION值以影响他们自己对查询缓存的使用。下面的表显示了可能的值:

选项

描述

0�OFF

不要缓存或查询结果。请注意这样不会取消分配的查询缓存区。要想取消,你应å°�query_cache_size设置ä¸�0ã€�

1�ON

缓存除了ä»�SELECT SQL_NO_CACHE开头的所有查询结果ã€�

2�DEMAND

只缓存以SELECT SQL_NO_CACHE开头的查询结果ã€�

该变量默认设ä¸�ONã€�

·         query_cache_wlock_invalidate

一般情况,当客户端å¯�MyISAM表进è¡�WRITE锁定时,如果查询结果位于查询缓存中,则其它客户端未被锁定,可以对该表进行查询。将该变量设置为1,则可以对表进行WRITE锁定,使查询缓存内所有对该表进行的查询变得非法。这样当锁定生效时,可以强制其它试图访问表的客户端来等待ã€�

·         query_prealloc_size

用于查询分析和执行的固定缓冲区的大小。在查询之间该缓冲区不释放。如果你执行复杂查询,分配更大的query_prealloc_size值可以帮助提高性能,因为它可以降低查询过程中服务器分配内存的需求ã€�

·         range_alloc_block_size

范围优化时分配的块的大小ã€�

·         read_buffer_size

每个线程连续扫描时为扫描的每个表分配的缓冲区的大å°�(字节)。如果进行多次连续扫描,可能需要增加该值, 默认值为131072ã€�

·         read_only

当变量对复制从服务器设置ä¸�ON时,从服务器不允许更新,除非通过从服务器的线程或用户拥有SUPER权限。可以确保从服务器不接受客户端的更新命令ã€�

·         relay_log_purge

当不再需要中继日志时禁用或启用自动清空中继日志。默认值是1(启用)ã€�

·         read_rnd_buffer_size

当排序后按排序后的顺序读取行时,则通过该缓冲区读取行,避免搜索硬盘。将该变量设置为较大的值可以大大改è¿�ORDER BY的性能。但是,这是为每个客户端分配的缓冲区,因此你不应将全局变量设置为较大的值。相反,只为需要运行大查询的客户端更改会话变量ã€�

·         secure_auth

如果ç”�--secure-auth选项启动äº�MySQL服务器,它将阻塞有旧格式(4.1之前)密码的所有账户所发起的连接。在这种情况下,该变量的值为ON,否则为OFFã€�

如果你想要防止使用旧格式的密ç �(致使网络通信不安å…�),你应启用该选项ã€�

如果启用该选项并且授权表为pre-4.1格式,服务器启动失败并且会出现错误。参è§�A.2.3节,“客户端不支持鉴定协议â€�ã€�

当用于客户端选项时,如果服务器需要该客户端账户的旧格式的密码,则客户端拒绝连接该服务器ã€�

·         server_id

--server-id选项的值。用于主复制服务器和从复制服务器ã€�

·         shared_memory

(只用äº�Windows)服务器是否允许共享内存连接ã€�

·         shared_memory_base_name

(只用äº�Windows)说明服务器是否允许共享内存连接,并为共享内存设置识别符。当在单台机器上运行多个MySQL实例时很有用ã€�

·         skip_external_locking

如果mysqld使用外部锁定,该值为OFFã€�

·         skip_networking

如果服务器只允许本地(é��TCP/IP)连接,该值为ON。在Unix中,本地连接使用Unix套接字文件。在Windows中,本地连接使用命名管道或共享内存。在NetWare中,只支æŒ�TCP/IP连接,因此不要将该变量设置为ONã€�

·         skip_show_database

防止不具æœ�SHOW DATABASES权限的人们使ç”�SHOW DATABASES语句。如果你担心用户能够看见属于其它用户的数据库,这样设置可以提高安全性。其效果取决äº�SHOW DATABASES权限:如果变量值为ON,只允许具有SHOW DATABASES权限的人们使ç”�SHOW DATABASES 语句,并且该语句将显示所有数据库名。如果值为OFF,允许所有用户执è¡�SHOW DATABASES,但只显示用户具æœ�SHOW DATABASES或其它权限的数据库的名称ã€�

·         slave_compressed_protocol

如果主、从服务器均支持,确定是否使用从/主压缩协议ã€�

·         slave_load_tmpdir

从服务器为复åˆ�LOAD DATA INFILE语句创建临时文件的目录名ã€�

·         slave_net_timeout

放弃读操作前等待ä¸�/从连接的更多数据的等待秒数ã€�

·         slave_skip_errors

从服务器应跳è¿�(忽视)的复制错误ã€�

·         slave_transaction_retries

如果由于ofInnoDB死锁或超è¿�InnoDBçš�innodb_lock_wait_timeoutæˆ�NDBCLUSTERçš�TransactionDeadlockDetectionTimeoutæˆ�TransactionInactiveTimeoutï¼�复制从服务器SQL线程未能执行事务,在提示错误并停止前它自动重å¤�slave_transaction_retries次ã€� 默认值是10ã€�

·         slow_launch_time

如果创建线程的时间超过该秒数,服务器增加Slow_launch_threads状态变量ã€�

·         socket

Unix平台:用于本地客户端连接的套接字文件。默认为/var/lib/mysql/mysql.sockã€�

Windows:用于本地客户端连接的命名管道名。默认为mysqlã€�

·         sort_buffer_size

每个排序线程分配的缓冲区的大小。增加该值可以加å¿�ORDER BYæˆ�GROUP BY操作。参è§�A.4.4节,“MySQL将临时文件储存在哪里â€�ã€�

·         sql_mode

当前的服务器SQL模式,可以动态设置。参è§�5.3.2节,“SQL服务器模式â€�ã€�

·         sql_slave_skip_counter

从服务器应跳过的来自主服务器的事件数ã€�

·         storage_engine

该变量是table_typeis的同义词。在MySQL 5.1ä¸�,首é€�storage_engineã€�

·         sync_binlog

如果为正,当每个sync_binlog'th写入该二进制日志后,MySQL服务器将它的二进制日志同步到硬盘ä¸�(fdatasync())。请注意如果åœ�autocommit模式,每执行一个语句向二进制日志写入一次,否则每个事务写入一次ã€� 默认值是0,不与硬盘同步。值为1是最安全的选择,因为崩溃时,你最多丢掉二进制日志中的一个语å��/事务;但是,这是最慢的选择(除非硬盘有电池备份缓存,从而使同步工作较快)ã€�

·         sync_frm

如果该变量设ä¸�1,当创建非临时表时它的.frm文件被同步到硬盘ä¸�(fdatasync());这样较慢但出现崩溃时较安全ã€� 默认值为1ã€�

·         system_time_zone

服务器系统时区。当 服务器开始执行时,它继承机器默认时区设置值,可以由运行服务器的账户或在启动脚本中进行修改。该值用来设ç½�system_time_zone。典型情况用TZ环境变量来指定时区。还可以ç”�mysqld_safe脚本çš�--timez选项来指定ã€�

·         table_cache

所有线程打开的表的数目。增大该值可以增åŠ�mysqld需要的文件描述符的数量。你可以检æŸ�Opened_tables状态变量来检查你是否需要增加表缓存。参è§�5.3.4节,“服务器状态变量â€�。如æž�Opened_tables值较大,并且多次执行FLUSH TABLES(只是强制关闭所有表并重æ–�),则应增åŠ�table_cache变量的值ã€�

关于表缓存的详细信息,参è§�7.4.9节,“MySQL如何打开和关闭表â€�ã€�

·         table_type

默认表类åž�(存储引擎)。要想在服务器启动时设置表类型,使用--default-table-type选项。参è§�5.3.1节,â€�mysqld命令行选项â€�ã€�

·         thread_cache_size

服务器应缓存多少线程以便重新使用。当客户端断开连接时,如果线程少于thread_cache_size,则客户端的线程被放入缓存。当请求线程时如果允许可以从缓存中重新利用线程,并且只有当缓存空了时才会创建新线程。如果新连接很多,可以增加该变量以提高性能ã€�(一般情况,如果线程执行得很好,性能提高不明æ˜�)。检æŸ�Connectionså’�Threads_created状态变量的å·�(详见5.3.4节,“服务器状态变量â€�),你可以看见线程缓存的效率ã€�

·         thread_concurrency

åœ�Solaris中,mysqld用该值调ç”�thr_setconcurrency()。该函数使应用程序向线程系统提供需要同时运行的期望的线程数目的提示ã€�

·         thread_stack

每个线程的堆栈大小。用crash-me测试检测出的许多限制取决于该值ã€� 默认值足够大,可以满足普通操作。参è§�7.1.4节,“MySQL基准套件â€�ã€�

·         time_format

该变量为使用ã€�

·         time_zone

当前的时区。初使值是'SYSTEM'(使用system_time_zone的å€�),但可以ç”�--default-time-zone选项在服务器启动时显式指定ã€�

·         tmp_table_size

如果内存内的临时表超过该值,MySQL自动将它转换为硬盘上çš�MyISAM表。如果你执行许多高级GROUP BY查询并且有大量内存,则可以增åŠ�tmp_table_size的值ã€�

·         tmpdir

保存临时文件和临时表的目录。该变量可以设置为几个路径,æŒ�round-robin模式使用。在Unix中应该用冒号(â€�:â€�)间隔开路径,在Windowsã€�NetWareå’�OS/2中用分号(â€�ï¼�â€�)ã€�

用来将负荷分散到几个物理硬盘上。如æž�MySQL服务器为复制从服务器,你不应å°�tmpdir设置为指向基于内存的文件系统上的目录或当服务器主机重启时声明的目录。复制从服务器需要部分临时文件来在机器重启后仍可用,以便它可以复制临时表或执è¡�LOAD DATA INFILE操作。如果服务器重启时临时文件夹中的文件丢失了,则复制失败。但是,如果你使ç”�MySQL 4.0.0或更新版本,你可以使ç”� slave_load_tmpdir变量设置从服务器的临时目录。在这种情况下,从服务器不再使用常规tmpdir,说明你可以å°�tmpdir设置到一个非固定位置ã€�

·         transaction_alloc_block_size

为保存将保存到二进制日志中的事务的查询而分配的内存块的大小(字节)ã€�

·         transaction_prealloc_size

ä¸�transaction_alloc_blocks分配的固定缓冲区的大小(字节),在两次查询之间不会释放。使该值足够大,将所有查询固定到一个事务中,可以避免多æ¬�malloc()调用ã€�

·         tx_isolation

默认事务隔离级别。默认值为REPEATABLE-READã€�

·         updatable_views_with_limit

该变量控制如果更新包å��LIMIT子句,是否可以在当前表中使用不包含主关键字的视图进行更新ã€�(通常ç”�GUI工具生成这类更新)。更新指UPDATEæˆ�DELETE语句。这儿主关键字指PRIMARY KEY,或一ä¸�UNIQUE索引,其中任何列不可以包å��NULLã€�

该变量有两个值:

o        1æˆ�YES:只发出警告(没有错误消息)。这æ˜� 默认值ã€�

o        0æˆ�NO:禁止更新ã€�

·         version

服务器版本号ã€�

·         version_bdb

BDB存储引擎版本ã€�

·         version_comment

configure脚本有一ä¸�--with-comment选项,当构建MySQL时可以进行注释。该变量包含注释值ã€�

·         version_compile_machine

MySQL构建的机器或架构的类型ã€�

·         version_compile_os

MySQL构建的操作系统的类型ã€�

·         wait_timeout

服务器关闭非交互连接之前等待活动的秒数ã€�

在线程启动时,根据全局wait_timeout值或全局interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(ç”�mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义)。又è§�interactive_timeoutã€�

5.3.3.1. 动态系统变é‡�

许多服务器系统变量是动态的,可以使ç”�SET GLOBALæˆ�SET SESSION在运行时设置。你还可以使ç”�SELECT获得它们的值。参è§�9.4节,“系统变量â€�ã€�

下面的表列出了所有动态系统变量。最å��1列说明每个变量是否适用GLOBALæˆ�SESSION(或二è€�)ã€�

变量å��

值类åž�

类型

autocommit

boolean

SESSION

big_tables

boolean

SESSION

binlog_cache_size

numeric

GLOBAL

bulk_insert_buffer_size

numeric

GLOBAL | SESSION

character_set_client

string

GLOBAL | SESSION

character_set_connection

string

GLOBAL | SESSION

character_set_results

string

GLOBAL | SESSION

character_set_server

string

GLOBAL | SESSION

collation_connection

string

GLOBAL | SESSION

collation_server

string

GLOBAL | SESSION

completion_type

numeric

GLOBAL | SESSION

concurrent_insert

boolean

GLOBAL

connect_timeout

numeric

GLOBAL

convert_character_set

string

GLOBAL | SESSION

default_week_format

numeric

GLOBAL | SESSION

delay_key_write

OFF | ON | ALL

GLOBAL

delayed_insert_limit

numeric

GLOBAL

delayed_insert_timeout

numeric

GLOBAL

delayed_queue_size

numeric

GLOBAL

div_precision_increment

numeric

GLOBAL | SESSION

engine_condition_pushdown

boolean

GLOBAL | SESSION

error_count

numeric

SESSION

expire_logs_days

numeric

GLOBAL

flush

boolean

GLOBAL

flush_time

numeric

GLOBAL

foreign_key_checks

boolean

SESSION

ft_boolean_syntax

numeric

GLOBAL

group_concat_max_len

numeric

GLOBAL | SESSION

identity

numeric

SESSION

innodb_autoextend_increment

numeric

GLOBAL

innodb_concurrency_tickets

numeric

GLOBAL

innodb_max_dirty_pages_pct

numeric

GLOBAL

innodb_max_purge_lag

numeric

GLOBAL

innodb_support_xa

boolean

GLOBAL | SESSION

innodb_sync_spin_loops

numeric

GLOBAL

innodb_table_locks

boolean

GLOBAL | SESSION

innodb_thread_concurrency

numeric GLOBAL

 

innodb_thread_sleep_delay

numeric GLOBAL

 

insert_id

boolean

SESSION

interactive_timeout

numeric

GLOBAL | SESSION

join_buffer_size

numeric

GLOBAL | SESSION

key_buffer_size

numeric

GLOBAL

last_insert_id

numeric

SESSION

local_infile

boolean

GLOBAL

log_warnings

numeric

GLOBAL

long_query_time

numeric

GLOBAL | SESSION

low_priority_updates

boolean

GLOBAL | SESSION

max_allowed_packet

numeric

GLOBAL | SESSION

max_binlog_cache_size

numeric

GLOBAL

max_binlog_size

numeric

GLOBAL

max_connect_errors

numeric

GLOBAL

max_connections

numeric

GLOBAL

max_delayed_threads

numeric

GLOBAL

max_error_count

numeric

GLOBAL | SESSION

max_heap_table_size

numeric

GLOBAL | SESSION

max_insert_delayed_threads

numeric

GLOBAL

max_join_size

numeric

GLOBAL | SESSION

max_relay_log_size

numeric

GLOBAL

max_seeks_for_key

numeric

GLOBAL | SESSION

max_sort_length

numeric

GLOBAL | SESSION

max_tmp_tables

numeric

GLOBAL | SESSION

max_user_connections

numeric

GLOBAL

max_write_lock_count

numeric

GLOBAL

myisam_stats_method

enum

GLOBAL | SESSION

multi_read_range

numeric

GLOBAL | SESSION

myisam_data_pointer_size

numeric

GLOBAL

log_bin_trust_routine_creators

boolean

GLOBAL

myisam_max_sort_file_size

numeric

GLOBAL | SESSION

myisam_repair_threads

numeric

GLOBAL | SESSION

myisam_sort_buffer_size

numeric

GLOBAL | SESSION

net_buffer_length

numeric

GLOBAL | SESSION

net_read_timeout

numeric

GLOBAL | SESSION

net_retry_count

numeric

GLOBAL | SESSION

net_write_timeout

numeric

GLOBAL | SESSION

old_passwords

numeric

GLOBAL | SESSION

optimizer_prune_level

numeric

GLOBAL | SESSION

optimizer_search_depth

numeric

GLOBAL | SESSION

preload_buffer_size

numeric

GLOBAL | SESSION

query_alloc_block_size

numeric

GLOBAL | SESSION

query_cache_limit

numeric

GLOBAL

query_cache_size

numeric

GLOBAL

query_cache_type

enumeration

GLOBAL | SESSION

query_cache_wlock_invalidate

boolean

GLOBAL | SESSION

query_prealloc_size

numeric

GLOBAL | SESSION

range_alloc_block_size

numeric

GLOBAL | SESSION

read_buffer_size

numeric

GLOBAL | SESSION

read_only

numeric

GLOBAL

read_rnd_buffer_size

numeric

GLOBAL | SESSION

rpl_recovery_rank

numeric

GLOBAL

safe_show_database

boolean

GLOBAL

secure_auth

boolean

GLOBAL

server_id

numeric

GLOBAL

slave_compressed_protocol

boolean

GLOBAL

slave_net_timeout

numeric

GLOBAL

slave_transaction_retries

numeric

GLOBAL

slow_launch_time

numeric

GLOBAL

sort_buffer_size

numeric

GLOBAL | SESSION

sql_auto_is_null

boolean

SESSION

sql_big_selects

boolean

SESSION

sql_big_tables

boolean

SESSION

sql_buffer_result

boolean

SESSION

sql_log_bin

boolean

SESSION

sql_log_off

boolean

SESSION

sql_log_update

boolean

SESSION

sql_low_priority_updates

boolean

GLOBAL | SESSION

sql_max_join_size

numeric

GLOBAL | SESSION

sql_mode

enumeration

GLOBAL | SESSION

sql_notes

boolean

SESSION

sql_quote_show_create

boolean

SESSION

sql_safe_updates

boolean

SESSION

sql_select_limit

numeric

SESSION

sql_slave_skip_counter

numeric

GLOBAL

updatable_views_with_limit

enumeration

GLOBAL | SESSION

sql_warnings

boolean

SESSION

sync_binlog

numeric

GLOBAL

sync_frm

boolean

GLOBAL

storage_engine

enumeration

GLOBAL | SESSION

table_cache

numeric

GLOBAL

table_type

enumeration

GLOBAL | SESSION

thread_cache_size

numeric

GLOBAL

time_zone

string

GLOBAL | SESSION

timestamp

boolean

SESSION

tmp_table_size

enumeration

GLOBAL | SESSION

transaction_alloc_block_size

numeric

GLOBAL | SESSION

transaction_prealloc_size

numeric

GLOBAL | SESSION

tx_isolation

enumeration

GLOBAL | SESSION

unique_checks

boolean

SESSION

wait_timeout

numeric

GLOBAL | SESSION

warning_count

numeric

SESSION

标记ä¸�string的变量采用字符串值。标记为numeric的变量采用数字值。标记为boolean的变量可以设置为0ã€�1ã€�ONæˆ�OFF。标记为enumeration的变量一般情况应设置为该变量的某个可用值,但还可以设置为对应期望的枚举值的数字。对äº�枚举系统变量,第1个枚举值应对应0。这不同äº�ENUM列,ç¬�1个枚举值对åº�1ã€�

5.3.4. 服务器状态变é‡�

服务器维护许多提供操作相关信息的状态变量。你可以通过SHOW STATUS语句查看这些变量和它们的值:

mysql> SHOW STATUS;
+-----------------------------------+------------+
| Variable_name                     | Value      |
+-----------------------------------+------------+
| Aborted_clients                   | 0          |
| Aborted_connects                  | 0          |
| Bytes_received                    | 155372598  |
| Bytes_sent                        | 1176560426 |
 
�
 
| Connections                       | 30023      |
| Created_tmp_disk_tables           | 0          |
| Created_tmp_files                 | 3          |
| Created_tmp_tables                | 2          |
 
�
 
| Threads_created                   | 217        |
| Threads_running                   | 88         |
| Uptime                            | 1389872    |
+-----------------------------------+------------+
 

ç”�FLUSH STATUS语句可以将许多状态变量重设为0ã€�

状态变量有以下含义。没有指示版本的变量åœ�MySQL 5.1之前已经出现。关于它们的使用历史,参è§�MySQL 5.0参考手å†�ã€�

·         Aborted_clients

由于客户端没有正确关闭连接导致客户端终止而中断的连接数。参è§�A.2.10节,“通信错误和失效连接â€�ã€�

·         Aborted_connects

试图连接åˆ�MySQL服务器而失败的连接数。参è§�A.2.10节,“通信错误和失效连接â€�ã€�

·         Binlog_cache_disk_use

使用临时二进制日志缓存但超过binlog_cache_size值并使用临时文件来保存事务中的语句的事务数量ã€�

·         Binlog_cache_use

使用临时二进制日志缓存的事务数量ã€�

·         Bytes_received

从所有客户端接收到的字节数ã€�

·         Bytes_sent

发送给所有客户端的字节数ã€�

·         Com_xxx

Com_xxx 语句计数变量表示每个xxx 语句执行的次数。每类语句有一个状态变量。例如,Com_deleteå’�Com_insert分别统计DELETE å’�INSERT语句执行的次数ã€�

Com_stmt_xxx状态变量为ï¼�

o        Com_stmt_prepare

o        Com_stmt_execute

o        Com_stmt_fetch

o        Com_stmt_send_long_data

o        Com_stmt_reset

o        Com_stmt_close

这些变量代表准备好的语句命令。它们的名字对应网络层使用的COM_xxx 命令系列;换句话说:当准备好的语å��API调用å¦�mysql_stmt_prepare()ã€�mysql_stmt_执行()并执行时,它们的值增加。但是,当执行下面的SQL语句时,Com_stmt_prepare, Com_stmt_executeå’�Com_stmt_close也增加:PREPAREã€�EXECUTEæˆ�DEALLOCATE PREPARE。此外,æ—�(ä»�MySQL 4.1.3起可ç”�)语句计数变量Com_prepare_sqlã€�Com_execute_sqlå’�Com_dealloc_sql的值也éš�PREPAREã€�EXECUTEå’�DEALLOCATE PREPARE语句增加ã€�Com_stmt_fetch代表通过光标获取的网ç»�round-trips的总数量ã€�

所æœ�Com_stmt_xxx变量将增加,即使语句参数未知或执行过程中出现错误。换句话说,它们的值对应发出的请求数,而不是成功完成的请求数ã€�

·         Connections

试图连接åˆ�(不管是否成功)MySQL服务器的连接数ã€�

·         Created_tmp_disk_tables

服务器执行语句时在硬盘上自动创建的临时表的数量ã€�

·         Created_tmp_files

mysqld已经创建的临时文件的数量ã€�

·         Created_tmp_files

服务器执行语句时自动创建的内存中的临时表的数量。如æž�Created_tmp_disk_tables较大,你可能要增åŠ�tmp_table_size值使临时 表基于内存而不基于硬盘ã€�

·         Delayed_errors

ç”�INSERT DELAYED写的出现错误的行æ•�(可能ä¸�duplicate key)ã€�

·         Delayed_insert_threads

使用çš�INSERT DELAYED处理器线程数ã€�

·         Delayed_writes

写入çš�INSERT DELAYED行数ã€�

·         Flush_commands

执行çš�FLUSH语句数ã€�

·         Handler_commit

内部提交语句数ã€�

·         Handler_discover

MySQL服务器可以问NDB CLUSTER存储引擎是否知道某一名字的表。这被称作发现ã€�Handler_discover说明通过该方法发现的次数ã€�

·         Handler_delete

行从表中删除的次数ã€�

·         Handler_read_first

索引中第一条被读的次数。如果较高,它建议服务器正执行大量全索引扫描;例如,SELECT col1 FROM foo,假å®�col1有索引ã€�

·         Handler_read_key

根据键读一行的请求数。如果较高,说明查询和表的索引正确ã€�

·         Handler_read_next

按照键顺序读下一行的请求数。如果你用范围约束或如果执行索引扫描来查询索引列,该值增加ã€�

·         Handler_read_prev

按照键顺序读前一行的请求数。该读方法主要用于优åŒ�ORDER BY ... DESCã€�

·         Handler_read_rnd

根据固定位置读一行的请求数。如果你正执行大量查询并需要对结果进行排序该值较高。你可能使用了大量需è¦�MySQL扫描整个表的查询或你的连接没有正确使用键ã€�

·         Handler_read_rnd_next

在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明你的表索引不正确或写入的查询没有利用索引ã€�

·         Handler_rollback

内部ROLLBACK语句的数量ã€�

·         Handler_update

在表内更新一行的请求数ã€�

·         Handler_write

在表内插入一行的请求数ã€�

·         Innodb_buffer_pool_pages_data

包含数据的页æ•�(脏或干净)ã€�

·         Innodb_buffer_pool_pages_dirty

当前的脏页数ã€�

·         Innodb_buffer_pool_pages_flushed

要求清空的缓冲池页数ã€�

·         Innodb_buffer_pool_pages_free

空页数ã€�

·         Innodb_buffer_pool_pages_latched

åœ�InnoDB缓冲池中锁定的页数。这是当前正读或写或由于其它原因不能清空或删除的页数ã€�

·           Innodb_buffer_pool_pages_misc

忙的页数,因为它们已经被分配优先用作管理,例如行锁定或适用的哈希索引。该值还可以计算ä¸�Innodb_buffer_pool_pages_total - Innodb_buffer_pool_pages_free - Innodb_buffer_pool_pages_dataã€�

·         Innodb_buffer_pool_pages_total

缓冲池总大小(页数)ã€�

·         Innodb_buffer_pool_read_ahead_rnd

InnoDB初始化的â€�随机â€�read-aheads数。当查询以随机顺序扫描表的一大部分时发生ã€�

·         Innodb_buffer_pool_read_ahead_seq

InnoDB初始化的顺序read-aheads数。当InnoDB执行顺序全表扫描时发生ã€�

·         Innodb_buffer_pool_read_requests

InnoDB已经完成的逻辑读请求数ã€�

·         Innodb_buffer_pool_reads

不能满足InnoDB必须单页读取的缓冲池中的逻辑读数量ã€�

·         Innodb_buffer_pool_wait_free

一般情况,通过后台å��InnoDB缓冲池写。但是,如果需要读或创建页,并且没有干净的页可用,则它还需要先等待页面清空。该计数器对等待实例进行记数。如果已经适当设置缓冲池大小,该值应小ã€�

·         Innodb_buffer_pool_write_requests

å��InnoDB缓冲池的写数量ã€�

·         Innodb_data_fsyncs

fsync()操作数ã€�

·         Innodb_data_pending_fsyncs

当前挂起çš�fsync()操作数ã€�

·         Innodb_data_pending_reads

当前挂起的读数ã€�

·         Innodb_data_pending_writes

当前挂起的写数ã€�

·         Innodb_data_read

至此已经读取的数据数量(字节)ã€�

·         Innodb_data_reads

数据读总数量ã€�

·         Innodb_data_writes

数据写总数量ã€�

·         Innodb_data_written

至此已经写入的数据量(字节)ã€�

·         Innodb_dblwr_writes, Innodb_dblwr_pages_written

已经执行的双写操作数量和为此目的已经写好的页数。参è§�15.2.14.1节,“磁盘I/Oâ€�ã€�

·         Innodb_log_waits

我们必须等待的时间,因为日志缓冲区太小,我们在继续前必须先等待对它清空ã€�

·         Innodb_log_write_requests

日志写请求数ã€�

·         Innodb_log_writes

向日志文件的物理写数量ã€�

·         Innodb_os_log_fsyncs

向日志文件完成的fsync()写数量ã€�

·         Innodb_os_log_pending_fsyncs

挂起的日志文ä»�fsync()操作数量ã€�

·         Innodb_os_log_pending_writes

挂起的日志文件写操作ã€�

·         Innodb_os_log_written

写入日志文件的字节数ã€�

·         Innodb_page_size

编译çš�InnoDB页大å°�(默认16KB)。许多值用页来记数;页的大小很容易转换为字节ã€�

·         Innodb_pages_created

创建的页数ã€�

·         Innodb_pages_read

读取的页数ã€�

·         Innodb_pages_written

写入的页数ã€�

·         Innodb_row_lock_current_waits

当前等待的待锁定的行数ã€�

·         Innodb_row_lock_time

行锁定花费的总时间,单位毫秒ã€�

·         Innodb_row_lock_time_avg

行锁定的平均时间,单位毫秒ã€�

·         Innodb_row_lock_time_max

行锁定的最长时间,单位毫秒ã€�

·         Innodb_row_lock_waits

一行锁定必须等待的时间数ã€�

·         Innodb_rows_deleted

ä»�InnoDB表删除的行数ã€�

·         Innodb_rows_inserted

插入åˆ�InnoDB表的行数ã€�

·         Innodb_rows_read

ä»�InnoDB表读取的行数ã€�

·         Innodb_rows_updated

InnoDB表内更新的行数ã€�

·         Key_blocks_not_flushed

键缓存内已经更改但还没有清空到硬盘上的键的数据块数量ã€�

·         Key_blocks_unused

键缓存内未使用的块数量。你可以使用该值来确定使用了多少键缓存;参è§�5.3.3节,“服务器系统变量â€�ä¸�Key_buffer_size的讨论ã€�

·         Key_blocks_used

键缓存内使用的块数量。该值为高水平线标记,说明已经同时最多使用了多少块ã€�

·         Key_read_requests

从缓存读键的数据块的请求数ã€�

·         Key_reads

从硬盘读取键的数据块的次数。如æž�Key_reads较大,则Key_buffer_size值可能太小。可以用Key_reads/Key_read_requests计算缓存损失率ã€�

·         Key_write_requests

将键的数据块写入缓存的请求数ã€�

·         Key_writes

向硬盘写入将键的数据块的物理写操作的次数ã€�

·         Last_query_cost

用查询优化器计算的最后编译的查询的总成本。用于对比同一查询的不同查询方案的成本。默认å€�0表示还没有编译查诀€� 默认值是0ã€�Last_query_cost具有会话范围ã€�

·         Max_used_connections

服务器启动后已经同时使用的连接的最大数量ã€�

·         Not_flushed_delayed_rows

等待写入INSERT DELAY队列的行数ã€�

·         Open_files

打开的文件的数目ã€�

·         Open_streams

打开的流的数é‡�(主要用于记录)ã€�

·         Open_tables

当前打开的表的数量ã€�

·         Opened_tables

已经打开的表的数量。如æž�Opened_tables较大ï¼�table_cache 值可能太小ã€�

·         QCACHE_free_blocks

查询缓存内自由内存块的数量ã€�

·         QCACHE_free_memory

用于查询缓存的自由内存的数量ã€�

·         QCACHE_hits

查询缓存被访问的次数ã€�

·         QCACHE_inserts

加入到缓存的查询数量ã€�

·         QCACHE_lowmem_prunes

由于内存较少从缓存删除的查询数量ã€�

·         QCACHE_not_cached

非缓存查询数(不可缓存,或由于query_cache_type设定值未缓存)ã€�

·         Qcache_queries_in_cache

登记到缓存内的查询的数量ã€�

·         Qcache_total_blocks

查询缓存内的总块数ã€�

·         Questions

已经发送给服务器的查询的个数ã€�

·         Rpl_status

失败安全复制状æ€�(还未使用)ã€�

·         Select_full_join

没有使用索引的联接的数量。如果该值不ä¸�0,你应仔细检查表的索引ã€�

·         Select_full_range_join

在引用的表中使用范围搜索的联接的数量ã€�

·         Select_range

在第一个表中使用范围的联接的数量。一般情况不是关键问题,即使该值相当大ã€�

·         Select_range_check

在每一行数据后对键值进行检查的不带键值的联接的数量。如果不ä¸�0,你应仔细检查表的索引ã€�

·         Select_scan

对第一个表进行完全扫描的联接的数量ã€�

·         Slave_open_temp_tables

当前由从SQL线程打开的临时表的数量ã€�

·         Slave_running

如果该服务器是连接到主服务器的从服务器,则该值为ONã€�

·         Slave_retried_transactions

启动后复制从服务å™�SQL线程尝试事务的总次数ã€�

·         Slow_launch_threads

创建时间超过slow_launch_time秒的线程数ã€�

·         Slow_queries

查询时间超过long_query_time秒的查询的个数。参è§�5.11.4节,“慢速查询日志â€�ã€�

·         Sort_merge_passes

排序算法已经执行的合并的数量。如果这个变量值较大,应考虑增加sort_buffer_size系统变量的值ã€�

·         Sort_range

在范围内执行的排序的数量ã€�

·         Sort_rows

已经排序的行数ã€�

·         Sort_scan

通过扫描表完成的排序的数量ã€�

·         Ssl_xxx

用于SSL连接的变量ã€�

·         Table_locks_immediate

立即获得的表的锁的次数ã€�

·         Table_locks_waited

不能立即获得的表的锁的次数。如果该值较高,并且有性能问题,你应首先优化查询,然后拆分表或使用复制ã€�

·         Threads_cached

线程缓存内的线程的数量ã€�

·         Threads_connected

当前打开的连接的数量ã€�

·         Threads_created

创建用来处理连接的线程数。如æž�Threads_created较大,你可能要增åŠ�thread_cache_size值。缓存访问率的计算方æ³�Threads_created/Connectionsã€�

·           Threads_running

激活的(非睡眠状态)线程数ã€�

·         Uptime

服务器已经运行的时间(以秒为单位)ã€�

5.4. mysql_fix_privilege_tables:升级MySQL系统è¡�

一äº�MySQL发布å¯�mysql数据库中的系统表的结构进行了更改,添加了新权限或特性。当你更新到新版æœ�MySQL,你应同时更新系统表,以确保它们的结构最新。首先备ä»�mysql数据库,然后按照下面的程序操作ã€�

åœ�Unixæˆ�Unix类系统中,运è¡�mysql_fix_privilege_tables脚本来更新系统表ï¼�

shell> mysql_fix_privilege_tables

你必须在服务器运行时执行该脚本。它试图连接本机上用root运行的服务器。如æž�root账户需要密码,在命令行中按下述方法给出密码ï¼�

shell> mysql_fix_privilege_tables--password=root_password

mysql_fix_privilege_tables脚本可以执行将系统表转换为当前格式的任何动作。运行时你可能会看见一äº�Duplicate column name警告;你可以忽略它们ã€�

运行完脚本后,停止服务器并重启ã€�

åœ�Windows系统中,MySQL分发包括mysql_fix_privilege_tables.sql SQL脚本,你可以ç”�mysql客户端来运行。例如,如果MySQL安装åˆ�C:\Program Files\MySQL\MySQL Server 5.1,命令应为:

C:\> C:\Program Files\MySQL\MySQL Server 5.1\bin\mysql -u root -p mysql
mysql> SOURCE C:/Program Files/MySQL/MySQL Server 5.1/scripts/mysql_fix_privilege_tables.sql

如果安装到其它目录,相应地更改路径名ã€�

mysql命令将提示输å…�root密码;按照提示输入密码ã€�

åœ�Unix中,å½�mysql处理mysql_fix_privilege_tables.sql script脚本中的语句时,你可能会看见一äº�Duplicate column name警告;你可以忽略它们ã€�

运行完脚本后,停止服务器并重启ã€�

5.5. MySQL服务器关机进ç¨�

  1.  服务器关闭进程可以概括为ï¼�

    1.    启动关闭进程

    2.    服务器根据需要创建关闭线ç¨�

    3.    服务器停止接收新连接

    4.    服务器终止当前的活动

    5.    存储引擎被停掉或关闭

    6.    服务器退å‡�

    下面是更详细的描述:

    1.    启动关闭进程ã€�

    可以用多种方法启动服务器的关闭。例如,拥有SHUTDOWN权限的用户可以执è¡�mysqladmin shutdown命令ã€�mysqladmin可以用于所有支æŒ�MySQL的平台上。其它操作系统相关的关闭开始方法还可能有:åœ�Unix中,当接收到SIGTERM信号后,服务器关闭。对于在Windows中作为服务运行的服务器,当服务管理器让它关闭时,则关闭ã€�

    2.    服务器根据需要创建关闭线程ã€�

    根据开始关闭的方式,服务器可以创建线程来处理关闭进程。如果客户端需要关闭,则创建关闭线程。如果收åˆ�SIGTERM信号后关闭,信号线程可以自己关闭,或者创建单独的线程来完成。如果服务器尝试创建关闭线程而不能创å»�(例如,如果内存被耗尽),它在错误日志中给出诊断消息ï¼�

    Error: Can't create thread to kill server

    3.    服务器停止接收新连接ã€�

    在关闭过程中要想防止启动新活动,服务器停止接收新的客户端连接。它将关闭它帧听的网络连接:TCP/IP端口ã€�Unix套接字文件ã€�Windows命名管道和在Windows中的共享内存ã€�

    4.    服务器终止当前的活动ã€�

    对于每个与客户端连接相关的线程,与客户端的连接被中断,线程被标记为“杀掉的”。当线程注意到此类标记后则线程终歀€‚空闲连接的线程很快终止。当前正处理查询的线程定期检查它们的状态,终止的时间较长。关于线程终止的详细信息,参è§�13.5.5.3节,“KILL语法â€�,特别是关于å¯�MyISAM表的杀掉的REPAIR TABLEæˆ�OPTIMIZE TABLE操作ã€�

    对于有打开事务的线程,事务被回滚。请注意如果某个线程正在更新非事务表,多è¡�UPDATEæˆ�INSERT等操作会使表部分更新,因为操作在完成前会终止ã€�

    如果服务器是主复制服务器,与当前连接的从服务器相关的线程的处理方式同其它客户端线程。即每个线程被标记为杀掉的,在下次检查他的状态后会退出ã€�

    如果服务器是从复制服务器,在客户端线程标记为杀掉的之前,激活的I/Oå’�SQL线程被停歀€�SQL线程允许先结束它当前的语å��(以避免造成复制问题)然后停止。如果此æ—�SQL线程正位于事务中部,事务åˆ� 回滚ã€�

    5.    存储引擎被停掉或关闭ã€�

    在该阶段,表缓存被清空,所有打开的表被关闭ã€�

    每个存储引擎执行它管理的表需要的任何动作。例如,MyISAM清空任何挂起的表索引写操作ã€�InnoDB将它的缓冲池清空到硬盘上(除é��innodb_fast_shutdownä¸�2),将当前的LSN写入表内,并终止自己的内部线程ã€�

    6.    服务器退出ã€�

5.6. 一般安全问é¢�

本节描述一些常见的需要注意的安全问题,以及一些可以使你的MySQL安装更加安全以防止黑客和误用的措施。关äº�MySQL用于设置用户账户并检查数据库访问的访问控制系统的具体信息,参è§�5.7节,“MySQL访问权限系统â€�ã€�

5.6.1. 通用安全指南

任何在与Internet联网的计算机上使ç”�MySQL的用户都应仔细阅读本节,以避免最常见的安全问题ã€�

讨论安全时,我们强调必须完全保护整个服务器主机的安全(而不只是MySQL服务å™�)防范各种类型的可能的攻击:偷听、修改、重放和拒绝服务。我们在这里不能覆盖各方面的内容和措施ã€�

MySQL根据访问控制列表(ACL)对所有连接、查询和其它用户尝试执行的操作进行安全管理ã€�MySQL客户端和服务器之间还支持SSL-加密连接。这儿讨论的许多概念并不æ˜�MySQL专有的;该思想几乎同样适合所有应用程序ã€�

运行MySQL时,应尽量遵从下面的指导ï¼�

·         不要让任何人(除了MySQL root账户)访问mysql数据库中çš�user表!这很关键ã€�加密的密码才æ˜�MySQL中的真正的密码ã€�知道user表中所列的密码并且能访问该账户客访问的主机的人可以很容易地用该用户登录ã€�

·         学习MySQL访问权限系统。用GRANTå’�REVOKE语句来控制对MySQL的访问。不要授予超过需求的权限。决不能为所有主机授权ã€�

检查清单:

o        试试mysql -u root。如果你能够成功连接服务器而没有要任何密码,则说明有问题。任何人可以作为MySQLroot用户用它的全部权限来连接MySQL服务器!查阅MySQL安装说明,应特别注意关于设置root密码的信息。参è§�2.9.3节,“使初始MySQL账户安全â€�ã€�

o        通过SHOW GRANTS语句检查查看谁已经访问了什么。然后使ç”�REVOKE语句删除不再需要的权限ã€�

·         不要将纯文本密码保存到数据库中。如果你的计算机有安全危险,入侵者可以获得所有的密码并使用它们。相反,应使ç”�MD5()ã€�SHA1()或单向哈希函数ã€�

·         不要从词典中选择密码。有专门的程序可以破解它们。即使象â€�xfish98”这样的密码也很差。而â€�duag98”要好得多,虽然包含了相同的字â€�fish”,但从标准QWERTY键盘向左输入。另一种方法是使用â€�Mhall”,来自句子â€�Mary had a little lamb.”中每个字的第一个字符。这样很容易记住并输入,但是不知道的人很难猜出来ã€�

·         购买防火墙。这样可以保护你防范各种软件中至å°�50%的各种类型的攻击。把MySQL放到防火墙后或隔离区(DMZ)ã€�

检查清单:

o        试试ä»�Internet使用nmap工具扫描端口ã€�MySQL默认使用端口3306。不应从不可信任主机访问该端口。另一种检查是å��MySQL端口打开的简单方式是从远程机器试试下面的命令,其ä¸�server_hostæ˜�MySQL服务器运行的主机ï¼�

o                     shell> telnet server_host 3306

如果得到连接并得到一些垃圾字符,则端口打开着,则应从防火墙或路由器上关闭,除非你有合理的理由让它开着。如æž�telnet挂起或连接被拒绝,则端口被阻塞,这是你所希望的ã€�

不要信任应用程序的用户输入的任何数据。它们可以用Web形式ã€�URL或构建的应用程序输入特殊或逃溢字符序列来尝试欺骗你的代码。如果某个用户输入â€�; DROP DATABASE mysql;”等内容,应确保你的应用程序保持安全。这是特例,但当黑客使用类似技术时,如果你没有做好准备,结果可能会出现大的安全漏洞和数据丢失ã€�

一个常见的错误是只保护字符串数据值。一定要记住还应检查数字数据。如果当用户输入å€�234时,应用程序生成查询SELECT * FROM table WHERE ID=234ï¼�用户可以输入å€�234 OR 1=1使应用程序生成查è¯�SELECT * FROM table WHERE ID=234 OR 1=1。结果是服务器查找表内的每个记录。这样会暴露每个记录并造成过多的服务器负载。保护防范这类攻击的最简单的方法是使用单引号将数字常量引起来ï¼�SELECT * FROM table WHERE ID='234'。如果用户输入其它信息,均变为字符串的一部分。在数字部分ï¼�MySQL自动将字符串转换为数字并剥离字符串包含的附加的非数字字符ã€�

有时候人们会认为如果数据库只包含供公共使用的数据,则不需要保护。这是不正确的。即使允许显示数据库中的任何记录,你仍然应保护防范拒绝服务攻å‡�(例如,基于前面段落中所述的技术的攻击,会使服务器浪费资源)。否则,你的服务器不再响应合法用户ã€�

检查清单:

o        试试ç”�Web形式输入单引号和双引å��(â€�'’和â€�"â€�)。如果得到任何形式的MySQL错误,立即分析原因ã€�

o        试试修改动æ€�URL,可以在其中添加%22(â€�"â€�)ã€�%23(â€�#â€�)å’�%27(â€�'â€�)ã€�

o        试试在动æ€�URL中修改数据类型,使用前面示例中的字符,包括数字和字符类型。你的应用程序应足够安全,可以防范此类修改和类似攻击ã€�

o        试试输入字符、空格和特殊符号,不要输入数值字段的数字。你的应用程序应在将它们传递到MySQL之前将它们删除或生成错误。将未经过检查的值传递给MySQL是很危险的!

o        将数据传ç»�MySQL之前先检查其大小ã€�

o        用管理账户之外的用户名将应用程序连接到数据库。不要给应用程序任何不需要的访问权限ã€�

·         许多应用程序编程接口提供了措施逃逸数据值中的特殊字符。如果使用正确,可以防止应用程序用户输入使应用程序生成不期望的效果的语句的数值:

o        MySQL C API:使ç”�mysql_real_escape_string() API调用ã€�

o        MySQL++:查询流使用escapeå’�quote修订符ã€�

o        PHP:使ç”�mysql_escape_string()函数基于MySQL C API中的同名函数ã€�(åœ�PHP 4.0.3之前,使用addslashes()ï¼�ã€�åœ�PHP 5ä¸�,可以使用mysqli扩展名,它支持改进的MySQL鉴定协议和密码,以及用占位符编写的语句ã€�

o        Perl DBI:使ç”�quote()方法或使用占位符ã€�

o        Java JDBC:使用一ä¸�PreparedStatement对象和占位符ã€�

其它编程接口有类似的功能ã€�

·         不要通过Internet传送明æ–�(未加密的)数据。该信息可以被有足够时间和能力来截取它并用于个人目的的任何人访问。相反,应使用加密协议,例如SSLæˆ�SSHã€�MySQL支持内部SSL连接,例如版æœ� 4.0.0。可以使ç”�SSH端口映射为通信创建加密(并压ç¼�)的隧道ã€�

·         学会使用tcpdumpå’�strings工具。在大多数情况下,你可以使用下面的命令检查是å��MySQL数据流未加密ï¼�

·                shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings

(该命令在Linux中可以工作,在其它系统中经过小小的修改后应可以工作)ã€� 警告:如果你没有看见明文数据,并不一定说明信息实际上被加密了。如果你需要较高级别的安全,你应咨询安全专家ã€�

5.6.2. 使MySQL在攻击者面前保持安å…�

当你连接åˆ�MySQL服务器时,你应使用一个密码。密码不以明文在上传输。客户端连接序列中的密码处理åœ�MySQL 4.1.1中已经升级,很安全。如果你仍然使用pre-4.1.1-风格的密码,加密算法不如新算法强;通过一些工作,可以窃取客户端和服务器之间的通信的聪明的攻击者可以破解密码ã€�(关于不同的密码处理方法的讨论参见5.7.9节,“MySQL 4.1中的密码哈希处理â€�ï¼�ã€� 如果客户端和服务器之间的连接通过不可信任网络,你应使ç”�SSH隧道来加密通信ã€�

所有其它信息以文本传送,可以被可以看到连接的任何人读取。如果你担心这个,你可以使用压缩协议来使通信更难以解密。要想使连接更加安全,你应使ç”�SSH来获得加密的MySQL服务器和MySQL客户端之间的TCP/IP连接。你可以ä»�http://www.openssh.org/找到开放源ç �SSH 客户端,并可以从http://www.ssh.com/获得商业SSH客户端ã€�

你还可以使用MySQL内部OpenSSL支持。参è§�5.8.7节,“使用安全连接â€�ã€�

为了ä½�MySQL系统安全,强烈要求你考虑下列建议ï¼�

·         对所æœ�MySQL用户使用密码。客户端程序不需要知道运行它的人员的身份。对于客户端/服务器应用程序,用户可以指定客户端程序的用户名。例如,如果other_user没有密码,任何人可以简单地ç”�mysql -u other_user db_name冒充他人调用mysql程序进行连接。如果所有用户有密码,使用其它用户的账户进行连接要困难得多ã€�

要想更改用户的密码,应使ç”�SET PASSWORD语句。还可以直接更新mysql数据库中çš�user表。例如,要更改所æœ�root用户çš�MySQL账户的密码,应:

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

·         绝对不要作为Unixçš�root用户运行MySQL服务器。这样做非常危险,因为任何具æœ�FILE权限的用户能够用root创建文件(例如ï¼�~root/.bashrc)。为了防止,mysqld拒绝ç”�root运行,除非使ç”�--user=root选项明显指定ã€�

应可ä»�(并且应该)用普通非特权用户运行mysqld。你可以创建独立çš�Unix中的mysql账户来以便使所有内容更加安全。该账户只用于管ç��MySQL。要想用其它Unix用户启动mysqld,增åŠ�user选项指定/etc/my.cnf选项文件或服务器数据目录çš�my.cnf选项文件中的[mysqld]组的用户名。例如:

[mysqld]
user=mysql

该命令使服务器用指定的用户来启动,无论你手动启动或通过mysqld_safeæˆ�mysql.server启动。详细信息参è§�A.3.2节,“如何以普通用户身份运行MySQLâ€�ã€�

作为其它Unix用户而不ç”�root运行mysqld,你不需要更æ”�user表中çš�root用户名,因为MySQL账户的用户名ä¸�Unix账户的用户名无关ã€�

·         不要允许使用表的符号链接ã€�(可以ç”�--skip-symbolic-links选项禁用ï¼�ã€�如果你用root运行mysqld则特别重要,因为任何对服务器的数据目录有写访问权限的人则能够删除系统中的任何文件!参è§�7.6.1.2节,“在Unix平台上使用表的符号链æŽ�”ã€�

·         确保mysqld运行时,只使用对数据库目录具有读或写权限çš�Unix用户来运行ã€�

·         不要å°�PROCESSæˆ�SUPER权限授给非管理用户ã€�mysqladmin processlist的输出显示出当前执行的查询正文,如果另外的用户发出一ä¸�UPDATE user SET password=PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到ã€�

mysqld为有SUPER权限的用户专门保留一个额外的连接,因此即使所有普通连接被占用ï¼�MySQL root用户仍可以登录并检查服务器的活动ã€�

可以使用SUPER权限来终止客户端连接,通过更改系统变量的值更改服务的器操作,并控制复制服务器ã€�

·         不要向非管理用户授予FILE权限。有这权限的任何用户能在拥有mysqld守护进程权限的文件系统那里写一个文件!为了更加安全,由SELECT ... INTO OUTFILE生成的所有文件对每个人是可写的,并且你不能覆盖已经存在的文件ã€�

file权限也可以被用来读取任何作为运行服务器的Unix用户可读取或访问的文件。使用该权限,你可以将任何文件读入数据库表。这可能被滥用,例如,通过使用LOAD DATA装载â€�/etc/passwdâ€�进一个数据库表,然后能用SELECT显示å®�ã€�

·         如果你不信任你的DNS,你应该在授权表中使ç”�IP数字而不是主机名。在任何情况下,你应该非常小心地使用包含通配符的主机名来创建 授权表条目!

·         如果你想要限制单个账户允许的连接数量,你可以设置mysqld中的max_user_connections变量来完成ã€�GRANT语句也可以支æŒ� 资源控制选项来限制服务器对一个账户允许的使用范围。参è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

5.6.3. Mysqld安全相关启动选项

下列mysqld选项影响安全ï¼�

·         --allow-suspicious-udfs

该选项控制是否可以载入主函数只æœ�xxx符的用户定义函数。默认情况下,该选项被关闭,并且只能载入至少有辅助符çš�UDF。这样可以防止从未包含合æ³�UDF的共享对象文件载入函数。参è§�27.2.3.6节,“用户定义函数安全注意事项â€�ã€�

·         --local-infile[={0|1}]

如果ç”�--local-infile=0启动服务å™�ï¼�则客户端不能使用LOCAL in LOAD DATA语句。参è§�5.6.4节,“LOAD DATA LOCAL安全问题â€�ã€�

·         --old-passwords

强制服务器为新密码生成短(pre-4.1)密码哈希。当服务器必须支持旧版本客户端程序时,为了保证兼容性这很有用。参è§�5.7.9节,“MySQL 4.1中的密码哈希处理â€�ã€�

·         (OBSOLETE) --safe-show-database

在以前版本的MySQL中,该选项ä½�SHOW DATABASES语句只显示用户具有部分权限的数据库名。在MySQL 5.1中,该选项不再作为现在çš� 默认行为使用,有一ä¸�SHOW DATABASES权限可以用来控制每个账户对数据库名的访问。参è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

·         --safe-user-create

如果启用,用户不能用GRANT语句创建新用户,除非用户æœ�mysql.user表的INSERT权限。如果你想让用户具有授权权限来创建新用户,你应给用户授予下面的权限:

mysql> GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name';

这样确保用户不能直接更改权限列,必须使用GRANT语句给其它用户授予该权限ã€�

·         --secure-auth

不允许鉴定有æ—�(pre-4.1)密码的账户ã€�

·         --skip-grant-tables

这个选项导致服务器根本不使用权限系统。这给每个人ä»�完全访问所有的数据库的权力!(通过执行mysqladmin flush-privilegesæˆ�mysqladmin reload命令,或执行FLUSH PRIVILEGES语句,你能告诉一个正在运行的服务器再次开始使用授权表。)  

·         --skip-name-resolve

主机名不被解析。所有在授权表的Host的列值必须是IP号或localhostã€�

·         --skip-networking

在网络上不允è®�TCP/IP连接。所有到mysqld的连接必须经ç”�Unix套接字进行ã€�

·         --skip-show-database

使用该选项,只允许æœ�SHOW DATABASES权限的用户执è¡�SHOW DATABASES语句,该语句显示所有数据库名。不使用该选项,允许所有用户执è¡�SHOW DATABASES,但只显示用户有SHOW DATABASES权限或部分数据库权限的数据库名。请注意全局权限指数据库的权限ã€�

5.6.4. LOAD DATA LOCAL安全问题

LOAD DATA语句可以装载服务器主机上的文件,若指å®�LOCAL关键字,可以装载客户端文件ã€�

支持LOCAL版本çš�LOAD DATA语句有两个可能的安全问题ï¼�

·         ç”�MySQL服务器启动文件从客户端向服务器主机的传输。理论上,打过补丁的服务器可以告诉客户端程序传输服务器选择的文件,而不是客户用LOAD DATA语句指定的文件。这样服务器可以访问客户端上客户有读访问权限的任何文件ã€�

·         åœ�Web环境中,客户ä»�Web服务器连接,用户可以使用LOAD DATA LOCAL来读å��Web服务器进程有读访问权限的任何文件(假定用户可以运行SQL服务器的任何命令)。在这种环境中,MySQL服务器的客户实际上是Web服务器,而不是连æŽ�Web服务器的用户运行的程序ã€�

要处理这些问题,我们更改äº�MySQL 3.23.49å’�MySQL 4.0.2(Windows中的4.0.13)中的LOAD DATA LOCAL的处理方法:

·         默认情况下,现在所有二进制分中的发MySQL客户端和库是ç”�--enable-local-infile选项编译,以便与MySQL 3.23.48和以前的版本兼容ã€�

·         如果你从源码构建MySQL但没有使ç”�--enable-local-infile选项来进è¡�configure,则客户不能使用LOAD DATA LOCAL,除非显式调ç”�mysql_options (...MYSQL_OPT_本地_INFILEï¼�0)。参è§�25.2.3.48节,“mysql_options()â€�ã€�

·         你可以用--local-infile=0选项启动mysqld从服务器端禁用所æœ�LOAD DATA LOCAL命令ã€�

·         对于mysql命令行客户端,可以通过指定--local-infile[=1]选项启用LOAD DATA LOCAL,或通过--local-infile=0选项禁用。类似地,对äº�mysqlimportï¼�--local or -L选项启用本地数据文件装载。在任何情况下,成功进行本地装载需要服务器启用相关选项ã€�

·         如果你使ç”�LOAD DATA LOCAL Perl脚本或其它读选项文件中的[client]组的程序,你可以在组内添åŠ�local-infile=1选项。但是,为了便面不理è§�local-infile的程序产生问题,则规定使ç”�loose- prefixï¼�

·                [client]
·                loose-local-infile=1

·         如果LOAD DATA LOCAL INFILE在服务器或客户端被禁用,试图执行该语句的客户端将收到下面的错误消息:

ERROR 1148: The used command is not allowed with this MySQL version

5.7. MySQL访问权限系统

MySQL有先进但非标准的安全/权限系统。本节描述它的工作原理ã€�

5.7.1. 权限系统的作ç”�

MySQL权限系统的主要功能是证实连接到一台给定主机的用户,并且赋予该用户在数据库上的SELECTã€�INSERTã€�UPDATEå’�DELETE权限ã€�

附加的功能包括有匿名的用户并对于MySQL特定的功能例å¦�LOAD DATA INFILE进行授权及管理操作的能力ã€�

5.7.2. 权限系统工作原理

MySQL权限系统保证所有的用户只执行允许做的事情。当你连æŽ�MySQL服务器时,你的身份由你从那儿连接的主æœ�å’�你指定的用户å��来决定。连接后发出请求后,系统根据你的身份å’�你想做什ä¹�来授予权限ã€�

MySQL在认定身份中考虑你的主机名和用户名字,是因为几乎没有原因假定一个给定的用户在因特网上属于同一个人。例如,ä»�office.com连接的用æˆ�joe不一定和ä»�elsewhere.com连接çš�joe是同一个人ã€�MySQL通过允许你区分在不同的主机上碰巧有同样名字的用户来处理它:你可以å¯�joeä»�office.com进行的连接授与一个权限集,而为joeä»�elsewhere.com的连接授予一个不同的权限集ã€�

MySQL存取控制包含2个阶段:

  • 阶段1:服务器检查是否允许你连接ã€�
  • 阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够的权限实施它。例如,如果你从数据库表中选择(select)行或从数据库删除表,服务器确定你对表æœ�SELECT权限或对数据库有DROP权限ã€�

如果连接时你的权限被更改äº�(通过你和其它äº�),这些更改不一定立即对你发出的下一个语句生效。详情参è§�5.7.7节,“权限更改何时生效â€�ã€�

服务器在mysql数据库的 授权表中保存权限信息(即在mysql数据库中)。当MySQL服务器启动时将这些表的内容读入内存,åœ�5.7.7节,“权限更改何时生效â€�的环境下重新读取它们。访问控制决策取决于内存中的 授权表的份数ã€�

一般情况,你通过GRANTå’�REVOKE语句间接来操ä½� 授权表的内容,设置账户并控制个人的权限。参è§�13.5.1.3节,“GRANT和REVOKE语法â€�。下面讨论了 授权表的结构以及服务器与客户端交互操作时如何使用其内容ã€�

服务器在存取控制的两个阶段使ç”�mysql数据库中çš�userã€�dbå’�host表,这些授权表中的列如下ï¼�

表名

user

db

host

列范å›�

Host

Host

Host

 

User

Db

Db

 

Password

User

 

权限åˆ�

Select_priv

Select_priv

Select_priv

 

Insert_priv

Insert_priv

Insert_priv

 

Update_priv

Update_priv

Update_priv

 

Delete_priv

Delete_priv

Delete_priv

 

Index_priv

Index_priv

Index_priv

 

Alter_priv

Alter_priv

Alter_priv

 

Create_priv

Create_priv

Create_priv

 

Drop_priv

Drop_priv

Drop_priv

 

Grant_priv

Grant_priv

Grant_priv

 

Create_view_priv

Create_view_priv

Create_view_priv

 

Show_view_priv

Show_view_priv

Show_view_priv

 

Create_routine_priv

Create_routine_priv

 

 

Alter_routine_priv

Alter_routine_priv

 

 

References_priv

References_priv

References_priv

 

Reload_priv

 

 

 

Shutdown_priv

 

 

 

Process_priv

 

 

 

File_priv

 

 

 

Show_db_priv

 

 

 

Super_priv

 

 

 

Create_tmp_table_priv

Create_tmp_table_priv

Create_tmp_table_priv

 

Lock_tables_priv

Lock_tables_priv

Lock_tables_priv

 

Execute_priv

 

 

 

Repl_slave_priv

 

 

 

Repl_client_priv

 

 

安全åˆ�

ssl_type

 

 

 

ssl_cipher

 

 

 

x509_issuer

 

 

 

x509_subject

 

 

资源控制åˆ�

max_questions

 

 

 

max_updates

 

 

 

max_connections

 

 

 

max_user_connections

 

 

对存取控制的第二阶段(请求证实),服务器执行请求验证以确保每个客户端有充分的权限满足各需求。除äº�userã€�dbå’�host授权表,如果请求涉及表,服务器可以另外参è€�tables_privå’�columns_priv表ã€�tables_privå’�columns_priv表可以对表和列提供更精确的权限控制。这些表的列如下ï¼�

表名

tables_priv

columns_priv

范围åˆ�

Host

Host

 

Db

Db

 

User

User

 

Table_name

Table_name

 

 

Column_name

权限åˆ�

Table_priv

Column_priv

 

Column_priv

 

其它åˆ�

Timestamp

Timestamp

 

Grantor

 

Timestampå’�Grantor列当前还未使用,这儿不再进一步讨论ã€�

为了对涉及保存程序的请求进行验证,服务器将查é˜�procs_priv表。该表具有以下列ï¼�

表名

procs_priv

范围åˆ�

Host

 

Db

 

User

 

Routine_name

 

Routine_type

权限åˆ�

Proc_priv

其它åˆ�

Timestamp

 

Grantor

Routine_type列为ENUM列,值为'FUNCTION'æˆ�'PROCEDURE',表示行所指的程序类型。该列允许为同名函数和程序单独授权ã€�

Timestampå’�Grantor列当前还未使用,这儿不再进一步讨论ã€�

每个授权表包含范围列和权限列ï¼�

l        范围列决定表中每个条目(行)的范围,即,行适用的上下文。例å¦�, 一ä¸�user表行çš�Hostå’�User值为'thomas.loc.gov'å’�'bob'ï¼�将被用于证实来自主机thomas.loc.govçš�bob对服务器的连接。同样,一ä¸�db表行çš�Hostã€�Userå’�Db列的值是'thomas.loc.gov'ã€�'bob'å’�'reports'将用åœ�bob从主æœ�thomas.loc.gov联接访问reports数据库的时候ã€�tables_privå’�columns_priv表包含范围列,指出每个行适用的表或表/列的组合ã€�procs_priv范围列指出每个行适用的保存程序ã€�

对于检查存取的用途,比较Host值是忽略大小写的ã€�Userã€�Passwordã€�Dbå’�Table_name值是区分大小写的ã€�Column_name值在MySQL3.22.12或以后版本是忽略大小写的ã€�

l        权限列指出由一个表行授予的权限,即,可实施什么操作。服务器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规则åœ�5.7.6节,“访问控åˆ�, 阶段2:请求核实â€�描述ã€�

范围列包含字符串,如下所述;每个列的默认值是空字符串ï¼�

列名

类型

Host

CHAR(60)

User

CHAR(16)

Password

CHAR(16)

Db

CHAR(64)

Table_name

CHAR(64)

Column_name

CHAR(64)

Routine_name

CHAR(64)

为了访问检查目的,Host值的比较对大小写不敏感ã€�Userã€�Passwordã€�Dbå’�Table_name值对大小写敏感ã€�Column_name值对大小写不敏感ã€�

åœ�userã€�dbå’�host表中,所有权限列于单独的列内,被声明ä¸�ENUM('N','Y') DEFAULT 'N'ã€�换句话说ï¼�每一个权限都可以被禁用和启用,并ä¸� 默认是禁ç”�ã€�

åœ�tables_privã€�columns_privå’�procs_priv表中,权限列被声明为SET列。这些列的值可以包含该表控制的权限的组合:

表名

列名

可能的设置元ç´�

tables_priv

Table_priv

'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'

tables_priv

Column_priv

'Select', 'Insert', 'Update', 'References'

columns_priv

Column_priv

'Select', 'Insert', 'Update', 'References'

procs_priv

Proc_priv

'Execute', 'Alter Routine', 'Grant'

简单地说,服务器使用这样的授权表:

·         user表范围列决定是否允许或拒绝到来的连接。对于允许的连接ï¼�user表授予的权限指出用户的全局(超级用户)权限。这些权限适用于服务器上的all数据库ã€�

·         db表范围列决定用户能从哪个主机存取哪个数据库。权限列决定允许哪个操作。授予的数据库级别的权限适用于数据库和它的表ã€�

·         当你想要一个给定的db表行应用于若干主机时ï¼�dbå’�host表一起使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个数据库,在用户çš�db表行çš�Host值设为空值,然后将那些主机的每一个移å…�host表。这个机制详细描述在5.7.6节,“访问控åˆ�, 阶段2:请求核实â€�ã€�

æ³�释:host表不å��GRANTå’�REVOKE语句的影响。大多数MySQL安装根本不需要使用该表ã€�

·         tables_privå’�columns_priv表类似于db表,但是更精致:它们在表和列级应用而非在数据库级。授予表级别的权限适用于表和所有它的列。授予列级别的权限只适用于专用列ã€�

·         procs_priv表适用于保存的程序。授予程序级别的权限只适用于单个程序ã€�

管理权限(例如RELOADæˆ�SHUTDOWN等等)仅在user表中被指定。这是因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由在其他授权表中列出这样的权限。事实上,只需要查è¯�user表来决定你是否执行一个管理操作ã€�

FILE权限也仅åœ�user表中指定。它不是管理性权限,但你在服务器主机上读或写文件的能力与你正在存取的数据库无关ã€�

å½�mysqld服务器启动时,将授权表的内容读入到内存中。你可以通过FLUSH PRIVILEGES语句或执è¡�mysqladmin flush-privilegesæˆ�mysqladmin reload命令让它重新读取表。对授权表的更改生效åœ�5.7.7节,“权限更改何时生效â€�描述ã€�

当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一个好主意。要检查给定账户的权限,使ç”�SHOW GRANTS语句。例如,要检æŸ�Hostå’�User值分别为pc84.example.comå’�bob的账户所授予的权限,应通过语句ï¼�

 

mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com';

一个有用的诊断工具æ˜�mysqlaccess脚本,由Carlier Yves 提供ç»�MySQL分发。使ç”�--help选项调用mysqlaccess查明它怎样工作。注意:mysqlaccess仅用userã€�dbå’�host表检查存取。它不检æŸ�tables_privã€�columns_privæˆ�procs_priv表中指定的表、列和程序级权限ã€�

对于诊断权限相关的问题的其它帮助,参è§�5.7.8节,“拒绝访问错误的原因â€�。对于安全问题常规建议,参见5.6节,“一般安全问题â€�ã€�

5.7.3. MySQL提供的权é™�

账户权限信息被存储在mysql数据库的userã€�dbã€�hostã€�tables_privã€�columns_privå’�procs_priv表中。在MySQL启动时并åœ�5.7.7节,“权限更改何时生效â€�所说的情况时,服务器将这些数据库表内容读入内存ã€�

GRANTå’�REVOKE语句所用的涉及权限的名称显示在下表,还有在授权表中每个权限的表列名称和每个权限有关的上下文。关于每个权限的含义相关的详细信息参è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

权限

�

上下æ–�

CREATE

Create_priv

数据库、表或索å¼�

DROP

Drop_priv

数据库或è¡�

GRANT OPTION

Grant_priv

数据库、表或保存的程序

REFERENCES

References_priv

数据库或è¡�

ALTER

Alter_priv

�

DELETE

Delete_priv

�

INDEX

Index_priv

�

INSERT

Insert_priv

�

SELECT

Select_priv

�

UPDATE

Update_priv

�

CREATE VIEW

Create_view_priv

视图

SHOW VIEW

Show_view_priv

视图

ALTER ROUTINE

Alter_routine_priv

保存的程åº�

CREATE ROUTINE

Create_routine_priv

保存的程åº�

EXECUTE

Execute_priv

保存的程åº�

FILE

File_priv

服务器主机上的文件访é—�

CREATE TEMPORARY TABLES

Create_tmp_table_priv

服务器管ç��

LOCK TABLES

Lock_tables_priv

服务器管ç��

CREATE USER

Create_user_priv

服务器管ç��

PROCESS

Process_priv

服务器管ç��

RELOAD

Reload_priv

服务器管ç��

REPLICATION CLIENT

Repl_client_priv

服务器管ç��

REPLICATION SLAVE

Repl_slave_priv

服务器管ç��

SHOW DATABASES

Show_db_priv

服务器管ç��

SHUTDOWN

Shutdown_priv

服务器管ç��

SUPER

Super_priv

服务器管ç��

当从早期的没æœ�CREATE VIEWã€�SHOW VIEWã€�CREATE ROUTINEã€�ALTER ROUTINEå’�EXECUTE权限的版本的MySQL中升级时,要想使用这些权限,你必须使ç”�MySQL分发提供çš�mysql_fix_privilege_tables脚本升级 授权表。参è§�2.10.2节,“升级授权表â€�ã€�

如果启用了二进制记录,要想创建或修改保存的程序,你还需è¦�SUPER权限,详细描述见20.4节,“存储子程序和触发程序的二进制日志功能â€�ã€�

通过CREATEå’�DROP权限,你可以创建新数据库和表,或删除(移掉)已有数据库和表ã€�如果你将mysql数据库中çš�DROP权限授予某用户,用户可以删掉MySQL访问权限保存的数据库ã€�

SELECTã€�INSERTã€�UPDATEå’�DELETE权限允许你在一个数据库现有的表上实施操作ã€�

SELECT语句只有在他们真正从一个表中检索行时才需è¦�SELECT权限。一äº�SELECT语句不访问表,甚至没有任何到服务器上的数据库里的存取任何东西的许可。例如,你可使用mysql客户端作为一个简单的计算器来评估未引用表的表达式ï¼�

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

INDEX权限允许你创建或删除索引ã€�INDEX适用已有è¡�ã€�如果你具有某个表çš�CREATE权限,你可以åœ�CREATE TABLE语句中包括索引定义ã€�

通过ALTER权限,你可以使用ALTER TABLE来更改表的结构和重新命名è¡�ã€�

需è¦�CREATE ROUTINE权限来创建保存的程序(函数和程序),ALTER ROUTINE权限来更改和删除保存的程序,EXECUTE来执行保存的程序ã€�

GRANT权限允许你把你自己拥有的那些权限授给其他的用户。可以用于数据库、表和保存的程序ã€�

FILE权限给予你用LOAD DATA INFILEå’�SELECT ... INTO OUTFILE语句读和写服务器上的文件,任何被授予FILE权限的用户都能读或写MySQL服务器能读或写的任何文件ã€�(说明用户可以读任何数据库目录下的文件,因为服务器可以访问这些文件ï¼�ã€� FILE权限允许用户åœ�MySQL服务器具有写权限的目录下创建新文件。不能覆盖已有文件ã€�

其余的权限用于管理性操作,它使ç”�mysqladmin程序æˆ�SQL语句实施。下表显示每个管理性权限允许你执行çš�mysqladmin命令ï¼�

权限

权限拥有者允许执行的命令

RELOAD

flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload

SHUTDOWN

shutdown

PROCESS

processlist

SUPER

kill

reload命令告诉服务器将授权表重新读入内存ã€�flush-privilegesæ˜�reload的同义词ï¼�refresh命令清空所有表并打开并关闭记录文件,其它flush-xxx命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更好用。例如,如果你只是想清空记录文件ï¼�flush-logsæ¯�refresh是更好的选择ã€�

shutdown命令关掉服务器。只能从mysqladmin发出命令。没有相应的SQL语句ã€�

processlist命令显示在服务器内执行的线程的信息(即其它账户相关的客户端执行的语句)ã€�kill命令杀死服务器线程。你总是能显示或杀死你自己的线程,但是你需è¦�PROCESS权限来显示或杀死其他用户和SUPER权限启动的线程ã€�参见13.5.5.3节,“KILL语法â€�ã€�

拥有CREATE TEMPORARY TABLES权限便可以使ç”�CREATE TABLE语句中的关键å­�TEMPORARYã€�

拥有LOCK TABLES权限便可以直接使ç”�LOCK TABLES语句来锁定你拥有SELECT权限的表。包括使用写锁定,可以防止他人读锁定的表ã€�

拥有REPLICATION CLIENT权限便可以使ç”�SHOW MASTER STATUSå’�SHOW SLAVE STATUSã€�

REPLICATION SLAVE权限应授予从服务器所使用的将当前服务器连接为主服务器的账æˆ�。没有这个权限,从服务器不能发出对主服务器上的数据库所发出的更新请求ã€�

拥有SHOW DATABASES权限便允许账户使ç”�SHOW DATABASE语句来查看数据库名。没有该权限的账户只能看到他们具有部分权限的数据库, 如果数据库用--skip-show-database选项启动,则根本不能使用这些语句。请注意全局权限指数据库的权限ã€�

总的说来,只授予权限给需要他们的那些用户是好主意,但是你应该在授äº�FILE和管理权限时试验特定的警告:

  • FILE权限可以被滥用于将服务器主机ä¸�MySQL能读取的任何文件读入到数据库表中。包括任何人可读的文件和服务器数据目录中的文件。可以使ç”�SELECT访问数据库表,然后将其内容传输到客户端上ã€�
  • GRANT权限允许用户将他们的权限给其他用户。有不同的权限并æœ�GRANT权限çš�2个用户可以合并权限ã€�
  • ALTER权限可以用于通过重新命名表来推翻权限系统ã€�
  • SHUTDOWN权限通过终止服务器可以被滥用完全拒绝为其他用户服务ã€�
  • PROCESS权限能被用来察看当前执行的查询的明文文本,包括设定或改变密码的查诀€�
  • SUPER权限能用来终止其它用户或更改服务器的操作方式ã€�
  • 授给mysql数据库本身的权限能用来改变密码和其他访问权限信息。密码被加密存储,所以恶意的用户不能简单地读取他们以知道明文密码。然而,具有userè¡�Password列写访问权限的用户可以更改账户的密码,并可以用该账户连接MySQL服务器ã€�

有一些事情你不能ç”�MySQL权限系统做到ï¼�

  • 你不能明显地指定某个给定的用户应该被拒绝访问。即,你不能明显地匹配用户然后拒绝连接ã€�
  • 你不能指定用户有权创建立或删除数据库中的表,但不能创建或删除数据库本身ã€�

5.7.4. 与MySQL服务器连æŽ�

当你想要访问MySQL服务器时ï¼�MySQL客户端程序一般要求你指定参数ï¼�

·         MySQL服务器运行的主机å��

·         姓名

·         密码

例如,可以从命令行按照下述提示启åŠ�MySQL客户ç«�(ç”�shell>表示)ï¼�

shell> MySQL -h host_name -u user_name -pyour_pass

-h, -uå’�-p选项还可以采用形å¼�--host=host_nameã€�--user=user_nameå’�--password=your_pass。请注意åœ�-pæˆ�--password=和后面的密码之间没有空格ã€�

如果你使ç”�-pæˆ�--password选项但没有指定密码值,客户端程序提示你输入密码。当你输入密码时并不显示密码。这比在在命令行输入密码要安全得多。系统上的任何用户可以通过命令ps auxww在命令行中指定密码。参è§�5.8.6节,“使你的密码安全â€�ã€�

如果没有指定连接参数ï¼�MySQL客户端程序使用默认值:

  • 默认主机名是localhostã€�
  • 默认用户名在Windows中是ODBC,在Unix中是你的Unix登录名ã€�

·         如果没有-p,则不提供密码ã€�

这样, å¯�Unix用户joe,下列命令是等价的:

shell> MySQL -h localhost -u joe
shell> MySQL -h localhost
shell> MySQL -u joe
shell> MySQL

其它MySQL客户端程序类似ã€�

当进行连接时,你可以指定要使用的不同的默认值,这样不必每次在你调用客户端程序是在命令行上输入它们。这可以有很多方法做到:

  • 你可以在选项文件çš�[client]小节里指定连接参数。文件的相关小节看上去可能像这样ï¼�
·                [client]
·                host=host_name
·                user=user_name
·                password=your_pass

åœ�4.3.2节,“使用选项文件â€�中详细讨论了选项文件ã€�

5.7.5. 访问控制, 阶段1:连接核å®�

当你试图连接MySQL服务器时,服务器基于你的身份以及你是否能通过供应正确的密码验证身份来接受或拒绝连接。如果不是,服务器完全拒绝你的访问,否则,服务器接受连接,然后进入阶æ®�2并且等待请求ã€�

你的身份基于2个信息:

  • 你从那个主机连接
  • 你的MySQL用户å��

身份检查使ç”�3ä¸�userè¡�(Host, Userå’�Password)范围列执行。服务器只有åœ�user表记录的Hostå’�User列匹配客户端主机名和用户名并且提供了正确的密码时才接受连接ã€�

åœ�userè¡�Host值的指定方法ï¼�

  • Host值可以是主机名或IP号,æˆ�'localhost'指出本地主机ã€�
  • 你可以在Host列值使用通配符字ç¬�â€�%â€�å’�â€�_â€�ã€�
  • Hostå€�'%'匹配任何主机名,ç©�Host值等价于'%'。它们的含义ä¸�LIKE操作符的模式匹配操作相同。例如,'%'çš�Host值与所有主机名匹配,è€�'%.mysql.com'匹配mysql.com域的所有主机ã€�

·         对于指定ä¸�IP号的Host值,你可以指定一个网络掩码,说明使用多少位地址位来评比网络号。例如:

·                mysql> GRANT ALL PRIVILEGES ON db.*
·                    -> -> TO david@'192.58.197.0/255.255.255.0';

允许david从任何客户端ç”�IPå��client_ip来连接,下面的条件为真:

client_ip & netmask = host_ip

That is, for the GRANT statement just shown:

client_ip & 255.255.255.0 = 192.58.197.0

满足该条件并可以连接MySQL服务器的IP号的范围ä¸�192.58.197.0åˆ�192.58.197.255ã€�

·         注释:网络掩码只用来告诉服务器使ç”�8ã€�16ã€�24æˆ�32位地址,例如:

·                192.0.0.0/255.0.0.0(192 A类网络的任何地址)
·                192.168.0.0/255.255.0.0(192.168 A类网络的任何地址)
·                192.168.1.0/255.255.255.0(192.168.1 C类网络的任何地址)
·                192.168.1.1(只有è¯�IP)

下面的网络掩ç �(28 ä½�)无效ï¼�

192.168.0.1/255.255.255.240

·         db表记录中的空Host值表示它的权限应结合匹配客户端名çš�host表中的行使用。通过AND(相与)而不是或(联合)操作将权限组合到一起。你可以ä»�5.7.6节,“访问控åˆ�, 阶段2:请求核实â€�找到关于host表的详细信息ã€�

其它grant表的ç©�Host值与'%'相同ã€�

既然你能åœ�Host字段使用IP通配符å€�(例如ï¼�'144.155.166.%'匹配在一个子网上的每台主æœ�),有可能某人可能企图探究这种能力,通过命名一台主机为144.155.166.somewhere.com。为了阻止这样的企图ï¼�MySQL不允许匹配以数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的主机,它的名字决不会匹配授权表中的Host列。只有一ä¸�IP数字能匹é…�IP通配符值ã€�

通配符字符在User列中不允许,但是你能指定空的值,它匹配任何名字。如æž�user表匹配的连接有一个空用户名,用户被认为是匿名用户(没有名字的用æˆ�),而非客户端实际指定的名字。这意味着一个空的用户名被用于在连接期间的进一步的访问检æŸ�(即,在阶æ®�2期间)ã€�

Password列可以是空的。这不是通配符,也不意味着匹配任何密码,它意味着用户必须不指定一个密码进行连接ã€�

user表中çš�非空Password值代表加密的密码ã€�MySQL不以任何人可以看的明文文本格式存储密码,相反,正在试图联接的用户提供的密码被加密(使用PASSWORD( )函数),在连接过程中使用加密的密码检查密码是否正确ã€�(加密后的密码未通过连接即可实现ï¼�ã€�ä»�MySQL角度,加密的密码是实际密码,因此你不应让其它人访问它!特别是,绝对不要让非管理用户读mysql数据库中的表ï¼�

MySQL 5.1使用强鉴定方æ³�(最先在MySQL 4.1中适用)在前面的版本中在连接进程中的密码保护较好。即ä½�TCP/IP包被截取æˆ�mysql数据åº� 被捕获也很安全ã€�5.7.9节,“MySQL 4.1中的密码哈希处理â€�中详细讨论了密码加密ã€�

下面的例子显示出各种user表中Hostå’�User值的组合如何应用于到来的连接ï¼�

Host�

User�

被条目匹配的连接

'thomas.loc.gov'

'fred'

fred, ä»�thomas.loc.gov 连接

'thomas.loc.gov'

''

任何用户, ä»�thomas.loc.gov连接

'%'

'fred'

fred, 从任何主机连æŽ�

'%'

''

任何用户, 从任何主机连æŽ�

'%.loc.gov'

'fred'

fred, 从在loc.gov域的任何主机连接

'x.y.%'

'fred'

fred, ä»�x.y.netã€�x.y.com,x.y.edu等联接。(这或许无用)

'144.155.166.177'

'fred'

fred, 从有144.155.166.177 IP地址的主机连æŽ�

'144.155.166.%'

'fred'

fred, ä»�144.155.166 C类子网的任何主机连接

到来的连接中的客户端名和用户名可能与user表中的多行匹配。例如,ç”�fredä»�thomas.loc.gov的连接匹配多个条目如上所述ã€�

如果有多个匹配,服务器必须选择使用哪个条目。按照下述方法解决问题:

l        服务器在启动时读å…�user表后进行排序ã€�

l        然后当用户试图连接时,以排序的顺序浏览条ç›�

l        服务器使用与客户端和用户名匹配的第一行ã€�

user表排序工作如下,假定user表看起来像这样:

+-----------+----------+-
| Host      | User     | â€�
+-----------+----------+-
| %         | root     | â€�
| %         | jeffrey  | â€�
| localhost | root     | â€�
| localhost |          | â€�
+-----------+----------+-

当服务器读取表时,它首先以最具体çš�Host值排序。主机名å’�IP号是最具体的ã€�'%'意味着“任何主机”并且是最不特定的。有相同Host值的条目首先以最具体çš�User值排åº�(ç©�User值意味着“任何用户”并且是最不特定的)。最终排序的user表看起来像这样:

+-----------+----------+-
| Host      | User     | â€�
+-----------+----------+-
| localhost | root     | â€� ...
| localhost |          | â€� ...
| %         | jeffrey  | â€� ...
| %         | root     | â€� ...
+-----------+----------+-

当客户端试图连接时,服务器浏览排序的条目并使用找到的第一匹配。对于由jeffreyä»�localhost的连接,表内有两个条目匹配:Hostå’�User值为'localhost'å’�''的条目,和值为'%'å’�'jeffrey'的条目ã€�'localhost'条目首先匹配,服务器可以使用ã€�

还有一个例子。假å®�user表看起来像这样:

+----------------+----------+-
| Host           | User     | â€�
+----------------+----------+-
| %              | jeffrey  | â€�
| thomas.loc.gov |          | â€�
+----------------+----------+-

排序后的表看起来像这样:

+----------------+----------+-
| Host           | User     | â€�
+----------------+----------+-
| thomas.loc.gov |          | â€�
| %              | jeffrey  | â€�
+----------------+----------+-

ç”�jeffreyä»�thomas.loc.gov的连接与第一行匹配,而由jeffreyä»�whitehouse.gov的连接被第二个匹配ã€�

普遍的误解是认为,对给定的用户名,当服务器试图对连接寻找匹配时,明确命名那个用户的所有条目将首先被使用。这明显不符合事实。先前的例子说明了这点,在那里由jeffreyä»�thomas.loc.gov的连接没被包å��'jeffrey'作为User列值的行匹配,但是由没有用户名的题目匹配!结果是,jeffrey被鉴定为匿名用户,即使他连接时指定了用户名ã€�

如果你能够连接服务器,但你的权限不是你期望的,你可能被鉴定为其它账户。要想找出服务器用来鉴定你的账户,使ç”�CURRENT_USER()函数。它返回user_name@host_name格式的值,说明Userå’�Host 值匹é…�user表记录。假å®�jeffrey连接并发出下面的查询ï¼�

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost     |
+----------------+

这儿显示的结果说æ˜�user表行有空çš�User列值。换句话说,服务器将jeffrey视为匿名用户ã€�

诊断鉴定问题的另一个方法是打印å‡�user表并且手动排序它看看第一个匹配在哪儿进行。又è§�12.9.3节,“信息函数â€�ã€�

5.7.6. 访问控制, 阶段2:请求核å®�

一旦你建立了连接,服务器进入访问控制的阶段2。对在此连接上进来的每个请求,服务器检查你想执行什么操作,然后检查是否有足够的权限来执行它。这正是在授权表中的权限列发挥作用的地方。这些权限可以来è‡�userã€�dbã€�hostã€�tables_privæˆ�columns_priv表。(你会发现参è€�5.7.2节,“权限系统工作原理â€�很有帮助,它列出了每ä¸� 授权表中呈现的列。)

user表在全局基础上授予赋予你的权限,该权限不管当前的数据库是什么均适用。例如,如果user表授予你DELETE权限ï¼� 你可以删除在服务器主机上从任何数据库删除行!换句话说ï¼�user表权限是超级用户权限。只æŠ�user表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,你应该把在user表中的权限设æˆ�'N'并且仅在特定数据库的基础上授权。你可以为特定的数据库、表或列授权ã€�

dbå’�host表授予数据库特定的权限。在这些表中的范围列的值可以采用以下方式:

  • 通配符字ç¬�â€�%â€�å¹�â€�_â€�可用于两个表çš�Hostå’�Db列。它们与ç”�LIKE操作符执行的模式匹配操作具有相同的含义。如果授权时你想使用某个字符,必须使用反斜现引用。例如,要想在数据库名中包括下划çº�(â€�_â€�),在GRANT语句中用â€�\_â€�来指å®�ã€�
  • åœ�db表的'%'Host值意味着“任何主机”,åœ�db表中ç©�Host值意味着“对进一步的信息咨询host表”(本节后面将描述的一个过程)ã€�
  • åœ�host表的'%'或空Host值意味着“任何主机”ã€�
  • 在两个表中的'%'或空Db值意味着“任何数据库”ã€�
  • 在两个表中的ç©�User值匹配匿名用户ã€�

dbå’�host表在服务器启动时被读取并排序(同时它读userè¡�)ã€�db表在Hostã€�Dbå’�User范围列上排序,并ä¸�host表在Hostå’�Db范围列上排序。对äº�user表,首先根据最具体的值最后根据最不具体的值排序,并且当服务器寻找匹配条目时,它使用它找到的第一匹配ã€�

tables_privå’�columns_priv表授予表和列特定的权限。这些表的范围列的值可以如下被指定ï¼�

  • 通配ç¬�â€�%â€�å¹�â€�_â€�可用在使用在两个表的Host列ã€�
  • 在两个表中的'%'或空Host意味着“任何主机”ã€�
  • 在两个表中的Dbã€�Table_nameå’�Column_name列不能包含通配符或空ã€�

tables_privå’�columns_priv表根æ��Hostã€�Dbå’�User列被排序。这类似äº�db表的排序,因为只æœ�Host列可以包含通配符,排序更简单ã€�

请求证实进程在下面描述。(如果你熟悉访问检查的源码,你会注意到这里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;不同处只是使解释更简单。)

对需要管理权限的请求(SHUTDOWNã€�RELOAD等等),服务器仅检æŸ�user表条目,因为那是唯一指定管理权限的表。如果行许可请求的操作,访问被授权,否则拒绝。例如,如果你想要执è¡�mysqladmin shutdown,但是由äº�user表行没有为你授予HUTDOWN权限,甚至不用检æŸ�dbæˆ�host表就拒绝你的访问。(因为它们不包å��hutdown_priv行列,没有这样做的必要。)

对数据库有关的请æ±�(INSERTã€�UPDATE等等),服务器首先通过查找user表行来检查用户的全局(超级用户)权限。如果行允许请求的操作,访问被授权。如果在user表中全局权限不够,服务器通过检æŸ�dbå’�host表确定特定的用户数据库权限:

  1. 服务器在db表的Hostã€�Dbå’�User列上查找匹配ã€�Hostå’�User对应连接用户的主机名å’�MySQL用户名ã€�Db列对应用户想要访问的数据库。如果没æœ�Hostå’�User的行,访问被拒绝ã€�
  2. 如果db表中有匹配的行而且它的Host列不是空的,该行定义用户的数据库特定的权限ã€�
  3. 如果匹配çš�db表的行的Host列是空的,它表示host表列举被允许访问数据库的主机。在这种情况下,åœ�host表中作进一步查找以发现Hostå’�Db列上的匹配。如果没æœ�host表行匹配,访问被拒绝。如果有匹配,用户数据库特定的权限以åœ�dbå’�host表的行的权限,即在两个行都是'Y'的权限的交集(而不æ˜�并集ï¼�)计算。(这样你可以授予在db表行中的一般权限,然后ç”�host表行按主机主机为基础有选择地限制它们。)

在确定了ç”�dbå’�host表行授予的数据库特定的权限后,服务器把他们加到由user表授予的全局权限中。如果结果允许请求的操作,访问被授权。否则,服务器检查在tables_privå’�columns_priv表中的用户的表和列权限并把它们加到用户权限中。基于此结果允许或拒绝访问ã€�

用布尔术语表示,前面关于用户权限如何计算的描述可以这样总结ï¼�

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

它可能不明显,为什么呢,如果全局user行的权限最初发现对请求的操作不够,服务器以后把这些权限加到数据库、表并列的特定权限。原因是请求可能要求超过一种类型的权限。例如,如果你执è¡�INSERT INTO ... SELECT语句,你就需è¦�INSERTå’�SELECT权限。你的权限必须是user表行授予一个权限è€�db表行授予另一个权限。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把两个表区别开来;两个行授予的权限必须组合起来ã€�

host表不å��GRANTæˆ�REVOKE语句的影响,因此在大多数MySQL安装中没有使用。如果你直接修改它,你可以用于某种专门目的,例如用来维护安全服务器列表。例如,åœ�TcXï¼�host表包含在本地网络上所有的机器的表。这些表被授予所有的权限ã€�

你也可以使用host表指å®�ä¸�安全的主机。假定你有一台机å™�public.your.domain,它位于你认为不安全的公共区域,你可以用下列çš�host表条目允许除了那台机器外的网络上所有主机的访问ï¼�

+--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (all privileges set to 'N')
| %.your.domain      | %  | ... (all privileges set to 'Y')
+--------------------+----+-

当然,一定要测试授权表中的行(例如,使ç”�SHOW GRANTSæˆ�mysqlaccess),确保你的访问权限实际按你期望的方式被设置ã€�

5.7.7. 权限更改何时生效

å½�mysqld启动时,所有授权表的内容被读进内存并且从此时生效ã€�

当服务器注意到授权表被改变了时,现存的客户端连接有如下影响:

  • 表和列权限在客户端的下一次请求时生效ã€�
  • 数据库权限改变在下一ä¸�USE db_name命令生效ã€�

·         全局权限的改变和密码改变在下一次客户端连接时生效ã€�

如果ç”�GRANTã€�REVOKEæˆ�SET PASSWORD对授权表进行修改,服务器会注意到并立即重新将授权表载入内存ã€�

如果你手动地修改授权è¡�(使用INSERTã€�UPDATEæˆ�DELETE等等),你应该执行mysqladmin flush-privilegesæˆ�mysqladmin reload告诉服务器再装载授权表,否则你的更改å°�不会生效,除非你重启服务器ã€�

如果你直接更改了授权表但忘记重载,重启服务器后你的更改方生效。这样可能让你迷惑为什么你的更改没有什么变化!

5.7.8. 拒绝访问错误的原å›�

当你试着联接MySQL服务器时,如果碰到问题,下面各项可以帮助你纠正问题:

·         确保服务器在运行。如果服务器没有运行,则你不能连接服务器。如果你视图连接服务器并看到下述消息,可能是服务器没有运行:

·                shell> mysql
·                ERROR 2003: Can't connect to MySQL server on 'host_name' (111)
·                shell> mysql
·                ERROR 2002: Can't connect to local MySQL server through socket
·                '/tmp/mysql.sock' (111)

也可能服务器正在运行,但你可能使用与服务器上侦听的不一样的TCP/IP端口、命名管道或Unix套接字文件。你可以调用客户端程序,指定端口选项来指示正确的端口或套接字选项来指示正确的命名管道æˆ�Unix套接字文件。要找出套接字文件的地点,应ï¼�

shell> netstat -ln | grep mysql
  • 必须正确设置授权表,以便服务器可以使用它们进行访问控制。对于某些分发版类型(例如Windows中的二进制分发版æˆ�Linux中的RPM分发ç‰�),安装过程初始化包å�� 授权表的mysql数据库。如果分发版没有这样做,你必须运è¡�mysql_install_db脚本来手动初始化授权表。详细内容参è§�2.9.2节,“Unix下安装后的过程â€�ã€�

确定是否要初始化授权表的一个方法是寻找数据目录下的mysql目录ï¼�数据目录名通常ä¸�dataæˆ�var,位äº�MySQL安装目录ä¸�ï¼�。应保证MySQL数据库目录有文件â€�user.MYDâ€�。否则,执行mysql_install_db脚本。运行并重启服务器后,执行该命令来测试初始权限:

shell> mysql -u root test

服务器应该让你无误地连接ã€�

  • 在新的安装以后,你应该连接服务器并且设置你的用户及其访问许可ï¼�
·                shell> mysql -u root mysql

服务器应该让你连接,因为MySQL root用户初始时没有密码。那也是安全风险,当你正在设置其ä»�MySQL用户时,也应设定root密码是一件重要的事请。关于设置初始密码的说明,参è§�2.9.3节,“使初始MySQL账户安全â€�ã€�

  • 如果你将一个现存的MySQL安装升级到较新的版本,运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。增加新功能后,授权表的结构可能会改变,因此更新后应确保表的结构随之更新。相关说明参è§�2.10.2节,“升级授权表â€�ã€�

·         如果客户端程序试图连接时收到以下错误信息,说明服务器需要新格式的密码,而客户端不能生成ï¼�

·                shell> mysql
·                Client does not support authentication protocol requested
·                by server; consider upgrading MySQL client

关于如何处理的详细信息,参见5.7.9节,“MySQL 4.1中的密码哈希处理â€�å’�A.2.3节,“客户端不支持鉴定协议â€�ã€�

  • 如果你作ä¸�root试试连接并且得到这个错误,这意味着,你没有行在user表中çš�User列值为'root'并且mysqld不能为你的客户端解析主机名:
  • Access denied for user ''@'unknown' to database mysql

在这种情况下,你必须ç”�--skip-grant-tables选项重启服务器并且编è¾�â€�/etc/hostsâ€�æˆ�â€�\windows\hostsâ€�文件为你的主机增加行ã€�

  • 如果你从3.22.11以前的版本更新现存的MySQL安装åˆ�3.22.11版或以后版本,你运行äº�mysql_fix_privilege_tables脚本吗?如果没有,运行它。在GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 ã€�

·         记住客户端程序使用选项文件或环境变量中指定的连接参数。如果客户端程序发送不正确的默认连接参数,而你没有在命令行中指定,检查环境变量和适用的选项文件。例如,当你不用任何选项运行客户端程序,得到Access denied错误,确保你没有在选项文件中指定旧密码ï¼�

你可以通过使用--no-defaults选项调用客户端程序来禁用选项文件。例如:

shell> mysqladmin --no-defaults -u root version

客户端使用的选项文件è§�4.3.2节,“使用选项文件â€�。环境变量列äº�附录Fï¼�环境变量ã€�

·         如果遇到下述错误,说æ˜�root密码错误ï¼�

·                shell> mysqladmin -u root -pxxxx ver
·                Access denied for user 'root'@'localhost' (using password: YES)

如果你未指定密码时出现前面的错误,说明某个选项文件中的密码不正确。试试前面所说的--no-defaults选项ã€�

关于密码更改的信息参è§�5.8.5节,“设置账户密码â€�ã€�

如果你丢失或忘记root密码,你可以ç”�--skip-grant-tables重启 mysqld来更改密码。参è§�A.4.1节,“如何复位根用户密码â€�.

·         如果你使ç”�SET PASSWORDã€�INSERTæˆ�UPDATE更改密码,你必须使用  PASSWORD()函数加密密码。如果你不使ç”�PASSWORD()函数,密码不工作。例如,下面的语句设置密码,但没能加密,因此用户后面不能连接ï¼�

·                mysql> SET PASSWORD FOR 'abe'@'host_name' = 'eagle';

相反,应这样设置密码ï¼�

mysql> SET PASSWORD FOR 'abe'@'host_name' = PASSWORD('eagle');

当你使用GRANTæˆ�CREATE USER语句æˆ�mysqladmin password命令指定密码时,不需è¦�PASSWORD()函数,它们会自动使用PASSWORD()来加密密码。参è§�5.8.5节,“设置账户密码â€�å’�13.5.1.1节,“CREATE USER语法â€�ã€�

·         localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机而客户端尝试连接的默认主机ã€�

要想在这种系统上避免该问题,你可以使ç”�--host=127.0.0.1选项来明确命名服务器主机。这样将通过TCP/IP协议来连接本åœ�mysqld服务å™�。你还可以指å®�--host选项使用TCP/IP,使用实际的本机主机名。在这种情况下,主机名必须指定为服务器主机上çš�user表行,即使你在服务器上运行客户端程序ã€�

·         当尝试用mysql -u user_name与数据库连接时,如果你得到一ä¸�Access denied错误,可能会遇到ä¸�user表有关的问题,通过执行mysql -u root mysql并且执行下面çš�SQL语句进行检查:

·                mysql> SELECT * FROM user;

结果应该包含一个有Hostå’�User列的行匹配你的计算机主机名和你的MySQL用户名ã€�

  • Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图连接哪个主机,是否使用了密码。通常,你应该åœ�user表中有一行,正确地匹配在错误消息给出的主机名和用户名。例如,如果遇到包含using password: NO的错误信息,说明你登录时没有密码ã€�

·         如果当你试着从一个不æ˜�MySQL服务器正在运行的主机上连接时,遇到下列错误,那么åœ�user表中没有匹配那台主机的行ï¼�

·                Host ... is not allowed to connect to this MySQL server

可以通过组合你正在试图连接的用户/主机名设置一个账户来修正它。如果你不知道正连接的机器的IP号或主机名,应该把一ä¸�'%'行作ä¸�Host列值放åœ�user表中。在试图从客户端器连接以后,通过SELECT USER()查询显示你如何真正进行连接。(然后用在日志文件上面显示出的实际的主机名代替user表中çš�'%'行。否则,你将得到一个不安全的系统,因为它允许从任何主机上以任何用户名连接。)

åœ�Linux中,发生该错误的另一个原因可能是你正使用于你所使用版本çš�glibc库不同版本的库编译的二进åˆ�MySQL版本。在这种情况下,你应升级操作系统æˆ�glibc,或下载MySQL版本的源码分发版并自己编译。源ç �RPM一般很容易编译并安装,因此不是大问题ã€�

·         如果你连接时指定主机名,但得到错误消息主机名未显示或ä¸�IP号,表示å½�MySQL服务器将IP号解析为客户端来名时遇到错误ï¼�

·                shell> mysqladmin -u root -pxxxx -h some-hostname ver
·                Access denied for user 'root'@'' (using password: YES)

这表ç¤�DNS问题。要想修复,执行mysqladmin flush-hosts来重设内éƒ� DNS主机名缓存。参è§�7.5.6节,“MySQL如何使用DNSâ€�ã€�

一些常用的解决方案包括ï¼�

o        试试找出DNS服务器的错误并修复ã€�

o        åœ�MySQL授权表中指定IP号而不是主机名ã€�

o        åœ�/etc/hosts中放入客户端名ã€�

o        ç”�--skip-name-resolve选项启动mysqldã€�

o        ç”�--skip-host-cache选项启动mysqldã€�

o        åœ�Unix中,如果你在同一台机器上运行服务器和客户端,连接åˆ�localhost。连接到çš�localhostçš�Unix连接使用Unix套接字文件而不æ˜�TCP/IPã€�

o        åœ�Windows中,你在同一台机器上运行服务器和客户端并且服务器支持命名管道连接,连接主机名(周期)。连接使用命名管道而不æ˜�TCP/IPã€�

  • 如果mysql -u root test工作但是mysql -h your_hostname -u root test导致Access deniedï¼�your_hostname是本地机的实际主机名ï¼�,那么在user表中可能没有你的主机的正确名字。这里的一个普遍的问题是在user表行中的Host值指定一个唯一的主机名,但是你系统的名字解析例程返回一个完全正规的域名(或相å��)。例如,如果你在user表中有一个主机是'tcx'的行,但是你çš�DNS告诉MySQL你的主机名是'tcx.subnet.se',行将不工作。尝试把一个行加到user表中,它包含你主机的IP号作ä¸�Host列的值。(另外,你可以把一个行加到user表中,它有包含一个通配符如'tcx.%'çš�Host值。然而,使用ä»�â€�%â€�结尾的主机名æ˜�不安全的并且ä¸�推荐!)
  • 如果mysql -u user_name test工作但是mysql -u user_name other_db_name不工作,你没有为给定的用户授äº�other_db_name数据库的访问权限ã€�
  • 当在服务器上执行mysql -u user_name时,它工作,但是在其它远程客户端上执mysql -h host_name -u user_name时,它却不工作,你没有为给定的用户授予从远程主机访问服务器的权限ã€�
  • 如果你不能弄明白你为什么得åˆ�Access denied,从user表中删除所æœ�Host包含通配符值的è¡�(包含â€�%â€�æˆ�â€�_â€�的条ç›�)。一个很普遍的错误是ç”�Host='%'å’�User='some_user'插入一个新行,认为这将允许你指å®�localhost从同一台机器进行连接。它不工作的原因æ˜� 默认权限包括一个有Host='localhost'å’�User=''的行,因为那个行çš�Hostå€�'localhost'æ¯�'%'更具体,当从localhost连接时,它用于指向新行!正确的步骤是插入Host='localhost'å’�User='some_user'的第2个行,或删除Host='localhost'å’�User=''行。删除条目后,记住用FLUSH PRIVILEGES语句重载授权表ã€�

·         如果你得到下列错误,可以ä¸�dbæˆ�host表有关:

·                Access to database denied

如果ä»�db表中选择了在Host列有空值的条目,保证在host表中有一个或多个相应的条目,指定db表中的条目适用哪些主机ã€�

·         如果你能够连æŽ�MySQL服务器,但如果在使用命令SELECT ... INTO OUTFILEæˆ�LOAD DATA INFILE语句时,你得åˆ�Access denied错误,在user表中的条目可能没有启ç”�FILE权限ã€�

·         如果你直接更改授权表(例如,使ç”�INSERTã€�UPDATEæˆ�DELETE语句)并且你的更改好像被忽略了,记住你必须执行FLUSH PRIVILEGES语句æˆ�mysqladmin flush-privileges命令让服务器来重读授权表。否则,直到服务器下次重启,你的更改方有效。记住用UPDATE命令更改root密码后,在清空权限前,你不需要指定新密码,因为服务器还不知道你已经更改了密码ï¼�

·         如果你的权限似乎在一个会话过程中改变了,可能是一个超级用户改变了他们。再次装入授权表会影响新客户端连接,但是它也影响现存的连接,å¦�5.7.7节,“权限更改何时生效â€�小节所述ã€�

·         如果你有Perlã€�Pythonæˆ�ODBC程序的存取问题,试着ç”�mysql -u user_name db_nameæˆ�mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用mysql客户端进行连接,这是程序的一个问题而不是访问权限的问题。(注意åœ�-p和密码之间没有空格;也可以使ç”�--password=your_pass语法指定密码。如果使ç”�-p选项ï¼�MySQL提示你输入密码。)

·         为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变MySQL授权表并且使ç”�mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新çš� 授权表。(再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务器开始使用授权表,而不用停掉并重启它)ã€�

·         如果任何其它事情失败,用调试选项(例如ï¼�--debug=d,general,query)启动mysqld服务器。这将打印有关尝试连接的主机和用户信息,和发出的每个命令的信息。请参见E.1.2节,“创建跟踪文件â€�ã€�

·         如果你有任何ä¸�MySQL授权表的其它问题,而且觉得你必须将这个问题发送到邮件表,一定要提供一ä¸�MySQL授权表的倾倒副æœ�(dump)。你可用mysqldump mysql命令复制数据库表。象平时一样,ç”�mysqlbug脚本邮寄你的问题。参è§�1.7.1.3节,“如何通报缺陷和问题â€�。在一些情况下可以ç”�--skip-grant-tables重启mysqld以便能运è¡�mysqldumpã€�


 

5.7.9. MySQL 4.1中的密码哈希处理

MySQL用户账户列于mysql数据库中çš�user表内。每ä¸�MySQL账户指定一个密码,尽管保存åœ�userè¡�Password列的密码不是明文,但哈希值是从表中的记录计算的。用PASSWORD()函数来计算密码的哈希值ã€�

MySQL在客户端/服务器通信的两个阶段使用密码:

·         如果客户端试图连接服务器,有一个初始鉴定步骤,客户必须提供一个密码,并且必须与客户想要使用的账户åœ�user表保存的哈希值匹配ã€�

·         客户端连接后,它可以(如果有充分的权限) 设置或更æ”�user表内所列的账户的密码哈希值值。客户端可以通过PASSWORD()函数来生成密码哈希值,或使ç”�GRANTæˆ�SET PASSWORD语句ã€�

换句话说,当客户端首次试图连接时,服务器使用哈希值进行鉴定。如果连接的客户端调ç”�PASSWORD()函数或使ç”�GRANTæˆ�SET语句来设置或更改密码,则服务å™�产生哈希值ã€�

åœ�MySQL 4.1中密码哈希算法已经更新,提供了更好的安全性并降低了密码被截取的风险。但是,该新机制只能åœ�MySQL 4.1(和更新版本的)服务器和客户端中使用,会产生一些兼容性问题ã€�4.1或新客户端可以连æŽ�4.1之前的服务器,因为客户端可以同时理解旧的和新的密码哈希机制。但是,4.1之前的客户端试图连接4.1版或更新版的服务器时会遇到困难。例如,3.23ç‰�mysql客户端试图连æŽ�5.1服务器时会失败并出现下面的错误消息:

shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

出现该问题的另一个普通例子是在升级到MySQL 4.1或更新版后,试图使用旧版本的PHP mysql扩展名ã€�(参见25.3.1节,“使用MySQL和PHP的常见问题â€�ï¼�ã€�

下面讨论了新、旧密码机制之间的差别,以及如果你升级了服务器但需要为4.1版以前的客户端保持向后兼容性该怎样做ã€�A.2.3节,“客户端不支持鉴定协议â€�中有更详细的信息。该信息å°�MySQL数据库从4.0版本或更低版升级åˆ�4.1版或更高版的PHP编程人员特别重要ã€�

æ³�释:该讨论对比了4.1版的行为å’�4.1前的行为,这儿描述的4.1中的行为实际上从4.1.1开始ã€�MySQL 4.1.0是一个“旧”的发布,因为它的实施机制与4.1.1版和更新版中的稍有不同。在MySQL 5.0 参考手册中详细描述äº�4.1.0和最新版之间的差别ã€�

åœ�MySQL 4.1之前,ç”�PASSWORD()函数计算的密码哈希值有16个字节长。应为:

mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e   |
+--------------------+

åœ�MySQL 4.1之前ï¼�user表的Passwordåˆ�(保存了哈希å€�)也是16字节长ã€�

åœ�MySQL 4.1ä¸�,已经å¯�PASSWORD()函数进行了修改,可以生成41字节的哈希值:

mysql> SELECT PASSWORD('mypass');
+-------------------------------------------+
| PASSWORD('mypass')                        |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+

同样ï¼�user表的Password列必须有41字节长来保存这些值:

·         如果你新安装MySQL 5.1, Password列自动为41字节长ã€�

·         ä»�MySQL 4.1(4.1.1æˆ�4.1系列的更新版)升级åˆ�MySQL 5.1,应不会出现相关问题,因为两个版本使用相同的密码哈希机制。如果你想要将更早版本的MySQL升级åˆ�MySQL5.1,你应先升级到4.1,然后将4.1升级åˆ�5.1ã€�

加宽çš�Password列可以同时保存新、旧格式的密码哈希值。可以有两种方式确定任何给定格式的密码哈希值:

·         明显的不同之处是长度(16字节å’�41字节)ã€�

·         ç¬�2个不同之处是新格式的密码哈希值都以â€�*’字符开头,而旧格式的密码绝对不是ã€�

 长密码哈希值具有更好的加密属性,并且客户端根据长哈希值进行鉴定比旧的短哈希值更加安全ã€�

短密码哈希值和长密码哈希值之间的不同之处与服务器如何使用密码进行鉴定以及如何为执行密码更改操作的连接的客户端生成密码哈希值都有关ã€�

服务器使用密码哈希值进行鉴定的方式å��Password列的宽度影响ï¼�

·         如果列较短,只用短哈希鉴定ã€�

·         如果列较长,可以有短或长哈希值,并且服务器可以使用任何一种格式:

o        4.1之前的客户端可以连接,它们只可以使用旧的哈希机制,它们可以只鉴定有短哈希的账户ã€�

o        4.1及以后版本的客户端可以鉴定有短哈希或长哈希的账户ã€�

对于短哈希账户的鉴定过程ï¼�4.1和以后版本的客户端比为旧版本的客户端实际要安全得多。从安全性角度,从最低安全到最安全的梯度为ï¼�

·         4.1之前的客户端用短密码哈希值进行鉴å®�

·         4.1或以后版本的客户端用短密码哈希值进行鉴å®�

·         4.1或以后版本的客户端用长密码哈希值进行鉴å®�

服务器为连接的客户端生成密码哈希值的方式å��Password列宽度和--old-passwords选项的影响ã€�4.1或更新版本的服务器只有满足某个条件才生成长哈希:Password列必须足够宽以容纳长哈希值并且未给定--old-passwords选项。这些条件适合ï¼�

·         Password列必须足够宽以容纳长哈希(41字节)值。如果列没有更新,仍然为4.1之前çš�16字节宽,当客户端使用PASSWORD()ã€�GRANTæˆ�SET PASSWORD执行密码更改操作时,服务器注意到长哈希不适合,只生成短哈希。如果你已经升级åˆ�4.1但还没有运行 mysql_fix_privilege_tables脚本来扩å®�Password列时会出现这种行为ã€�

·         如果Password列足够宽,则可以保存短或长密码哈希值。在这种情况下,PASSWORD()ã€�GRANTæˆ�SET PASSWORD生成长哈希,除非 ç”�--old-passwords选项启动服务器。该选项强制服务器生成短密码哈希值ã€�

--old-passwords选项的目的是当服务器生成长密码哈希值时,允许你维持å��4.1之前的客户端的向后兼容性。该选项不影响鉴å®�(4.1和以后版本的客户端仍然可以使用有长密码哈希值的账户),但它防止在密码更改操作中在user表中创建长密码哈希值。在这种情况下,该账户不能再用于4.1之前的客户端。没æœ�--old-passwords选项,可能会出现下面的不期望的情况:

·         旧客户端连接有短密码哈希值的账户ã€�

·         客户更改自己的密码。没æœ�--old-passwords,可以为该账户生成长密码哈希值ã€�

·         下次旧客户试图连接账户时不能连接上,因为账户有长密码哈希值,需要新的哈希机制进行鉴定ã€�(一旦账æˆ�user表中为长密码哈希值,只有4.1和以后版本的客户端可以鉴定它,因ä¸�4.1之前的客户端不理解长哈希ï¼�ã€�

该场景说明,如果你必须支持旧çš�4.1之前的客户端,不使用--old-passwords选项运行4.1或更新版本的服务器很危险。用--old-passwords运行服务器,密码更改操作不会生成长密码哈希值,这样旧客户端也可以访问账户ã€�(这些客户端不能意外地因更改了密码将自己锁出去,并留下长密码哈希值)ã€�

--old-passwords选项的不利之处是你创建或更改的密码使用短哈希,甚至对äº�4.1客户端也如此。这样,你丢失了长密码哈希值提供的安全性。如果你想要创建有长哈希的账æˆ�(例如,为4.1客户ç«�),你必须不使ç”�--old-passwords来运行服务器ã€�

下面的场景可用于运行4.1或以后的服务器,包括MySQL 5.1ï¼�

场景1ï¼�user表中的短Password列:

·         只有短哈希可以保存到Password列ã€�

·         服务器只使用短哈希进行客户端鉴定ã€�

·         对于连接的客户端,调ç”�PASSWORD()ã€�GRANTæˆ�SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值ã€�

·          --old-passwords选项可以使用但是多余,因ä¸�Password列较短,服务器只生成短密码哈希值ã€�

场景2ï¼�é•�Password列;没有ç”�--old-passwords选项启动服务器:

·         短或长哈希可以保存到Password列ã€�

·         4.1和以后版本的客户ç«�(包括5.1客户ç«�)可以鉴定有短或长哈希的账户ã€�

·         4.1之前的客户端只能鉴定有短哈希的账户ã€�

·         对于连接的客户端,调ç”�PASSWORD()ã€�GRANTæˆ�SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值ã€�

如前面所示,该场景的危险性在äº�4.1之前的客户端可能不能访问有短密码哈希值的账户。通过PASSWORD()ã€�GRANTæˆ�SET PASSWORDA对这些账户密码的更改会产生长的密码哈希值。从该点看,4.1之前的客户端升级åˆ�4.1之前不能鉴定该账户ã€�

要处理该问题,可以用特殊方法更改密码。例如,一般情况你可以使用SET PASSWORD按照下面的方法更改账户密码:

mysql> SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('mypass');

要想更改密码但创建短哈希,使ç”�OLD_PASSWORD()函数ï¼�

mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('mypass');

当你想明显生成短哈希æ—�ï¼�OLD_PASSWORD()很有用ã€�

场景3ï¼�é•�Password列;ç”�--old-passwords选项启动4.1或新版本的服务器ï¼�

·         短或长哈希可以保存到Password列ã€�

·         4.1和以后版本的客户端可以鉴定有短或长哈希的账户(请注意只有不使用--old-passwords选项启动服务器,方可以创建长哈希)ã€�

·         4.1之前的客户端只可以鉴定短哈希账户ã€�

·         对于连接的客户端,调ç”�PASSWORD()ã€�GRANTæˆ�SET PASSWORD的密码哈希生成操作专使用短哈希。对账户的任何更改均会生成短密码哈希值ã€�

在该场景中,你不能创建长密码哈希值的账户,因ä¸�--old-passwords选项防止生成长哈希。并且,如果你在使用--old-passwords选项前创建长哈希账户,当--old-passwords有时更改账户密码,结果会使账户的密码为短密码,安全性较长哈希要降低ã€�

这些场景的不利之处可以概括为ï¼�

在场æ™�1ä¸�,你不能利用长哈希提供更安全的鉴定ã€�

在场æ™�2ä¸�, 如果你没有显式使ç”�OLD_PASSWORD()来更改密码,åˆ�4.1之前的客户端不能再访问短哈希账户ã€�

在场æ™�3ä¸�,--old-passwords防止短哈希账户不可访问,但密码更改操作使账户的长哈希转换为短哈希,当--old-passwords有效时不能将它改回长哈希ã€�

5.7.9.1. 更改应用程序密码哈希值的含义

升级åˆ�MySQL4.1或更新版本后,使ç”�PASSWORD()为自己的目的生成密码的应用程序会出现兼容性问题。应用程序实际不应这样做,因ä¸�PASSWORD()只应用来管理MySQL账户的密码。但一些应用程序使ç”�PASSWORD()用于自己的目的ã€�

如果你从MySQL 4.1之前的版本升级到4.1或以后版本,并在生成长密码哈希值的条件下运行服务器,应用程序使ç”�PASSWORD()破解自己的密码。这种情况下推荐的方法是修改应用程序,使用其它函数,例如SHA1()æˆ�MD5(),来产生哈希值。如果不行,你可以使ç”�OLD_PASSWORD()函数,该函数用来提供旧格式的短哈希。但是,请注æ„�OLD_PASSWORD()可能有一天不再被支持ã€�

如果服务器运行在生成短哈希的条件下,可以使用 OLD_PASSWORD()但与PASSWORD()等同ã€�

å°�MySQL数据库从4.0或更低版本移植到4.1或更高版本的PHP编程人员应参é˜�旧客户端ã€�

5.8. MySQL用户账户管理

本节描述如何ä¸�MySQL服务器的客户端设置账户。讨论了下面的主题:

·         MySQL使用的账户名和密码的含义,以及如何比较你的操作系统所使用的账户名和密ç �

·         如何设置新账户并移除已有账户

·         如何更改密码

·         安全使用密码指导

·         如何使用安全SSL连接

5.8.1. MySQL用户名和密码

用用户名和客户端或主机定ä¹�MySQL账户,用户可以根据这些名称来连接服务器。账户也有密码ã€�MySQL和操作系统使用用户名和密码的方式有几处区别:

·         MySQL用于鉴定目的用户名与Windowsæˆ�Unix使用的用户名(登录å��)没有关系。在Unix中,大多æ•�MySQL客户端默认试图使用当å‰�Unix的用户名作为MySQL用户名来登录,但这样只是为了方便ã€� 默认值可以很容易被覆盖,因为客户端程序允许用-uæˆ�--user选项来指定用户名。因为这表示任何人可以试图使用任何用户名来连接服务器,除非所æœ�MySQL账户有密码,否则你不能使数据库保持安全。通过为没有密码的账户指定用户名,任何人能够成功连接服务器ã€�

·         MySQL用户名最大客è¾�16字符长。这样可以限åˆ�MySQL服务器和客户端之间的硬编码,并且防止通过修改mysql数据库中表的定义来偷窃密码ã€�

æ³�:ä½�应绝对不要以任何方式修改mysql数据库中的任何表,只能运è¡�MySQL分发中专为此目的提供的脚本。将MySQL系统表重新定义为其它方式会导致未定义çš�(和不支持çš�!)行为ã€�

操作系统用户名与MySQL用户名完全不相关,甚至最大长度可能不同。例如, Unix用户名限制为8个字符ã€�

·         MySQL密码与登录到你的操作系统的密码没有关系。不需要将你用来登å½�Windowsæˆ�Unix机器的密码和你用来访问该机器上的MySQL服务器的密码关联起来ã€�

·         MySQL的加密密码使用自己的算法。该加密算法不同äº�Unix登录过程使用的算法ã€�MySQL密码加密ä¸�PASSWORD()SQL函数的方法相同ã€�Unix密码加密ä¸�ENCRYPT()SQL函数的方法相同ã€�PASSWORD()å’�ENCRYPT()函数的描述参è§�12.9.2节,“加密函数â€�。从版本4.1 起,MySQL使用更强的鉴定方法,同以前的版本相比可以在连接过程中提供更好的密码保护。即ä½�TCP/IP包被截取æˆ�mysql数据库被捕获也很安全ã€�(在前面的版本中,即使密码以加密形式保存到user表中,仍可以通过加密密码值来连接MySQL服务器)ã€�

当安è£�MySQL时,授权表装载时有一系列初使账户。这些账户的名称和访问权限见2.9.3节,“使初始MySQL账户安全â€�,其中还讨论了如何未这些账户赋予密码。因此,你一般应使用GRANTå’�REVOKE语句来设置、修改和移除MySQL账户。参è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

当用命令行客户端连接MySQL服务器时,你应为想要使用的账户指定用户名和密码:

shell> mysql --user=monty --password=guess db_name

如果你想用较短的选项,命令应为:

shell> mysql -u monty -pguess db_name

-p选项和后面的密码值之间绝对不能有空格。参è§�5.7.4节,“与MySQL服务器连接â€�ã€�

前面的命令包括命令行中的密码值,会很危险。参è§�5.8.6节,“使你的密码安全â€�。要想避免,指定--passwordæˆ�-p选项后面不跟任何密码值:

shell> mysql --user=monty --password db_name
shell> mysql -u monty -p db_name

然后客户端程序输出提示符并等待你输入密码ã€�(在这些示例中ï¼�db_name并不为密码,因为用空格将它同前面的密码项隔离开了)ã€�

在一些系统中ï¼�MySQL用来提示输入密码的库调用自动将密码限制到8个字符。这是系统库的问题,而不æ˜�MySQL的问题ã€�MySQL本身并不限制密码的长度。要解决该问题,å°�MySQL密码改为8个字符和更少字符的值,或将密码放入选项文件中ã€�

5.8.2. 向MySQL增加新用户账æˆ�

可以用两种方式创å»�MySQL账户ï¼�

·         使用GRANT语句

·         直接操作MySQL授权è¡�

最好的方法是使ç”�GRANT语句,因为这样更精确,错误少。从MySQL 3.22.11起提供了GRANT;其语法è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

创建账户的其它方法是使用MySQL账户管理功能的第三方程序ã€�phpMyAdmin即是一个程序ã€�

下面的示例说明如何使ç”�MySQL客户端程序来设置新用户。假定按ç…�2.9.3节,“使初始MySQL账户安全â€�描述çš� 默认值来设置权限。这说明为了更改,你必须ä»�MySQL root用户连接MySQL服务器,并且root账户必须æœ�mysql数据库的INSERT权限å’�RELOAD管理权限ã€�

首先,使ç”�MySQL程序ä»�MySQL root用户来连接服务器ï¼�

shell> MySQL --user=root MySQL

如果你为root账户指定了密码,还需要为è¯�MySQL命令和本节中的其它命令提ä¾�--passwordæˆ�-p选项ã€�

ä»�root连接到服务器上后,可以添加新账户。下面的语句使用GRANT来设置四个新账户ï¼�

mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'
    ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
    ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';

ç”�GRANT语句创建的账户有下面的属性:

·         其中两个账户有相同的用户å��monty和密ç �some_pass。两个账户均为超级用户账户,具有完全的权限可以做任何事情。一个账æˆ� ('monty'@'localhost')只用于从本机连接时。另一个账æˆ�('monty'@'%')可用于从其它主机连接。请注意monty的两个账户必须能从任何主机以monty连接。没æœ�localhost账户,当monty从本机连接时ï¼�mysql_install_db创建çš�localhost的匿名用户账户将占先。结果是ï¼�monty将被视为匿名用户。原因是匿名用户账户çš�Host列值比'monty'@'%'账户更具体,这样åœ�user表排序顺序中排在前面ã€�(user表排序的讨论参见5.7.5节,“访问控åˆ�, 阶段1:连接核实â€�ï¼�ã€�

·         一个账户有用户å��admin,没有密码。该账户只用于从本机连接。授予了RELOADå’�PROCESS管理权限。这些权限允è®�admin用户执行mysqladmin reloadã€�mysqladmin refreshå’�mysqladmin flush-xxx命令,以å��mysqladmin processlist。未授予访问数据库的权限。你可以通过GRANT语句添加此类权限ã€�

·         一个账户有用户å��dummy,没有密码。该账户只用于从本机连接。未授予权限。通过GRANT语句中的USAGE权限,你可以创建账户而不授予任何权限。它可以将所有全局权限设为'N'。假定你将在以后将具体权限授予该账户ã€�

除了GRANT,你可以直接ç”�INSERT语句创建相同的账户,然后使用FLUSH PRIVILEGES告诉服务器重载授权表ï¼�

shell> mysql --user=root mysql
mysql> INSERT INTO user
    ->     VALUES('localhost','monty',PASSWORD('some_pass'),
    ->     'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user
    ->     VALUES('%','monty',PASSWORD('some_pass'),
    ->     'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user SET Host='localhost',User='admin',
    ->     Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
    ->     VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

当你ç”�INSERT创建账户时使ç”�FLUSH PRIVILEGES的原因是告诉服务器重读授权表。否则,只有重启服务器后更改方会被注意到。使ç”� GRANT,则不需要使ç”�FLUSH PRIVILEGESã€�

ç”�INSERT使用PASSWORD()函数是为了加密密码ã€�GRANT语句为你加密密码,因此不需è¦�PASSWORD()ã€�

'Y'值启用账户权限。对äº�admin账户,还可以使用更加可读çš�INSERT扩充的语法(使用SET)ã€�

在为dummy账户çš�INSERT语句中,只有user表中çš�Hostã€�Userå’�Password列记录为指定的值。没有一个权限列为显式设置,因此MySQL将它们均指定ä¸� 默认å€�'N'。这样等同于GRANT USAGE的操作ã€�

请注意要设置超级用户账户,只需要创建一个权限列设置ä¸�'Y'çš�user表条目ã€�user表权限为全局权限,因此其å®� 授权表不再需要条目ã€�

下面的例子创å»�3个账户,允许它们访问专用数据库。每个账户的用户名为custom,密码为obscureã€�

要想ç”�GRANT创建账户,使用下面的语句ï¼�

shell> MySQL --user=root MySQL
shell> mysql --user=root mysql
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    ->     ON bankaccount.*
    ->     TO 'custom'@'localhost'
    ->     IDENTIFIED BY 'obscure';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    ->     ON expenses.*
    ->     TO 'custom'@'whitehouse.gov'
    ->     IDENTIFIED BY 'obscure';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    ->     ON customer.*
    ->     TO 'custom'@'server.domain'
    ->     IDENTIFIED BY 'obscure';

è¿�3个账户可以用于:

·         ç¬�1个账户可以访é—�bankaccount数据库,但只能从本机访问ã€�

·         ç¬�2个账户可以访é—�expenses数据库,但只能从主机whitehouse.gov访问ã€�

·         ç¬�3个账户可以访é—�customer数据库,但只能从主机server.domain访问ã€�

要想不用GRANT设置custom账户,使ç”�INSERT语句直接修改 授权表:

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
    ->     VALUES('localhost','custom',PASSWORD('obscure'));
mysql> INSERT INTO user (Host,User,Password)
    ->     VALUES('whitehouse.gov','custom',PASSWORD('obscure'));
mysql> INSERT INTO user (Host,User,Password)
    ->     VALUES('server.domain','custom',PASSWORD('obscure'));
mysql> INSERT INTO db
    ->     (Host,Db,User,Select_priv,Insert_priv,
    ->     Update_priv,Delete_priv,Create_priv,Drop_priv)
    ->     VALUES('localhost','bankaccount','custom',
    ->     'Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
    ->     (Host,Db,User,Select_priv,Insert_priv,
    ->     Update_priv,Delete_priv,Create_priv,Drop_priv)
    ->     VALUES('whitehouse.gov','expenses','custom',
    ->     'Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
    ->     (Host,Db,User,Select_priv,Insert_priv,
    ->     Update_priv,Delete_priv,Create_priv,Drop_priv)
    ->     VALUES('server.domain','customer','custom',
    ->     'Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;
 

å‰�3ä¸�INSERT语句åœ�user表中加入条目,允许用æˆ�custom从各种主机用给定的密码进行连接,但不授予全局权限(所有权限设置为 默认å€�'N')。后é��3ä¸�INSERT语句åœ�user表中加入条目,为custom授予bankaccountã€�expenseså’�customer数据库权限,但只能从合适的主机访问ã€�通常若直接修æ”� 授权表,则应告诉服务器用FLUSH PRIVILEGES重载授权表,使权限更改生效ã€�

如果你想要让某个用户从给定域的所有机器访é—�(例如ï¼�mydomain.com),你可以在账户名的主机部分使用含â€�%’通配符的GRANT语句ï¼�

mysql> GRANT ...
    ->     ON *.*
    ->     TO 'myname'@'%.mydomain.com'
    ->     IDENTIFIED BY 'mypass';

要想通过直接修改授权表来实现ï¼�

mysql> INSERT INTO user (Host,User,Password,...)
    ->     VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...);

mysql> FLUSH PRIVILEGES;

5.8.3. 从MySQL删除用户账户

要想移除账户,应使用DROP USER语句,请参见13.5.1.2节,“DROP USER语法â€�ã€�

5.8.4. 限制账户资源

限制MySQL服务器资源使用的一个方法是å°�max_user_connections系统变量设置为非零值。但是,该方法严格限于全局,不允许管理具体账户。并且,它只限制使用单一账户同时连接的数量,而不是客户端连接后的操作。许å¤�MySQL管理员对两种类型的控制均感兴趣,特别æ˜�Internet服务提供者ã€�

åœ�MySQL 5.1ä¸�,你可以为具体账户限制下面的服务器资源ï¼�

·         账户每小时可以发出的查询æ•�

·         账户每小时可以发出的更新æ•�

·         账户每小时可以连接服务器的次æ•�

客户端可以执行的语句根据查询限制来记数。只有修改数据库或表的语句根据更新限制来记数ã€�

还可以限制每个账户的同时连接服务器的连接数ã€�

本文中的账户ä¸�user表中的单个记录。根æ��Userå’�Host列值唯一识别每个账户ã€�

做为使用该特性的先决条件ï¼�mysql数据库的user表必须包含资源相关的列。资源限制保存在max_questionsã€�max_updatesã€�max_connectionså’�max_user_connections列内。如æž�user表没有这些列,必须对它进行升级;参见2.10.2节,“升级授权表â€�ã€�

要想ç”�GRANT语句设置资源限制,使WITH子句来命名每个要限制的资源和根据每小时记数的限制值。例如,要想只以限制方式创建可以访问customer数据库的新账户,执行该语句:

mysql> GRANT ALL ON customer.* TO 'francis'@'localhost'
    ->     IDENTIFIED BY 'frank'
    ->     WITH MAX_QUERIES_PER_HOUR 20
    ->          MAX_UPDATES_PER_HOUR 10
    ->          MAX_CONNECTIONS_PER_HOUR 5
    ->          MAX_USER_CONNECTIONS 2;

限制类型不需要全部在WITH子句中命名,但已经命名的可以按任何顺序。每个每小时限制值均应为整数,代表每小时的记数。如æž�GRANT语句没有WITH子句,则每个限制值设置为 默认值零(即没有限åˆ�)。对äº�MAX_USER_CONNECTIONS,限制为整数,表示账户一次可以同时连接的最大连接数。如果限制设置为 默认值零,则根据MAX_USER_CONNECTIONS系统变量确定该账户可以同时连接的数量ã€�

要想设置或更改已有账户的限制,在全局级别使用GRANT USAGE语句(åœ�*.*)。下面的语句可以å°�francis的查询限制更改为100ï¼�

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'
    ->     WITH MAX_QUERIES_PER_HOUR 100;

该语句没有改变账户的已有权限,只修改了指定的限制值ã€�

要想取消已有限制,将该值设置为零。例如,要想取消francis每小时可以连接的次数的限制,使用该语句:

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'
    ->     WITH MAX_CONNECTIONS_PER_HOUR 0;

当账户使用资源时如果有非零限制,则对资源使用进行记数ã€�

服务器运行时,它统计每个账户使用资源的次数。如果账户在最后一个小时的连接次数达到限制,该账户的进一步的连接被拒绝。类似地,如果账户达到查询或更新次数的限制,进一步的查询或更新被拒绝。在这种情况下,会给出相关错误消息ã€�

根据每个账户进行资源计算,而不是根据每个客户端。例如,如果你的账户的查询限制为50,你不能通过两个客户端同时连接服务器将限制增加到100。两个连接的查询被计算到一起ã€�

可以为所有账户从全局重设当前的每小时资源使用记数,或单独重设给定的账户:

·         要想将所有账户当前的记数重设为零,可以执è¡�FLUSH USER_RESOURCES语句。还可以通过重载授权表来重设记数(例如,使ç”�FLUSH PRIVILEGES语句æˆ�mysqladmin reload命令)ã€�

·         将具体账户的限制重新授予任何值,可以将它设置为零。要想实现,按照前面所述使ç”�GRANT USAGE,并将限制值指定为该账户当前的限制值ã€�

计数器重设不影响MAX_USER_CONNECTIONS限制ã€�

当服务器启动时所有记数从零开始ã€�

5.8.5. 设置账户密码

  • 可以ç”�mysqladmin命令在命令行指定密码ï¼�
    shell> mysqladmin -u user_name -h host_name password "newpwd"

    该命令重设密码的账户ä¸�user表内匹配User列的user_nameå’�Hoståˆ�你发起连接的客户端的记录ã€�

    为账户赋予密码的另一种方法是执行SET PASSWORD语句ï¼�

    mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');

    只有root等可以更æ–�mysql数据库的用户可以更改其它用户的密码。如果你没有以匿名用户连接,省略FOR子句便可以更改自己的密码ï¼�

    mysql> SET PASSWORD = PASSWORD('biscuit');

    你还可以在全局级别使用GRANT USAGE语句(åœ�*.*)来指定某个账户的密码而不影响账户当前的权限:

    mysql> GRANT USAGE ON *.* TO 'jeffrey'@'%' IDENTIFIED BY 'biscuit';

    一般情况下最好使用上述方法来指定密码,你还可以直接修æ”�user表:

    ·         要想在创建新账户时建立密码,åœ�Password列提供一个值:

    ·                shell> mysql -u root mysql
    ·                mysql> INSERT INTO user (Host,User,Password)
    ·                     -> VALUES('%','jeffrey',PASSWORD('biscuit'));
    ·                mysql> FLUSH PRIVILEGES;
    ·                 

    ·         要想更改已有账户的密码,使用UPDATE来设ç½�Password列值:

    ·                shell> mysql -u root mysql
    ·                 mysql> UPDATE user SET Password = PASSWORD('bagel')
    ·                       -> WHERE Host = '%' AND User = 'francis';
    ·                mysql> FLUSH PRIVILEGES;

    当你使用SET PASSWORDã€�INSERTæˆ�UPDATE指定账户的密码时,必须用PASSWORD()函数对它进行加密ã€�(唯一的特例是如果密码为空,你不需要使ç”�PASSWORD())。需要使ç”�PASSWORD()是因ä¸�user表以加密方式保存密码,而不是明文。如果你忘记了,你可能会象这样设置密码:

    shell> mysql -u root mysql
    mysql> INSERT INTO user (Host,User,Password)
        -> VALUES('%','jeffrey','biscuit');
    mysql> FLUSH PRIVILEGES;
     

    结果是密ç �'biscuit'保存åˆ�user表后没有加密。当jeffrey使用该密码连接服务器时,值被加密并同保存åœ�user表中的进行比较。但是,保存的值为字符ä¸�'biscuit',因此比较将失败,服务器拒绝连接ï¼�

    shell> mysql -u jeffrey -pbiscuit test
    Access denied

    如果你使ç”�GRANT ... IDENTIFIED BY语句æˆ�mysqladmin password命令设置密码,它们均会加密密码。在这种情况下,不需要使ç”� PASSWORD()函数ã€�

    æ³�释:PASSWORD()加密不同äº�Unix密码加密。参è§�5.8.1节,“MySQL用户名和密码â€�ã€�

5.8.6. 使你的密码安å…�

在管理级别,你决不能å°�mysql.user表的访问权限授予任何非管理账户ã€�

当你运行客户端程序连æŽ�MySQL服务器时,以一种暴露的可被其他用户发现的方式指定你的密码是不妥当的。当你运行客户端程序时,你可以使用下列方法指定你的密码,还有每个方法的风险评估:

·         使用一个在命令行上-pyour_passæˆ�--password=your_pass的选项。例如:

·                shell> mysql -u francis -pfrank db_name

这很方便但是不安全,因为你的密码对系统状态程åº�(例如ps)变得可见,它可以被其他的用户调用来显示命令行。一èˆ�MySQL客户在他们的初始化顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可见的ã€�

·         使用一ä¸�-pæˆ�--password选项(没有指定密码)。在这种情况下,客户端程序请求来自终端的密码ï¼�

·                shell> mysql -u francis -p db_name
·                Enter password: ********

 â€�*â€�字符指示输入密码的地方。输入密码时密码看不见ã€�

因为它对其他用户不可见,与在命令行上指定它相比,这样进入你的密码更安全。然而,这个输入一个密码的方法仅仅为你交互式运行程序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户端,就没有从终端输入入密码的机会。在某些系统中,你甚至会发现脚本的第一行被(错误地)读并解释为你的密码ï¼�

·         在一个配置文件中存储你的密码。例如,åœ�Unix中,你可在主目录çš�â€�.my.cnfâ€�文件中的[client]节列出你的密码:

·                [client]
·                password=your_pass

如果你在â€�.my.cnfâ€�里面存储密码,除了你本人其它人不能访问该文件。保证文件的访问模式æ˜�400æˆ�600ã€�例如ï¼�

shell> chmod 600 .my.cnf

关于选项文件的详细讨论参è§�4.3.2节,“使用选项文件â€�ã€�

·         你可åœ�MYSQL_PWD环境变量中存储密码。但是这种指å®�MySQL密码的方法是极不安全的,不应该使用ã€�ps的某些版本包括显示运行进程的环境的选项;如果你设定MYSQL_PWD,你的密码将被运è¡�ps的所有人看见,甚至在没有这样一个版本的ps的系统上,没有其它方法观察到进程环境的假设是不明智的。参è§�附录Fï¼�环境变量ã€�

总之,最安全的方法是让客户端程序提示输入密码或在适当保护的选项文件中指定密码ã€�

5.8.7. 使用安全连接

MySQL支持MySQL客户端和服务器之间的安全(加密çš�)连接所使用的安全套接字å±�(SSL)协议。本节讨论如何使ç”�SSL连接。还描述了在Windows中设ç½�SSH的方法ã€�

MySQL的标准配置倾向于尽可能快,因此默认情况不使用加密连接。使用该协议会使客户ç«�/服务器协议慢得多。对数据进行加密非常è€�CPU,需要计算机多做许多工作,会延迟MySQL的其它任务。对于需要通过加密连接提供安全的应用程序,可以保证额外的计算ã€�

MySQL允许在连接前启用加密。你可以根据具体应用程序的需求选择普通未加密连接或安全加å¯�SSL连接ã€�

5.8.7.1. SSL基本概念

要想理解MySQL如何使用SSL,需要解释一些基æœ�SSLå’�X509概念。熟悉的人们可以跳过该部分ã€�

默认情况下,MySQL在客户端和服务器之间使用未加密的连接。这说明可以访问网络的部分人可以看到你的通信,并看到发送和接收的数据。他们甚至可以更改在客户端和服务器之间传递的数据。要想提高安全性,当调用客户端程序时,你可以通过--compress选项压缩客户ç«�/服务器之间的通信。但是,这样并不能阻挡住顽固的攻击者ã€�

当你需要以安全方式在网络中传递信息时,未加密的连接是不可接受的。加密是使任何数据不可读的方法。事实上,今天的许多惯例需要加密算法提供更加安全的要素。它们应能抵抗各种已知的攻击,例如更改加密消息的顺序或两次重放数据ã€�

SSL是一种使用不同的加密算法确保从公用网接收到的数据是可信的协议。它具有检测数据更改、丢失或重放的机制ã€�SSL还包括使ç”� X509标准提供身份认证的算法ã€�

使用X509,可以识åˆ�Internet上的某些人。通常用于电子商务应用程序中。按照基本概念,应有某种称之为â€�认证机构â€�(æˆ�CA)的机构,可以向请求者分发电子证书。证书依赖非对称加密算法,有两个加密密钥(公共密钥和私人密é’�)。认证持有者可以向其它方出示证书来证明身份。证书包括持有者的公共密钥。只能使用对应的私人密钥对含该公共密钥的加密数据进行解密,私人密钥由证书持有者拥有ã€�

如果你需要关äº�SSLã€�X509、或加密的详细信息,使用Internet搜索引擎来搜索你感兴趣的关键字ã€�

5.8.7.2. 需æ±�(OpenSSL)

要想åœ�MySQL服务器和客户端程序之间使ç”�SSL连接,系统必须能够支æŒ�OpenSSL。如果用支持内嵌å¼�yaSSLçš�MySQL版本,不要读该节,但应阅è¯�5.8.7.3节,“使用yaSSLâ€�ã€�

要想获得安全çš�MySQL连接,必须:

1.    安装OpenSSL库。我们已经测试了å¸�OpenSSL 0.9.6çš�MySQL。如果你需è¦�OpenSSL,请访问http://www.openssl.orgã€�

2.    配置MySQL,用--with-vioå’�--with-openssl选项运行configure脚本ã€�

3.    确保升级了授权表,使mysql.user表内包含SSL相关列。如æž� 授权表是ä»�MySQL 4.0.0之前的版本升级,这很重要。升级过程见2.10.2节,“升级授权表â€�ã€�

4.    要想检查是否运行的mysqld服务å™�支持OpenSSL,应检æŸ�have_openssl系统变量的值:

5.            mysql> SHOW VARIABLES LIKE 'have_openssl';
6.            +---------------+-------+
7.            | Variable_name | Value |
8.            +---------------+-------+
9.            | have_openssl  | YES   |
10.        +---------------+-------+

如果值为YES,服务器支持OpenSSL连接ã€�

5.8.7.3. 使用yaSSL

使用MySQL的内嵌式yaSSL支持,可以很容易地使用安全连接。不需要安è£�OpenSSL和执è¡�5.8.7.2节,“需æ±�(OpenSSL)â€�中的步骤。并且,MySQLå’�yaSSL使用相同的许可模型ã€�

当前,在以下平台上支æŒ�yaSSLï¼�

·         Linux/x86-64 Red Hat Enterprise 3.0

·         Linux RHAS21 Itanium-2,带gcc,静态链æŽ�

·         Linux Itanium-2,带gcc

·         Windows

当从源码构建MySQL时如果你想要启用yaSSL,应这样配置MySQLï¼�

./configure --with-yassl=yes

要想启动MySQL服务器支æŒ�yaSSL,使用支æŒ�OpenSSL的相同的选项,并识别建立安全连接需要的证书ï¼�

shell> mysqld --ssl-ca=cacert.pem \
       --ssl-cert=server-cert.pem \
       --ssl-key=server-key.pem

·         --ssl-ca识别认证机构证书ã€�

·         --ssl-cert识别服务器证书ã€�

·         --ssl-key识别客户证书ã€�

要想ç”�yaSSL支持建立ä¸�MySQL服务器的安全连接,应这样启动客户端:

shell> mysql --ssl-ca=cacert.pem \
       --ssl-cert=server-cert.pem \
       --ssl-key=server-key.pem

换句话说,选项与服务器的相同,并且认证机构证书必须相同ã€�

要想从应用程序建立安全连接,调用mysql_real_connect()之前,应使用mysql_ssl_set()API函数来设置相应认证选项。参è§�25.2.3.64节,“mysql_ssl_set()â€�ã€�

5.8.7.4. 为MySQL设置SSL证书

下面是一个为MySQ设置SSL证书的例子:
DIR=`pwd`/openssl
PRIV=$DIR/private
 
mkdir $DIR $PRIV $DIR/newcerts
cp /usr/share/ssl/openssl.cnf $DIR
replace ./demoCA $DIR -- $DIR/openssl.cnf
 
# Create necessary files: $database, $serial and $new_certs_dir
# directory (optional)
 
touch $DIR/index.txt
echo "01" > $DIR/serial
 
#
# Generation of Certificate Authority(CA)
#
 
openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem \
    -config $DIR/openssl.cnf
 
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ................++++++
# .........++++++
# writing new private key to '/home/monty/openssl/private/cakey.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL admin
# Email Address []:
 
#
# Create server request and key
#
openssl req -new -keyout $DIR/server-key.pem -out \
    $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf
 
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ..++++++
# ..........++++++
# writing new private key to '/home/monty/openssl/server-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL server
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:
 
#
# Remove the passphrase from the key (optional)
#
 
openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem
 
#
# Sign server cert
#
openssl ca  -policy policy_anything -out $DIR/server-cert.pem \
    -config $DIR/openssl.cnf -infiles $DIR/server-req.pem
 
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL admin'
# Certificate is to be certified until Sep 13 14:22:46 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated
 
#
# Create client request and key
#
openssl req -new -keyout $DIR/client-key.pem -out \
    $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf
 
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# .....................................++++++
# .............................................++++++
# writing new private key to '/home/monty/openssl/client-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL user
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:
 
#
# Remove a passphrase from the key (optional)
#
openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem
 
#
# Sign client cert
#
 
openssl ca  -policy policy_anything -out $DIR/client-cert.pem \
    -config $DIR/openssl.cnf -infiles $DIR/client-req.pem
 
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL user'
# Certificate is to be certified until Sep 13 16:45:17 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated
 
#
# Create a my.cnf file that you can use to test the certificates
#
 
cnf=""
cnf="$cnf [client]"
cnf="$cnf ssl-ca=$DIR/cacert.pem"
cnf="$cnf ssl-cert=$DIR/client-cert.pem"
cnf="$cnf ssl-key=$DIR/client-key.pem"
cnf="$cnf [mysqld]"
cnf="$cnf ssl-ca=$DIR/cacert.pem"
cnf="$cnf ssl-cert=$DIR/server-cert.pem"
cnf="$cnf ssl-key=$DIR/server-key.pem"
echo $cnf | replace " " '
' > $DIR/my.cnf

 

要想测试SSL连接,按下面方法启动服务器,其中$DIR是示ä¾�my.cnf选项文件安装的路径名ï¼�

shell> MySQLd --defaults-file=$DIR/my.cnf &

然后使用相同的选项文件调用客户端程序:

shell> MySQL --defaults-file=$DIR/my.cnf

如果你有MySQL源码分发版,还可以修改前面的my.cnf文件来指å��SSL目录中的示范证书和密钥文件来测试你的设置ã€�

5.8.7.5. SSL GRANT 选项

MySQL可以检æŸ�X509证书的属性和基于用户名和密码的通用鉴定方法。要想为MySQL账户指定SSL相关选项,使ç”�GRANT语句çš�REQUIRE子句。参è§�13.5.1.3节,“GRANT和REVOKE语法â€�ã€�

有多种可能来限制一个账户的连接类型ï¼�

·         如果账户没有SSLæˆ�X509需求,如果用户名和密码合法,允许未加密的连接。但是,如果客户有正确的证书和密钥文件,在客户选项中可以使用加密连接ã€�

·         REQUIRE SSL选项限制服务器只允许该账户的SSL加密连接。请注意如果æœ�ACL记录允许é��SSL连接,该选项会被忽略ã€�

·                  mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                     -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

·         REQUIRE X509表示客户必须有合法证书但确切的证书、分发者和主体不重要。唯一的需求是应可以被某个CA认证机构验证它的签名ã€�

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret' REQUIRE X509;

·         REQUIRE ISSUER 'issuer'限制连接企图,即客户必须出示CA 'issuer'签发的合æ³�X509证书。如果客户出示了一个合法证书,但是是由不同的分发者签发,服务器拒绝连接。使ç”�X509证书表示要加密,因此不需è¦�SSL选项ã€�

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
·                       O=MySQL Finland AB/CN=Tonu Samuel/[email protected]';

请注æ„�ISSUER值应做为单一字符串输入ã€�

·         REQUIRE SUBJECT 'subject' 限制连接企图,即客户必须出示主题ä¸�'subject'的合æ³�X509证书。如果客户出示了一个合法证书,但是有不同的主题,服务器拒绝连接ã€�

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
·                       O=MySQL demo client certificate/
       CN=Tonu Samuel/[email protected]';

请注æ„�SUBJECT值应做为单一字符串输入ã€�

·         REQUIRE CIPHER 'cipher'用来确保使用足够强的密码和密钥长度。如果使用旧的短加密密钥算法ï¼�SSL本身可能很弱。使用该选项,我们可以索取确切的加密方法来连接ã€�

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
    -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

åœ�REQUIRE子句中,可以结合使用SUBJECTã€�ISSUERå’�CIPHER选项ï¼�

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
    -> IDENTIFIED BY 'goodsecret'
    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
       O=MySQL demo client certificate/
       CN=Tonu Samuel/[email protected]'
    -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
       O=MySQL Finland AB/CN=Tonu Samuel/[email protected]'
    -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

请注æ„�SUBJECTå’�ISSUER值应做为单一字符串输入ã€�

åœ�MySQL 5.1ä¸�,åœ�REQUIRE选项之间可以选用AND关键字ã€�

选项的顺序不重要,但任何选项不能用两次ã€�

5.8.7.6. SSL命令行选项

下面列出了规å®�SSL、证书文件和密钥文件使用的选项。它们可以位于命令行中或选项文件中ã€�

·         --ssl

对于服务器,该选项规定该服务器允许SSL连接。对于客户端程序,它允许客户使用SSL连接服务器。单单该选项不足以使ç”�SSL连接。还必须指定--ssl-caã€�--ssl-certå’�--ssl-key选项ã€�

通常从反向使用该选项表示不应使用SSL。要想实现,将选项指定ä¸�--skip-sslæˆ�--ssl=0ã€�

请注意使ç”�--sslä¸�需è¦�SSL连接。例如,如果编译的服务器或客户不支持SSL,则使用普通的未加密的连接ã€�

确保使用SSL连接的安全方式是使用å��REQUIRE SSL子句çš�GRANT语句在服务器上创建一个账户。然后使用该账户来连接服务器,服务器和客户端均应启用SSL支持ã€�

·         --ssl-ca=file_name

含可ä¿�SSL CA的清单的文件的路径ã€�

·         --ssl-capath=directory_name

包含pem格式的可ä¿�SSL CA证书的目录的路径ã€�

·         --ssl-cert=file_name

SSL证书文件名,用于建立安全连接ã€�

·         --ssl-cipher=cipher_list

允许的用äº�SSL加密的密码的清单ã€�cipher_list的格式与OpenSSL ciphers命令相同ã€�

示例ï¼�--ssl-cipher=ALL:-AES:-EXP

·         --ssl-key=file_name

SSL密钥文件名,用于建立安全连接ã€�

5.8.7.7. 用SSH以远程方式从Windows连接到MySQL

本节说明如何ç”�SSH安全连接到远ç¨�MySQL服务å™�(David Carlson <dcarlson@mplcommã€�com>)ï¼�

1.    åœ�Windows主机上安è£�SSH客户端。作为用户,我所发现的最好的非免费客户端来自http://www.vandyke.com/çš�SecureCRT。另一个选则æ˜�http://www.f-secure.com/çš�f-secure。你还可以从http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cryptography/SSH/Clients/Windows/ çš�Google找到一些免费客户端ã€�

2.    启动Windows SSH客户端。设ç½�Host_Name = yourmysqlserver_URL_or_IP。设ç½�userid=your_userid以便登录服务器。此userid值可以与你的MySQL账户的用户名不相同ã€�

3.    设置端口映射。可以进行远程映å°�(设置local_port: 3306, remote_host: yourmysqlservername_or_ip, remote_port: 3306)或本地映å°�(设置port: 3306, host: localhost, remote port: 3306)ã€�

4.    进行保存,否则下次需要重设ã€�

5.    刚创建的SSH会话登录服务器ã€�

6.    åœ�Windows机器上启动相åº�ODBC应用程序(例如Access)ã€�

7.    åœ�Windows中创建一个新的文件按照常用方法通过ODBC驱动程序链接MySQL,不同的是要ä¸�MySQL服务器输å…�localhost,而不æ˜�yourmysqlservernameã€�

你应有使ç”�SSH加密çš�ODBC连接åˆ�MySQLã€�

5.9. 备份与恢å¤�

本节讨论如何进行数据库备ä»�(完全备份和增量备ä»�),以及如何执行表的维护。本节描述的SQL语句语法参见ç¬�5章:数据库管ç��。此处提供的大多数信息主要适合MyISAM表ã€�InnoDB备份程序参见15.2.8节,“InnoDB数据库的备份和恢å¤�â€�ã€�

5.9.1. 数据库备ä»�

因为MySQL表保存为文件方式,很容易备份。要想保持备份的一致性,对相关表执行LOCK TABLES操作,然后对表执è¡�FLUSH TABLES。参è§�13.4.5节,“LOCK TABLES和UNLOCK TABLES语法â€�å’�13.5.5.2节,“FLUSH语法â€�。你只需要读锁定;这样当你复制数据库目录中的文件时,允许其它客户继续查询表。需è¦�FLUSH TABLES语句来确保开始备份前将所有激活的索引页写入硬盘ã€�

如果你想要进è¡�SQL级别的表备份,你可以使用SELECT INTO ...OUTFILEæˆ�BACKUP TABLE。对äº�SELECT INTO ...OUTFILEï¼� 输出的文件不能先存在。对äº�BACKUP TABLE也如此,因为覆盖完整的文件会有安全风险。参è§�13.2.7节,“SELECT语法â€�å’�13.5.2.2节,“BACKUP TABLE语法â€�ã€�

备份数据库的另一个技术是使用mysqldump程序æˆ�mysqlhotcopy脚本。参è§�8.8节,“mysqldump:数据库备份程序â€�å’�8.9节,“mysqlhotcopy:数据库备份程序â€�ã€�

1.    完全备份数据库:

2.            shell> mysqldump --tab=/path/to/some/dir --opt db_name

或:

shell> mysqlhotcopy db_name /path/to/some/dir

只要服务器不再进行更新,还可以只复制所有表文件(*.frmã€�*.MYDå’�*.MYI文件)ã€�mysqlhotcopy脚本使用该方法ã€�(但请注意如果数据库包å��InnoDB表,这些方法不工作ã€�InnoDB不将表的内容保存到数据库目录中,mysqlhotcopy只适合MyISAM表)ã€�

3.    如果mysqld在运行则停止,然后用--log-bin[=file_name]选项来启动。参è§�5.11.3节,“二进制日志â€�。二进制日志文件中提供了  执行mysqldump之后对数据库的更改进行复制所需要的信息ã€�

对于InnoDB表,可以进行在线备份,不需要对表进行锁定;参见8.8节,“mysqldump:数据库备份程序â€�ã€�

MySQL支持增量备份:需要用--log-bin选项来启动服务器以便启用二进制日志;参见5.11.3节,“二进制日志â€�。当想要进行增量备份æ—�(包含上一次完全备份或增量备份之后的所有更æ”�),应使用FLUSH LOGS回滚二进制日志。然后,你需要将从最后的完全或增量备份的某个时刻到最后某个点的所有二进制日志复制到备份位置。这些二进制日志为增量备份;恢复时,按照下面的解释应用。下次进行完全备份时,还应使ç”�FLUSH LOGSæˆ�mysqlhotcopy --flushlogs回滚二进制日志。参è§�8.8节,“mysqldump:数据库备份程序â€�å’�8.9节,“mysqlhotcopy:数据库备份程序â€�ã€�

如果MySQL服务器为从复制服务器,则无论选择什么备份方法,当备份从机数据时,还应备ä»�master.infoå’�relay-log.info文件。恢复了从机数据后,需要这些文件来继续复制。如果从机执行复åˆ�LOAD DATA INFILE命令,你应还备份ç”�--slave-load-tmpdir选项指定的目录中çš�SQL_LOAD-*文件ã€�(如果未指定,该位置默认为tmpdir变量值)ã€�从机需要这些文件来继续复制中断çš�LOAD DATA INFILE操作ã€�

如果必须恢复MyISAM表,先使ç”�REPAIR TABLEæˆ�myisamchk -r来恢复ã€�99.9%的情况下该方法可以工作。如æž�myisamchk失败,试试下面的方法。请注意只有ç”�--log-bin选项启动äº�MySQL从而启用二进制日志它才工作;参è§�5.11.3节,“二进制日志â€�ã€�

1.    恢复åŽ�mysqldump备份,或二进制备份ã€�

2.    执行下面的命令重新更新二进制日志ï¼�

3.            shell> mysqlbinlog hostname-bin.[0-9]* | mysql

在某些情况下,你可能只想要从某个位置重新运行某些二进制日志ã€�(通常你想要从恢复备份的日期重新运行所有二进制日志,查询不正确时例å¤�)。关äº�mysqlbinlog工具和如何使用它的详细信息参è§�8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具â€�ã€�

还可以对具体文件进行选择备份ï¼�

·         要想复制表,使用SELECT * INTO OUTFILE 'file_name' FROM tbl_nameã€�

·         要想重载表,使用LOAD DATA INFILE 'file_name' REPLACE ...并恢复。要避免复制记录,表必须æœ�PRIMARY KEY或一ä¸�UNIQUE索引。当新记录复制唯一键值的旧记录时ï¼�REPLACE关键字可以将旧记录替换为新记录ã€�

如果备份时遇到服务器性能问题,可以有帮助的一个策略是在从服务器而不是主服务器上建立复制并执行备份。参è§�6.1节,“复制介绍â€�ã€�

如果使用Veritas文件系统,可以这样备份:

1.    从客户端程序执行FLUSH TABLES WITH READ LOCKã€�

2.    从另一ä¸�shell执行mount vxfs snapshotã€�

3.    从第一个客户端执行UNLOCK TABLESã€�

4.    从快照复制文件ã€�

5.    卸载快照ã€�

5.9.2. 示例用备份与恢复策略

本节讨论进行备份的程序,在出现崩溃后,可以恢复数据:

·         操作系统崩溃

·         电源故障

·         文件系统崩溃

·         硬件问题(硬盘、母板等ç­�)

该命令不包括mysqldumpå’�mysql程序çš�--userå’�â€�password等选项。应包括必要的选项è®�MySQL服务器允许你连接它ã€�

我们假定数据保存åœ�MySQLçš�InnoDB存储引擎中,支持事务和自动崩溃恢复。我们假定崩溃时MySQL服务器带负载。如果不带负载,则不需要恢复ã€�

出现操作系统崩溃或电源故障时,我们可以假定重启后硬盘上的MySQLś数据仍可用。由于崩溃,InnoDB数据文件中的数据可能不再保持一致性,ä½�InnoDB读取它的日志并会查到挂起的提交的和未提交的事务清单,它们没有清空到数据文件中ã€�InnoDB自动卷回未提交的事务,并清空到它的数据文件中。通过MySQL错误日志将该恢复过程相关信息传达给用户。下面的例子为日志摘录:

InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

如果文件系统崩溃或出现硬件问题,我们可以假定重启后硬盘上çš�MySQLś数据不可用。这说明MySQL未能成功启动,因为一些硬盘数据块不再可读。在这种情况下,需要重新格式化硬盘,安装一个新的,或纠正问题。然后需要从备份中恢å¤�MySQL数据,这说明我们必须先做好备份。要想确保,应及时返回并设计备份策略ã€�

5.9.2.1. 备份策略

我们都知道必须按计划定期进行备份。可以用几个工具完全备份(在某个时间点的数据快ç…�)MySQL。例如,InnoDB Hot Backupä¸�InnoDB数据文件提供在线非数据块物理备份ï¼�mysqldump提供在线逻辑备份。这里使ç”�mysqldumpã€�

假定我们在星期日下午1点进行了备份,此时负荷较低。下面的命令可以完全备份所有数据库中的所æœ�InnoDB表:

shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql

这是在线非块备份,不会干扰对表的读写ã€�我们以前假定我们的表ä¸�InnoDB表,因此--single-transaction使用一致性地读,并且保证mysqldump所看见çš�数据不会更改ã€�(其它客户端对InnoDB表进行的更改不会è¢�mysqldump进程看见ï¼�ã€�如果我们还有其它类型的表,我们必须假定在备份过程中它们不会更改。例如,对于mysql数据库中çš�MyISAMè¡�,我们必须假定在备份过程中没有对MySQL账户进行管理更改ã€�

mysqldump命令产生çš�.sql文件包含一系列SQL INSERT语句,可以用来重载转储的表ã€�

需要进行完全备份,但有时不方便。会产生大的备份文件并需要花时间来生成。从某个角度,完全备份并不理想,因为每个成功的完全备份包括所有数据,甚至自从上一次完全备份以来没有更改的部分。完成了初使完全备份后,进行增量备份会更有效。这样备份文件要小得多,备份时间也较短。不利之处是,恢复时不能只重载完全备份来恢复数据。还必须要用增量备份来恢复增量更改ã€�

要想进行增量备份,我们需要保存增量更改。应使用--log-bin选项启动MySQL服务器,以便更新数据时将这些更改保存到文件中。该选项启用二进制日志,因此服务器写将每个更新数据的SQL语句写入MySQL二进制日志。让我们看看ç”�--log-bin选项启动的已经运行多日的MySQL服务器的数据目录。我们找到以ä¸�MySQL二进制日志文件:

-rw-rw---- 1 guilhem  guilhem   1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem  guilhem         4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem  guilhem        79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem  guilhem       508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem  guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem  guilhem    998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem  guilhem       361 Nov 14 10:07 gbichot2-bin.index

每次重启ï¼�MySQL服务器用序列中的下一个编号创建一个新的二进制日志文件。当服务器运行时,你还可以通过执行FLUSH LOGS SQL语句æˆ�mysqladmin flush-logs命令,告诉服务器关闭当前的二进制日志文件并创建一个新文件ã€�mysqldump也有一个选项来清空日志。数据目录中çš�.index文件包含该目录下所æœ�MySQL二进制日志的清单。该文件用于复制ã€�

恢复æ—�MySQL二进制日志很重要,因为它们是增量备份。如果进行完全备份时确保清空了日志,则后面创建的二进制日志文件包含了备份后的所有数据更改。让我们稍稍修改前面çš�mysqldump命令,让它在完全备份时能够清ç©� MySQL二进制日志,以便转储文件包含包含新的当前的二进制日志ï¼�

shell> mysqldump --single-transaction --flush-logs --master-data=2
           --all-databases > backup_sunday_1_PM.sql

执行该命令后,数据目录则包含新的二进制日志文件,gbichot2-bin.000007。结æž�.sql文件包含下列行:

-- Position to start replication or point-in-time 恢复æ—�y from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;

因为mysqldump命令可以执行完全备份,这些行表示两件事情ï¼�

·         .sql文件包含所有写å…�gbichot2-bin.000007二进制日志文件或最新的文件之前的更改ã€�

·         备份后所记录的所有数据更改不出现åœ�.sql中,但出现在gbichot2-bin.000007二进制日志文件或最新的文件中ã€�

在星期一下午1点,我们可以清空日志开始新的二进制日志文件来创建增量备份。例如,执行mysqladmin flush-logs命令创建gbichot2-bin.000008。星期日下午1点的完全备份和星期一下午1点之间的所有更改为文件gbichot2-bin.000007。该增量备份很重要,因此最好将它复制到安全的地方ã€�(例如,备份到磁带æˆ�DVD上,或复制到另一台机器上ï¼�ã€�在星期二下午1点,执行另一ä¸�mysqladmin flush-logs命令。星期一下午1点和星期二下å��1点之间的所有所有更改为文件gbichot2-bin.000008(也应复制到某个安全的地方)ã€�

MySQL二进制日志占据硬盘空间。要想释放空间,应随时清空。操作方法是删掉不再使用的二进制日志,例如进行完全备份时ï¼�

shell> mysqldump --single-transaction --flush-logs --master-data=2
           --all-databases --delete-master-logs > backup_sunday_1_PM.sql

æ³�释:如果你的服务器为复制主服务器,用mysqldump --delete-master-logs删掉MySQL二进制日志很危险,因为从服务器可能还没有完全处理该二进制日志的内容ã€�

PURGE MASTER LOGS语句的描述中解释了为什么在删掉MySQL二进制日志之前应进行确认。参è§�13.6.1.1节,“PURGE MASTER LOGS语法â€�ã€�

5.9.2.2. 为恢复进行备ä»�

现在假设在星期三上午8点出现了灾难性崩溃,需要使用备份文件进行恢复。恢复时,我们首先恢复最后的完全备份(从星期日下午1点开å§�)。完全备份文件是一系列SQL语句,因此恢复它很容易:

shell> mysql < backup_sunday_1_PM.sql

在该点,数据恢复到星期日下午1点的状态。要想恢复从那时起的更改,我们必须使用增量备份,也就是,gbichot2-bin.000007å’�gbichot2-bin.000008二进制日志文件。根据需要从备份处取过这些文件,然后按下述方式处理:

shell> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql

我们现在将数据恢复到星期二下å��1点的状态,但是从该时刻到崩溃之间的数据仍然有丢失。要想恢复,我们需è¦�MySQL服务器将MySQL二进制日志保存到安全的位ç½�(RAID disks, SAN, ...),应为与数据文件的保存位置不同的地方,保证这些日志不在毁坏的硬盘上ã€�(也就是,我们可以ç”�--log-bin选项启动服务器,指定一个其它物理设备上的与数据目录不同的位置。这样,即使包含该目录的设备丢失,日志也不会丢失ï¼�ã€�如果我们执行了这些操作,我们手头上会æœ�gbichot2-bin.000009文件,我们可以用它来恢复大部分最新的数据更改,而不会丢失到崩溃时的数据ã€�

5.9.2.3. 备份策略摘要

出现操作系统崩溃或电源故障时ï¼�InnoDB自己可以完成所有数据恢复工作。但为了确保你可以睡好觉,应遵从下面的指导:

·         一定用--log-bin或甚è‡�--log-bin=log_name选项运行MySQL服务器,其中日志文件名位于某个安全媒介上,不同于数据目录所在驱动器。如果你有这样的安全媒介,最好进行硬盘负载均è¡�(这样能够提高性能)ã€�

·         定期进行完全备份,使ç”�mysqldump命令进行在线非块备份ã€�

·         ç”�FLUSH LOGSæˆ�mysqladmin flush-logs清空日志进行定期增量备份ã€�

5.9.3. 自动恢复

如果MySQL服务器启用了二进制日志,你可以使ç”�mysqlbinlog工具来恢复从指定的时间点开å§� (例如,从你最后一次备ä»�)直到现在或另一个指定的时间点的数据。关于启用二进制日志的信息,参见5.11.3节,“二进制日志â€�。对äº�mysqlbinlog的详细信息,参见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具â€�ã€�

要想从二进制日志恢复数据,你需要知道当前二进制日志文件的路径和文件名。一般可以从选项文件(å��my.cnf or my.ini,取决于你的系统)中找到路径。如果未包含在选项文件中,当服务器启动时,可以在命令行中以选项的形式给出。启用二进制日志的选项ä¸�--log-bin。要想确定当前的二进制日志文件的文件名,输入下面çš�MySQL语句ï¼�

SHOW BINLOG EVENTS \G

你还可以从命令行输入下面的内容:

mysql --user=root -pmy_pwd -e 'SHOW BINLOG EVENTS \G'

将密ç �my_pwd替换为服务器çš�root密码ã€�

5.9.3.1. 指定恢复时间

对于MySQL 4.1.4,可以在mysqlbinlog语句中通过--start-dateå’�--stop-date选项指定DATETIME格式的起止时间。举例说明,假设在今天上å��10:00(今天æ˜�2005å¹�4æœ�20æ—�),执è¡�SQL语句来删除一个大表。要想恢复表和数据,你可以恢复前晚上的备份,并输入:
mysqlbinlog --stop-date="2005-04-20 9:59:59" /var/log/mysql/bin.123456 \
     | mysql -u root -pmypwd

该命令将恢复截止到在--stop-date选项中以DATETIME格式给出的日期和时间的所有数据。如果你没有检测到几个小时后输入的错误çš�SQL语句,可能你想要恢复后面发生的活动。根据这些,你可以用起使日期和时间再次运è¡�mysqlbinlogï¼�

mysqlbinlog --start-date="2005-04-20 10:01:00" /var/log/mysql/bin.123456 \
     | mysql -u root -pmypwd \

在该行中,从上午10:01登录çš�SQL语句将运行。组合执行前夜的转储文件å’�mysqlbinlog的两行可以将所有数据恢复到上午10:00前一秒钟。你应检查日志以确保时间确切。下一节介绍如何实现ã€�

5.9.3.2. 指定恢复位置

也可以不指定日期和时间,而使ç”�mysqlbinlog的选项--start-positionå’�--stop-position来指定日志位置。它们的作用与起止日选项相同,不同的是给出了从日志起的位置号。使用日志位置是更准确的恢复方法,特别是当由于破坏æ€�SQL语句同时发生许多事务的时候。要想确定位置号,可以运è¡�mysqlbinlog寻找执行了不期望的事务的时间范围,但应将结果重新指向文本文件以便进行检查。操作方法为ï¼�
mysqlbinlog --start-date="2005-04-20 9:55:00" --stop-date="2005-04-20 10:05:00" \
      /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql

该命令将åœ�/tmp目录创建小的文本文件,将显示执行了错误的SQL语句时的SQL语句。你可以用文本编辑器打开该文件,寻找你不要想重复的语句。如果二进制日志中的位置号用于停止和继续恢复操作,应进行注释。用log_pos加一个数字来标记位置。使用位置号恢复了以前的备份文件后,你应从命令行输入下面内容ï¼�

mysqlbinlog --stop-position="368312" /var/log/mysql/bin.123456 \
    | mysql -u root -pmypwd 
 
mysqlbinlog --start-position="368315" /var/log/mysql/bin.123456 \
    | mysql -u root -pmypwd \ 

上面的第1行将恢复到停止位置为止的所有事务。下一行将恢复从给定的起始位置直到二进制日志结束的所有事务。因ä¸�mysqlbinlog的输出包括每ä¸�SQL语句记录之前çš�SET TIMESTAMP语句,恢复的数据和相å…�MySQL日志将反应事务执行的原时间ã€�

5.9.4. 表维护和崩溃恢复

后面几节讨论如何使用myisamchk来检查或维护MyISAMè¡�(对应.MYIå’�.MYD文件的表)ã€�

你可以使ç”�myisamchk实用程序来获得有关你的数据库表的信息或检查、修复、优化他们。下列小节描述如何调ç”�myisamchk(包括它的选项的描述),如何建立表的维护计划,以及如何使用myisamchk执行各种功能ã€�

尽管ç”�myisamchk修复表很安全,在修复(或任何可以大量更改表的维护操ä½�)之前先进行备ä»�也是很好的习æƒ�

影响索引çš�myisamchk操作会使ULLTEXT索引ç”�full-text参数重建,不再与MySQL服务器使用的值兼容。要想避免,请阅è¯�5.9.5.1节,“用于myisamchk的一般é€�é¡�â€�的说明ã€�

在许多情况下,你会发现使ç”�SQL语句实现MyISAM表的维护比执è¡�myisamchk操作要容易地多:

·         要想检查或维护MyISAM表,使用CHECK TABLEæˆ�REPAIR TABLEã€�

·         要想优化MyISAM表,使用OPTIMIZE TABLEã€�

·         要想分析MyISAM表,使用ANALYZE TABLEã€�

可以直接这些语句,或使用mysqlcheck客户端程序,可以提供命令行接口ã€�

这些语句æ¯�myisamchk有利的地方是服务器可以做任何工作。使ç”�myisamchk,你必须确保服务器在同一时间不使用表。否则,myisamchk和服务器之间会出现不期望的相互干涉ã€�

5.9.5. myisamchk:MyISAM表维护实用工å…�

可以使用myisamchk实用程序来获得有关数据库表的信息或检查、修复、优化他们ã€�myisamchk适用MyISAMè¡�(对应.MYIå’�.MYD文件的表)ã€�

调用myisamchk的方法:

shell> myisamchk [options] tbl_name ...

options指定你想è®�myisamchk做什么。在后面描述它们。还可以通过调用myisamchk --help得到选项列表ã€�

tbl_name是你想要检查或修复的数据库表。如果你不在数据库目录的某处运行myisamchk,你必须指定数据库目录的路径,因ä¸�myisamchk不知道你的数据库位于哪儿。实际上ï¼�myisamchk不在乎你正在操作的文件是否位于一个数据库目录;你可以将对应于数据库表的文件拷贝到别处并且在那里执行恢复操作ã€�

如果你愿意,可以ç”�myisamchk命令行命名几个表。还可以通过命名索引文件(ç”�â€� .MYIâ€�后缀)来指定一个表。它允许你通过使用模式â€�*.MYIâ€�指定在一个目录所有的表。例如,如果你在数据库目录,可以这样在目录下检查所有的MyISAM表:

shell> myisamchk *.MYI

如果你不在数据库目录下,可通过指定到目录的路径检查所有在那里的表ï¼�

shell> myisamchk /path/to/database_dir/*.MYI

你甚至可以通过ä¸�MySQL数据目录的路径指定一个通配符来检查所有的数据库中的所有表ï¼�

shell> myisamchk /path/to/datadir/*/*.MYI

推荐的快速检查所æœ�MyISAM表的方式是:

shell> myisamchk --silent --fast /path/to/datadir/*/*.MYI

如果你想要检查所æœ�MyISAM表并修复任何破坏的表,可以使用下面的命令ï¼�

shell> myisamchk --silent --force --fast --update-state \
          -O key_buffer=64M -O sort_buffer=64M \
          -O read_buffer=1M -O write_buffer=1M \
          /path/to/datadir/*/*.MYI

该命令假定你有大äº�64MB的自由内存。关于用myisamchk分配内存的详细信息,参见5.9.5.5节,â€�myisamchk内存使用â€�ã€�

当你运行myisamchk时,必须确保其它程序不使用表。否则,当你运行myisamchk时,会显示下面的错误消息ï¼�

warning: clients are using or haven't closed the table properly

这说明你正尝试检查正被另一个还没有关闭文件或已经终止而没有正确地关闭文件的程åº�(例如mysqld服务å™�)更新的表ã€�

如果mysqld正在运行,你必须通过FLUSH TABLES强制清空仍然在内存中的任何表修改。当你运è¡�myisamchk时,必须确保其它程序不使用表。避免该问题的最容易的方法是使用CHECK TABLE而不ç”�myisamchk来检查表ã€�

5.9.5.1. 用于myisamchk的一般é€�é¡�

本节描述的选项可以用于ç”�myisamchk执行的任何类型的表维护操作。本节后面的章节中描述的选项只适合具体操作,例如检查或修复表ã€�

·         --helpï¼�-?

显示帮助消息并退出ã€�

·         --debug=debug_options, -# debug_options

输出调试记录文件ã€�debug_options字符串经常是'd:t:o,filename'ã€�

·         --silentï¼�-s

沉默模式。仅当发生错误时写输出。你能使ç”�-s两次(-ss)ä½�myisamchk沉默ã€�

·         --verboseï¼�-v

冗长模式。打印更多的信息。这能与-då’�-e一起使用。为了更冗长,使ç”�-v多次(-vv, -vvv)ï¼�

·         --version, -V

显示版本信息并退出ã€�

·         --wait, -w

如果表被锁定,不是提示错误终止,而是在继续前等待到表被解锁。请注意如果ç”�--skip-external-locking选项运行mysqld,只能用另一ä¸�myisamchk命令锁定表ã€�

还可以通过--var_name=value选项设置下面的变量:

变量

默认å€�

decode_bits

9

ft_max_word_len

取决于版æœ�

ft_min_word_len

4

ft_stopword_file

内建列表

key_buffer_size

523264

myisam_block_size

1024

read_buffer_size

262136

sort_buffer_size

2097144

sort_key_blocks

16

stats_method

nulls_unequal

write_buffer_size

262136

可以ç”�myisamchk --help检æŸ�myisamchk变量及其 默认值:

当用排序键值修复键值时使用sort_buffer_size,使ç”�--recover时这是很普通的情况ã€�

当用--extend-check检查表或通过一行一行地将键值插入表ä¸�(如同普通插å…�)来修改键值时使用Key_buffer_size。在以下情况通过键值缓冲区进行修复ï¼�

·         使用--safe-recoverã€�

·         当直接创建键值文件时,需要对键值排序的临时文件有两倍大。通常是当CHARã€�VARCHAR、或TEXT列的键值较大的情况,因为排序操作在处理过程中需要保存全部键值。如果你有大量临时空间,可以通过排序强制使用myisamchk来修复,可以使用--sort-recover选项ã€�

通过键值缓冲区的修复占用的硬盘空间比使用排序么少,但是要慢ã€�

如果想要快速修复,å°�key_buffer_sizeå’�sort_buffer_size变量设置到大约可用内存的25%。可以将两个变量设置为较大的值,因为一个时间只使用一个变量ã€�

myisam_block_size是用于索引块的内存大小ã€�

stats_method影响当给å®�--analyze选项时,如何为索引统计搜集处ç��NULL值。它如同myisam_stats_method系统变量。详细信息参è§�5.3.3节,“服务器系统变量â€�å’�7.4.7节,“MyISAM索引统计集合â€�çš�myisam_stats_method的描述ã€�

ft_min_word_lenå’�ft_max_word_len表示FULLTEXT索引的最小和最大字长ã€�ft_stopword_file为停止字文件的文件名。需要在以下环境中对其进行设置ã€�

如果你使ç”�myisamchk来修改表索引(例如修复或分æž�),使用最小和最大字长和停止字文件的 默认全文参数值(除非你另外指定)重建FULLTEXT索引。这样会导致查询失败ã€�

出现这些问题是因为只有服务器知道这些参数。它们没有保存在MyISAM索引文件中。如果你修改了服务器中的最小或最大字长或停止字文件,要避免该问题,为用于mysqldçš�myisamchk指定相同çš�ft_min_word_lenï¼�ft_max_word_lenå’�ft_stopword_file值。例如,如果你将最小字长设置为3,可以这样使用myisamchk来修复表ï¼�

shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI

要想确保myisamchk和服务器使用相同的全文参数值,可以将它们放入选项文件çš�[mysqld]å’�[myisamchk]小节ï¼�

[mysqld]
ft_min_word_len=3
 
[myisamchk]
ft_min_word_len=3

除了myisamchk,还可以使用REPAIR TABLEã€�ANALYZE TABLEã€�OPTIMIZE TABLEæˆ�ALTER TABLE。这些语句由服务器执行,知道要使用的正确的全文参数值ã€�

5.9.5.2. 用于myisamchk的检查选项

myisamchk支持下面的表检查操作选项ï¼�

·         --check, -c

检查表的错误。如果你不明确指定操作类型选项,这就是默认操作ã€�

·         --check-only-changed, -C

只检查上次检查后有变更的表ã€�

·         --extend-check, -e

非常仔细地检查表。如果表有许多索引将会相当慢。该选项只能用于极端情况。一般情况下,可以使ç”�myisamchkæˆ�myisamchk --medium-check来确定表内是否有错误ã€�

如果你使用了--extend-check并且有充分的内存,将key_buffer_size变量设置为较大的值可以使修复操作运行得更快ã€�

·         --fastï¼�-F

只检查没有正确关闭的表ã€�

·         --force, -f

如果myisamchk发现表内有任何错误,则自动进行修复。维护类型与--repairæˆ�-r选项指定的相同ã€�

·         --information, -i

打印所检查表的统计信息ã€�

·         --medium-check, -m

æ¯�--extend-check更快速地进行检查。只能发çŽ�99.99%的错误,在大多数情况下就足够了ã€�

·         --read-only, -T

不要将表标记为已经检查。如果你使用myisamchk来检查正被其它应用程序使用而没有锁定的表很有用,例如当ç”�--skip-external-locking选项运行时运è¡�mysqldã€�

·         --update-state, -U

将信息保存在.MYI文件中,来表示表检查的时间以及是否表崩溃了。该选项用来充分利用--check-only-changed选项,但如果mysqld服务å™�正使用表并且正用--skip-external-locking选项运行时不应使用该选项ã€�

5.9.5.3. myisamchk的修复选项

myisamchk支持下面的表修复操作的选项ï¼�

·         --backup, -B

å°�.MYD文件备份ä¸�file_name-time.BAK

·         --character-sets-dir=path

字符集安装目录。参è§�5.10.1节,“数据和排序用字符集â€�ã€�

·         --correct-checksum

纠正表的校验和信息ã€�

·         --data-file-length=len, -D len

数据文件的最大长åº�(当重建数据文件且为“满”时)ã€�

·         --extend-checkï¼�-e

进行修复,试图从数据文件恢复每一行。一般情况会发现大量的垃圾行。不要使用该选项,除非你不顾后果ã€�

·         --force, -f

覆盖旧的中间文件(文件名类ä¼�tbl_name.TMD),而不是中断ã€�

·         --keys-used=val, -k val

对于myisamchk,该选项值为位值,说明要更新的索引。选项值的每一个二进制位对应表的一个索引,其中第一个索引对应位0。选项å€�0禁用对所有索引的更新,可以保证快速插入。通过myisamchk -r可以重新激活被禁用的索引ã€�

·         --no-symlinks, -l

不跟随符号连接。通常myisamchk修复一个符号连接所指的表。在MySQL 4.0中该选项不存在,因为ä»�4.0开始的版本在修复过程中不移除符号链接ã€�

·         --parallel-recover, -p

ä¸�-rå’�-n的用法相同,但使用不同的线程并行创建所有键ã€�这是alpha代码。自己承担风险!

·         --quickï¼�-q

不修改数据文件,快速进行修复。出现复制键时,你可以两次指定该项以强制myisamchk修改原数据文件ã€�

·         --recover, -r

可以修复几乎所有一切问题,除非唯一的键不唯一æ—�(对于MyISAM表,这是非常不可能的情况)。如果你想要恢复表,这是首先要尝试的选项。如æž�myisamchk报告表不能用-r恢复,则只能尝试-o。在不太可能的情况下-r失败,数据文件保持完好)ã€�

如果你有大量内存,你应增åŠ�sort_buffer_size的å€�ã€�

·         --safe-recover, -o

使用一个老的恢复方法读取,按顺序读取所有行,并根据找到的行更新所有索引树。这æ¯�-r慢些,但是能处理-r不能处理的情况。该恢复方法使用的硬盘空间比-r少。一般情况,你应首先ç”�-r维修,如æž�-r失败则用-oã€�

如果你有大量内存,你应增åŠ�sort_buffer_size的å€�ã€�

·         (OBSOLETE) --set-character-set=name

åœ�MySQL 5.1中不使用。参è§�--set-collationã€�

·         --set-collation=name

更改用来排序表索引的校对规则。校对规则名的第一部分包含字符集名ã€�

·         --sort-recover, -n

强制myisamchk通过排序来解析键值,即使临时文件将可能很大ã€�

·         --tmpdir=path, -t path

用于保存临时文件的目录的路径。如果未设置ï¼�myisamchk使用TMPDIR环境变量的值ã€�tmpdir可以设置为一系列目录路径,用于成功地ä»�round-robin模式创建临时文件。在Unix中,目录名之间的间隔字符为冒å��(â€�:â€�),在Windowsã€�NetWareå’�OS/2中为分号 (â€�ï¼�â€�)ã€�

·         --unpackï¼�-u

将用myisampack打包的表解包ã€�

5.9.5.4. 用于myisamchk的其它选项

myisamchk支持以下表检查和修复之外的其它操作的选项ï¼�

·         --analyzeï¼�-a

分析键值的分布。这通过让联结优化器更好地选择表应该以什么次序联结和应该使用哪个键来改进联结性能。要想获取分布相关信息,使用myisamchk --description --verbose tbl_name命令æˆ�SHOW KEYS FROM tbl_name语句ã€�

·         --description, -d

打印出关于表的描述性信息ã€�

·         --set-auto-increment[=value], -A[value]

强制从给定值开始的新记录使ç”�AUTO_INCREMENT编号(或如果已经有AUTO_INCREMENT值大小的记录,应使用更高å€�)。如果未指定value,新记录çš�AUTO_INCREMENT编号应使用当前表的最大值加ä¸�1ã€�

·         --sort-index, -S

以从高到低的顺序排序索引树块。这将优化搜寻并且将使按键值的表扫描更快ã€�

·         --sort-records=N, -R N

根据一个具体索引排序记录。这使你的数据更局部化并且可以加快在该键上çš�SELECTå’�ORDER BY的范围搜紀€‚(第一次做排序可能很慢!)为了找出一张表的索引编号,使用SHOW INDEX,它ä»�myisamchk看见他们的相同顺序显示一张表的索引。索引从1开始编号ã€�

如果键没有打åŒ�(PACK_KEYS=0),它们的长度相同,因此当myisamchk 排序并移动记录时,只覆盖索引中的记录偏移量。如果键已经打包(PACK_KEYS=1)ï¼�myisamchk必须先解开打包的键块,然后重新创建索引并再次将键块打包ã€�(在这种情况下,重新创建索引比更新每个索引的偏移量要快ï¼�ã€�

5.9.5.5. myisamchk内存使用

当你运行myisamchk时内存分配重è¦�.MYIsamchk使用的内存大小不能超过用-O选项指定的。如果你想对每一个大表使ç”�myisamchk,你必须首先确定你想使用多少内存。修复时可以使用çš� 默认值只æœ�3MB。使用更大的内存,可以让myisamchk工作得更快一些。例如,如果有大äº�32MBçš�RAM,可以使用如下所示选项(除了你可以指定的其它选项)ï¼�

shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...

对于大多数情况,使用-O sort=16M应该足够了ã€�

应记ä½�myisamchk使用TMPDIR中的临时文件。如æž�TMPDIR指向内存文件系统,你可能很容易得到内存溢出的错误。如果发生,设定TMPDIR指向有更多空间的文件系统目录并且重启myisamchkã€�

修复æ—�myisamchk也需要大量硬盘空间:

·         将数据文件大小扩大一å€�(原文件和复制文件)。如果你ç”�--quick修复则不需要该空间;在这种情况下,只重新创建了索引文件。在文件系统上需要的空间与原数据文件相同ï¼�(创建的复制文件位于原文件所在目录)ã€�

·         代替旧索引文件的新索引文件所占空间。修复工作一开始,就对旧索引文件进行了删减,因此你通常会忽略该空间。在文件系统上需要的该空间与原数据文件相同!

·         当使ç”�--recoveræˆ�---sort-recover(但不使用--safe-recover)时,需要排序缓冲区空间。需要的空间为:

·                (largest_key + row_pointer_length) * number_of_rows * 2

可以ç”�myisamchk -dv tbl_name检查键值和row_pointer_length的长度。在临时目录分配该空é—�(ç”�TMPDIRæˆ�--tmpdir=path指定)ã€�

如果在修复过程中出现硬盘空间问题,可以试试用--safe-recover代替--recoverã€�

5.9.5.6. 将myisamchk用于崩溃æ��å¤�

如果ç”�--skip-external-locking运行mysqld(在某些系统上ä¸� 默认设置,例å¦�Linux),当mysqld使用某个表时,你不能可靠地使ç”�myisamchk来检查相同的表。当你运è¡�myisamchk时如果可以确保没有人在通过mysqld访问表,在开始检查表前,你只需要运è¡�mysqladmin flush-tables。如果你不能保证,则你检查表时你必须停止mysqld。如æž�mysqld更新表时运行myisamchk,你可能会获得表被破坏的警告,即使事实并非如此ã€�

如果不使ç”�--skip-external-locking,可以随时使ç”�myisamchk来检查表。当检查表时,所有尝试更新表的客户端将等待,直到myisamchk准备好可以继续ã€�

如果使用myisamchk来修复或优化表,必须确保mysqld服务å™�没有在使用该è¡�(如果你正使用--skip-external-locking选项也适用)。如果不关闭mysqld,在运行myisamchk之前至少应执è¡�mysqladmin flush-tables。如果服务器å’�myisamchk同时访问表,è¡�可能会被破坏ã€�

本节描述如何检查和处理MySQL数据库中的数据破坏。如果表经常被破坏,你应尽力找到原因。参è§�A.4.2节,“如果MySQL依然崩溃,应作些什么â€�ã€�

关于MyISAM表怎样会被破坏的解释,参见15.1.4节,“MyISAM表方面的问题â€�ã€�

在执行崩溃恢复时,理解在一个数据库中的每一ä¸�MyISAMè¡�tbl_name对应的在数据库目录中çš�3个文件是很重要的ï¼�

文件

目的

tbl_name.frm

定义(格式)文件

tbl_name.MYD

数据文件

tbl_name.MYI

索引文件

è¿�3类文件的每一类都可能遭受不同形式的损坏,但是问题最常发生在数据文件和索引文件ã€�

myisamchk通过一行一行地创建一ä¸�â€�.MYDâ€�数据文件的副本来工作,它通过删除旧的â€�.MYD 文件并且重命名新文件到原来的文件名结束修复阶段。如果你使用--quickï¼�myisamchk不创建一个临æ—�â€�.MYDâ€�文件,只是假å®�â€�.MYDâ€�文件是正确的并且仅创建一个新的索引文件,不接è§�â€�.MYDâ€�文件,这是安全的,因ä¸�myisamchk自动检æµ�â€�.MYDâ€�文件是否损坏并且在这种情况下,放弃修复。你也可以给myisamchk两个--quick选项。在这种情况下,myisamchk不会在一些错误上(象重复键)放弃,相反试图通过修改â€�.MYDâ€�文件解决它们。通常,只有在太少的空闲磁盘空间上实施正常修复,使用两ä¸�--quick选项时才有用。在这种情况下,你至少应该在运行myisamchk前做进行备份ã€�

5.9.5.7. 如何检查MyISAM表的错误

要想检æŸ�MyISAM表,应使用下面的命令ï¼�

·         myisamchk tbl_name

这样能找å‡�99.99%的错误。它不能找出的是仅仅涉及数据文件的损å��(这很不常è§�)。如果想要检查一张表,通常应该没有选项地运è¡�myisamchk或用-sæˆ�--silent选项的任何一个ã€�

·         myisamchk -m tbl_name

这样能找å‡�99.99%的错误。它首先检查所有索引条目的错误并通读所有行。它还计算行内所有键值的校验和,并确认校验和与索引树内键的校验和相匹配ã€�

·         myisamchk -e tbl_name

可以完全彻底地检查数æ��(-e意思是“扩展检查â€�)。它对每一行做每个键的读检查以证实它们确实指向正确的行。这在一个有很多键的大表上可能花很长时间ã€�myisamchk通常将在它发现第一个错误以后停歀€‚如果你想要获得更多的信息,可以增加--verbose(-v)选项。这使得myisamchk继续一直到最å¤�20个错误ã€�

·         myisamchk -e -i tbl_name

象前面的命令一样,但是-i选项告诉myisamchk还打印出一些统计信息ã€�

在一般使用中,一个简单的myisamchk(没有除表名以外的参数)就足够检查表了ã€�

5.9.5.8. 如何修复è¡�

本节描述如何å¯�MyISAM表使ç”�myisamchk(扩展å��.MYIå’�.MYD)ã€�

你还可以(并且应该,如果可èƒ�)使用CHECK TABLEå’�REPAIR TABLE语句来检查和修复MyISAM表。参è§�13.5.2.3节,“CHECK TABLE语法â€�å’�13.5.2.6节,“REPAIR TABLE语法â€�ã€�

一张损坏的表的症状通常是查询意外中断并且能看到下述错误ï¼�

  • â€�tbl_name.frmâ€�被锁定不能更改ã€�
  • 不能找到文件â€�tbl_name.MYIâ€�ï¼�Errcodeï¼�nnn)ã€�
  • 文件意外结束ã€�
  • 记录文件被毁坏ã€�
  • 从表处理器得到错è¯�nnnã€�

要想得到错误相关的详细信息,你可以运è¡�perror nnn,其ä¸�nnn为错误编号。下面的示例显示了如何使ç”�perror来找到最常用错误编号(用表的方式指出问题)的含义ï¼�

shell> perror 126 127 132 134 135 136 141 144 145
126 = Index file is crashed / Wrong file format
127 = Record-file is crashed
132 = Old database file
134 = Record was already deleted (or record file crashed)
135 = No more room in record file
136 = No more room in index file
141 = Duplicate unique key or constraint on write or update
144 = Table is crashed and last repair failed

145 = Table was marked as crashed and should be repaired

请注意错è¯�135(记录文件中没有更多的空间)和错è¯�136(索引文件中没有更多的空间)不是可以通过简单修复可以修复的错误。在这种情况下,必须使用ALTER TABLE来增åŠ�MAX_ROWSå’�AVG_ROW_LENGTH表选项值:

ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;

如果你不知道当前的表的选项值,使用SHOW CREATE TABLEæˆ�DESCRIBE来查è¯�ã€�

对于其它的错误,你必须修复表ã€�myisamchk通常可以检测和修复大多数问题ã€�

修复过程包括四个阶段,此处将进行描述。开始修复前,应进入数据库目录并检查表文件的许可。在Unix中,确保它们对于运行mysqldçš�用户可读(你也应可读,因为你需要访问检查的文件)。如果你需要修改文件,你还必须拥有写访问权限ã€�

ç”�myisamchk修复表的选项的描述参è§�5.9.5节,“myisamchk:MyISAM表维护实用工具â€�的前几节ã€�

下面几节列出了上述命令失败或你想要使ç”�myisamchk提供的扩展特性等情况的例子ã€�

如果你要通过命令行来修复表,必须首先停止mysqld服务å™�。请注意当你在远程服务器上运è¡�mysqladmin shutdown时,mysqladmin返回后,mysqld服务器将仍然运行一会儿,直到停止所有查询并将所有键清空到硬盘上ã€�

阶段1:检查你的表

如果你有很多时间,运è¡�myisamchk *.MYIæˆ�myisamchk -e *.MYI。使ç”�-s(沉默)选项禁止不必要的信息ã€�

如果mysqld服务器处于宕机状æ€�,应使用--update-state选项来告è¯�myisamchk将表标记ä¸�'检查过çš�'ã€�

你必须只修复那些myisamchk报告有错误的表。对这样的表,继续到阶段2ã€�

如果在检查时,你得到奇怪的错误(例如out of memory错误),或如果myisamchk崩溃,到阶段3ã€�

阶段2:简单安全的修复

注释:如果想更快地进行修复,当运è¡�myisamchk时,你应å°�sort_buffer_sizeå’�Key_buffer_size变量的值设置为可用内存的大çº�25%ã€�

首先,试è¯�myisamchk -r -q tbl_name(-r -q意味着“快速恢复模式â€�)。这将试图不接触数据文件来修复索引文件。如果数据文件包含它应有的一切内容和指向数据文件内正确地点的删除连接,这应该管用并且表可被修复。开始修复下一张表。否则,执行下列过程ï¼�

  1. 在继续前对数据文件进行备份ã€�
  2. 使用myisamchk -r tbl_name(-r意味着“恢复模式â€�)。这将从数据文件中删除不正确的记录和已被删除的记录并重建索引文件ã€�
  3. 如果前面的步骤失败,使用myisamchk --safe-recover tbl_name。安全恢复模式使用一个老的恢复方法,处理常规恢复模式不行的少数情况(但是更慢)ã€�

如果在修复时,你得到奇怪的错误(例如out of memory错误),或如果myisamchk崩溃,到阶段3ã€�

阶段3:困难的修复

只有在索引文件的第一ä¸�16K块被破坏,或包含不正确的信息,或如果索引文件丢失,你才应该到这个阶段。在这种情况下,需要创建一个新的索引文件。按如下步骤操做ï¼�

  1. 把数据文件移到安全的地方ã€�
  2. 使用表描述文件创建新çš�(ç©�)数据文件和索引文件:
  3. shell> mysql db_name
  4. mysql> SET AUTOCOMMIT=1;
  5. mysql> TRUNCATE TABLE tbl_name;
  6. mysql> quit

如果你的MySQL版本没有TRUNCATE TABLE,则使用DELETE FROM tbl_nameã€�

  1. 将老的数据文件拷贝到新创建的数据文件之中。(不要只是将老文件移回新文件之中;你要保留一个副本以防某些东西出错。)

回到阶段2。现åœ�myisamchk -r -q应该工作了。(这不应该是一个无限循环)ã€�

你还可以使用REPAIR TABLE tbl_name USE_FRM,将自动执行整个程序ã€�

阶段4:非常困难的修复

只有.frm描述文件也破坏了,你才应该到达这个阶段。这应该从未发生过,因为在表被创建以后,描述文件就不再改变了ã€�

  1. 从一个备份恢复描述文件然后回到阶æ®�3。你也可以恢复索引文件然后回到阶æ®�2。对后者,你应该用myisamchk -r启动ã€�
  2. 如果你没有进行备份但是确切地知道表是怎样创建的,在另一个数据库中创建表的一个拷贝。删除新的数据文件,然后从其他数据库将描述文件和索引文件移到破坏的数据库中。这样提供了新的描述和索引文件,但是è®�.MYD数据文件独自留下来了。回到阶æ®�2并且尝试重建索引文件ã€�

5.9.5.9. 表优åŒ�

为了组合碎片记录并且消除由于删除或更新记录而浪费的空间,以恢复模式运行myisamchkï¼�

shell> myisamchk -r tbl_name

你可以用SQLçš�OPTIMIZE TABLE语句使用的相同方式来优化表,OPTIMIZE TABLE可以修复表并对键值进行分析,并且可以对索引树进行排序以便更快地查找键值。实用程序和服务器之间不可能交互操作,因为当你使ç”�OPTIMIZE TABLE时,服务器做所有的工作。参è§�13.5.2.5节,“OPTIMIZE TABLE语法â€�ã€�

myisamchk还有很多其它可用来提高表的性能的选项ï¼�

·         -S, --sort-index

·         -R index_num, --sort-records=index_num

·         -a, --analyze

关于这些选项的完整的描述,参è§�5.9.5节,“myisamchk:MyISAM表维护实用工具â€�ã€�

5.9.6. 建立表维护计åˆ�

定期对表进行检查而非等到问题出现后再检查数据库表是一个好主意。检查和修复MyISAM表的一个方式是使用CHECK TABLEå’�REPAIR TABLE语句。参è§�13.5.2.3节,“CHECK TABLE语法â€�å’�13.5.2.6节,“REPAIR TABLE语法â€�ã€�

检查表的另一个方法是使用myisamchk。为维护目的,可以使ç”�myisamchk -s检查表ã€�-s选项(简ç§�--silent)使myisamchk以沉默模式运行,只有当错误出现时才打印消息ã€�

在服务器启动时检查表是一个好主意。例如,无论何时机器在更新当中重新启动了,你通常需要检查所有可能受影响的表。(即“预期的破坏了的表”)。要想自动检æŸ�MyISAM表,ç”�--myisam-recover选项启动服务器ã€�

一个更好的测试将是检查最后修改时间比â€�.pidâ€�文件新的表ã€�

你还应该在正常系统操作期间定期检查表。在MySQL AB,我们运行一ä¸�cron任务,每周一次检查所有重要的表,使用â€�crontabâ€�文件中这样的行:

35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI

可以打印损坏的表的信息,以便我们在需要时能够检验并且修复它们ã€�

多年了我们还没有发现(的确是真çš�)都没有任何意外损坏的表时(由于除硬件故障外的其它原因造成损坏的表),每周一次对我们是足够了ã€�

我们建议现在开始,你对所有最å��24小时内被更新了的表每晚都执行myisamchk -s,直到你变得象我们那样信ä»�MySQLã€�

一般情况,MySQL表很少需要维护。如果你用动态大小的行更æ”�MyISAMè¡�(å��VARCHARã€�BLOBæˆ�TEXT列的è¡�)或有删除了许多行的表,你可能想要不时地(每月一次)整理/组合表的空间ã€�

可以对有问题的表执行OPTIMIZE TABLE来优化。或者是,如果可以停一ä¼�mysqld服务å™�,进入数据目录,当服务器停止时使用该命令ï¼�

shell> myisamchk -r -s --sort-index -O sort_buffer_size=16M */*.MYI

5.9.7. 获取关于表的信息

为了获得关于一个表的描述或统计,使用下面的命令ï¼�

·         myisamchk -d tbl_name

以“描述模式”运è¡�myisamchk,生成表的描述。如果用--skip-external-locking选项启动MySQL服务器,myisamchk可以报告运行的表被更新的错误。然而,既然在描述模式中myisamchk不更改表,没有任何破坏数据的风险ã€�

·         myisamchk -d -v tbl_name

为了生成更多关于myisamchk正在做什么的信息,加ä¸�-v告诉它以冗长模式运行ã€�

·         myisamchk -eis tbl_name

仅显示表的最重要的信息。因为必须读取整个表,该操作很慢ã€�

·         myisamchk -eiv tbl_name

这类ä¼� -eis,只是告诉你正在做什么ã€�

下面为这些命令的输出示例。它们基于含这些数据和索引文件大小的表:

-rw-rw-r--   1 monty    tcx     317235748 Jan 12 17:30 company.MYD
-rw-rw-r--   1 davida   tcx      96482304 Jan 12 18:35 company.MYM

myisamchk -d输出示例ï¼�

MyISAM file:     company.MYI
Record format:   Fixed length
Data records:    1403698  Deleted blocks:         0
Recordlength:    226
 
table description:
Key Start Len Index   Type
1   2     8   unique  double
2   15    10  multip. text packed stripped
3   219   8   multip. double
4   63    10  multip. text packed stripped
5   167   2   multip. unsigned short
6   177   4   multip. unsigned long
7   155   4   multip. text
8   138   4   multip. unsigned long
9   177   4   multip. unsigned long
    193   1           text

myisamchk -d -v 输出示例ï¼�

MyISAM file:         company
Record format:       Fixed length
File-version:        1
Creation time:       1999-10-30 12:12:51
Recover time:        1999-10-31 19:13:01
Status:              checked
Data records:            1403698  Deleted blocks:              0
Datafile parts:          1403698  Deleted data:                0
Datafile pointer (bytes):      3  Keyfile pointer (bytes):     3
Max datafile length:  3791650815  Max keyfile length: 4294967294
Recordlength:                226
 
table description:
Key Start Len Index   Type                  Rec/key     Root Blocksize
1   2     8   unique  double                      1 15845376      1024
2   15    10  multip. text packed stripped        2 25062400      1024
3   219   8   multip. double                     73 40907776      1024
4   63    10  multip. text packed stripped        5 48097280      1024
5   167   2   multip. unsigned short           4840 55200768      1024
6   177   4   multip. unsigned long            1346 65145856      1024
7   155   4   multip. text                     4995 75090944      1024
8   138   4   multip. unsigned long              87 85036032      1024
9   177   4   multip. unsigned long             178 96481280      1024
    193   1           text

myisamchk -eis 输出示例ï¼�

Checking MyISAM file: company
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:  98%  Packed:   17%
 
Records:          1403698    M.recordlength:     226
Packed:             0%
Recordspace used:     100%   Empty space:          0%
Blocks/Record:   1.00
Record blocks:    1403698    Delete blocks:        0
Recorddata:     317235748    Deleted data:         0
Lost space:             0    Linkdata:             0
 
User time 1626.51, System time 232.36
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 627, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 639, Involuntary context switches 28966

myisamchk -eiv 输出示例ï¼�

Checking MyISAM file: company
Data records: 1403698   Deleted blocks:       0
- check file-size
- check delete-chain
block_size 1024:
index  1:
index  2:
index  3:
index  4:
index  5:
index  6:
index  7:
index  8:
index  9:
No recordlinks
- check index reference
- check data record references index: 1
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 2
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
- check data record references index: 3
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
- check data record references index: 5
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 6
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 7
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 8
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 9
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:   9%  Packed:   17%
 
- check records and index references
[LOTS OF ROW NUMBERS DELETED]
 
Records:         1403698   M.recordlength:   226   Packed:           0%
Recordspace used:    100%  Empty space:        0%  Blocks/Record: 1.00
Record blocks:   1403698   Delete blocks:      0
Recorddata:    317235748   Deleted data:       0
Lost space:            0   Linkdata:           0
 
User time 1639.63, System time 251.61
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
Blocks in 4 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 10604, Involuntary context switches 122798

下面解释myisamchk产生的信息的类型。â€�keyfile”是索引文件。“记录”和“行”是同义词ã€�

·         MyISAM file

ISAM(索引)文件名ã€�

·         File-version

ISAM格式的版本。当前总是2ã€�

·         Creation time

数据文件创建的时间ã€�

·         Recover time

索引/数据文件上次被重建的时间ã€�

·         Data records

在表中有多少记录ã€�

·         Deleted blocks

有多少删除的块仍然保留着空间。你可以优化表以使这个空间减到最小。参è§�ç¬�7章:优化ã€�

·         Datafile parts

对动态记录格式,这指出有多少数据块。对于一个没有碎片的优化过的表,这与Data records相同ã€�

·         Deleted data

不能回收的删除数据有多少字节。你可以优化表以使这个空间减到最小。参è§�ç¬�7章:优化ã€�

·         Datafile pointer

数据文件指针的大小,以字节计。它通常æ˜�2ã€�3ã€�4æˆ�5个字节。大多数表用2个字节管理,但是目前这还不能ä»�MySQL控制。对固定表,这是一个记录地址。对动态表,这是一个字节地址ã€�

·         Keyfile pointer

索引文件指针的大小,以字节计。它通常æ˜�1ã€�2æˆ�3个字节。大多数表用 2 个字节管理,但是它自动由MySQL计算。它总是一个块地址ã€�

·         Max datafile length

表的数据文件(.MYD文件)能够有多长,以字节计ã€�

·         Max keyfile length

表的键值文ä»�(.MYI文件)能够有多长,以字节计ã€�

·           Recordlength

每个记录占多少空间,以字节计ã€�

·         Record format

用于存储表行的格式。上面的例子使用Fixed lengthã€�其他可能的值是Compressedå’�Packedã€�

·         table description

在表中所有键值的列表。对每个键,给出一些底层的信息ï¼�

o        Key

该键的编号ã€�

o        Start

该索引部分从记录的哪里开始ã€�

o        Len

该索引部分是多长。对于紧凑的数字,这应该总是列的全长。对字符串,它可以比索引的列的全长短些,因为你可能会索引到字符串列的前缀ã€�

o        Index

uniqueæˆ�multipï¼�multiple)。表明一个值是否能在该索引中存在多次ã€�

o        Type

该索引部分有什么数据类型。这是一ä¸�packedã€�strippedæˆ�empty选项çš�ISAM数据类型ã€�

o        Root

根索引块的地址ã€�

o        Blocksize

每个索引块的大小。默认是1024,但是从源码构建MySQL时,该值可以在编译时改变ã€�

o        Rec/key

这是由优化器使用的统计值。它告诉对该键的每个值有多少条记录。唯一键总是有一ä¸�1值。在一个表被装载后(或变更很å¤�),可以用myisamchk -a更新。如果根本没被更新,给定一ä¸�30的默认值ã€�

在上面例子的表中,第9个键有两ä¸�table description行。者说明它是有2个部分的多部键ã€�

·         Keyblocks used

键块使用的百分比是什么。当在例子中使用的表刚刚ç”�myisamchk重新组织时,该值非常高(很接近理论上的最大å€�)ã€�

·         Packed

MySQL试图用一个通用后缀压缩键。这只能被用äº�CHAR/VARCHAR/DECIMAL列的键。对于左部分类似的长字符串,能显著地减少使用空间。在上面的第3个例子中,第4个键æ˜�10个字符长,可以减å°�60%的空间ã€�

·         Max levels

对于该键çš�B树有多深。有长键的大表有较高的值ã€�

·         Records

表中有多少行ã€�

·         M.recordlength

平均记录长度。对于有定长记录的表,这是准确的记录长度,因为所有记录的长度相同ã€�

·         Packed

MySQL从字符串的结尾去掉空格ã€�Packed值表明这样做达到的节约的百分比ã€�

·         Recordspace used

数据文件被使用的百分比ã€�

·         Empty space

数据文件未被使用的百分比ã€�

·         Blocks/Record

每个记录的平均块æ•�(即,一个碎片记录由多少个连接组æˆ�)。对固定格式表,这总是1。该值应该尽可能保持接近1.0。如果它变得太大,你可以重新组织表。参è§�ç¬�7章:优化ã€�

·         Recordblocks

多少å��(链接)被使用。对固定格式,它与记录的个数相同ã€�

·         Deleteblocks

多少å��(链接)被删除ã€�

·         Recorddata

在数据文件中使用了多少字节ã€�

·         Deleted data

在数据文件中多少字节被删é™�(未使ç”�)ã€�

·         Lost space

如果一个记录被更新为更短的长度,就损失了一些空间。这是所有这样的损失之和,以字节计ã€�

·         Linkdata

当使用动态表格式,记录碎片用指针连接(每个4 ï½� 7字节)ã€� Linkdata指这样的指针使用的内存量之和ã€�

如果一张表已经ç”�myisampack压缩了,myisamchk -d打印每个表列的附加信息。对于它的一个例子及其含义的描述,参è§�8.2节,“myisampack:生成压缩、只读MyISAM表â€�ã€�

5.10. MySQL本地化和国际应用

本节描述如何配置服务器来使用不同的字符集。还讨论如何设置服务器的时区并启用各个连接的时区支持ã€�

5.10.1. 数据和排序用字符é›�

默认情况下,MySQL使用cp1252(Latin1)字符集根æ��Swedish/Finnish规则进行排序。这äº� 默认值适合美国和西欧大部分国家ã€�

所æœ�MySQL二进制分发版ç”�--with-extra-charsets=complex编译而成。可以在所有标准程序中添加代码,使它们可以处理latin1和所有多字节二进制字符集。其它字符集根据需要从字符集定义文件载入ã€�

字符集确定在名称中使用什么字符。它还确定如何用SELECT语句çš�ORDER BYå’�GROUP BY子句对字符串进行排序ã€�

还可以在启动服务器时ç”�--default-character-set选项更改字符集。字符集可以ç”�--with-charset=charsetå’�--with-extra-charsets=list-of-charsets | complex | all | none选项æ��configure,字符集配置文件列于SHAREDIR/charsets/Index。参è§�2.8.2节,“典型配置选项â€�ã€�

还可以在你启动服务器时用--default-collation选项更改字符é›� 校对规则。校对规则必须是默认字符集的合法校对规则ã€�(使用SHOW COLLATION语句来确定每个字符集使用哪个校对规则ï¼�ã€� 参见2.8.2节,“典型配置选项â€�ã€�

如果在运è¡�MySQL时更改字符集,还会更改排序顺序。结果是你必须对所有表运行myisamchk -r -q --set-character-set=charset ,或正确地对索引进行排序ã€�

当客户端连接MySQL服务器时,服务器告诉客户端服务器的默认字符集是什么。客户端切换到该字符集进行连接ã€�

当转ä¹�SQL查询的字符串时,你应使用mysql_real_escape_string()ã€�mysql_real_escape_string()等价于旧çš�mysql_escape_string()函数,不同的是它使用MYSQL连接句柄作为第一个参数,以便转义字符时可以使用相应的字符集ã€�

如果客户端的编译路径不是服务器的安装目录,并且配ç½�MySQL时没有包æ‹�MySQL二进制中的所有字符集,如果服务器运行时需要使用客户端设置的字符集之外的其它字符集,你必须告诉客户端从哪里找到更多的字符集ã€�

可以指定--character-sets-dir选项来表示动æ€�MySQL字符集所保存目录的路径。例如,可以将下面的行放入选项文件中:

[client]
character-sets-dir=/usr/local/mysql/share/mysql/charsets

你可以强制客户端使用专用字符集:

[client]
default-character-set=charset

但是一般情况不需要ã€�

5.10.1.1. 使用德国字符é›�

åœ�MySQL 5.1ä¸�,分别指定字符集和 校对规则。这说明如果你想使用German排序顺序,你应选择latin1 字符集和latin1_german1_ciæˆ�latin1_german2_ci校对规则。例如,要用latin1_german1_ci校对规则启动服务器,应使ç”�--character-set-server=latin1å’�--collation-server=latin1_german1_ci选项ã€�

关于这两种校对规则的不同之处,参è§�10.10.2节,“西欧字符集â€�ã€�

5.10.2. 设置错误消息语言

默认情况下,mysqld用英语给出错误消息,但也可以用以下语言显示ï¼�Czechã€�Danishã€�Dutchã€�Estonianã€�Frenchã€�Germanã€�Greekã€�Hungarianã€�Italianã€�Japaneseã€�Koreanã€�Norwegianã€�Norwegian-nyã€�Polishã€�Portugueseã€�Romanianã€�Russianã€�Slovakã€�Spanishæˆ� Swedishã€�

要想在启åŠ�mysqld后用具体语言显示错误消息,使ç”�--languageæˆ�-L选项。选项值可以为语言名称或错误消息文件的全路径。例如:

shell> mysqld --language=swedish

或:

shell> mysqld --language=/usr/local/share/swedish

语言名应为小写ã€�

语言文件位于(默认情况ä¸�)MySQL基本目录çš�share/LANGUAGE目录下ã€�

要想更改错误消息文件,应编辑errmsg.txt文件,然后执行下面的命令以生æˆ�errmsg.sys文件ï¼�

shell> comp_err errmsg.txt errmsg.sys

如果你升级到新版本的MySQL,记住使用新çš�errmsg.txt文件来重新更改ã€�

5.10.3. 添加新的字符é›�

本节讨论åœ�MySQL中添加新字符集的程序。你必须有一ä¸�MySQL源码分发版ã€�

要选择正确的程序,先确定字符集是简单字符集还是复杂字符集:

·         如果字符集不需要使用特殊字符串校对规则程序进行排序,并且不需要多字节字符支持,则为简单字符集ã€�

·         如果需要上述某个特性,则为复杂字符集ã€�

例如ï¼�latin1å’�danish为简单字符集,è€�big5å’�czech为复杂字符集ã€�

在下面的程序中,字符集名ç”�MYSET表示ã€�

对于简单字符集,应ï¼�

1.    åœ�sql/share/charsets/Index文件最后添åŠ�MYSET。并指定唯一的编号ã€�

2.    创建文件sql/share/charsets/MYSET.confã€�(你可以使ç”�sql/share/charsets/latin1.conf的备份文件作为该文件的基础ï¼�ã€�

è¯�文件的语法很简单:

·         注释从â€�#’字符开始,一直到该行末尾ã€�

·         各字之间用任意数量的空格间隔开ã€�

·         定义字符集时,每个字必须为十六进制格式的数字ã€�

·         ctype数组占据å‰�257个字ã€�to_lower[]ã€�to_upper[]å’�sort_order[]数组依次占据256个字ã€�

参见5.10.4节,“字符定义数组â€�ã€�

3.    将字符集名添加到configurE.inçš�CHARSETS_AVAILABLEå’�COMPILED_CHARSETS列ã€�

4.    重新配置、编译并测试ã€�

对于复杂字符集,应:

1.    åœ�MySQL源码分发版中创建文件strings/ctype-MYSET.cã€�

2.    åœ�sql/share/charsets/Index文件最后添åŠ�MYSET。并指定唯一的编号ã€�

3.    看看已有çš�ctype-*.c文件(例如strings/ctype-big5.c),看看需要定义什么。请注意文件中的数组名必须为ctype_MYSETã€�to_lower_MYSET等等。对应简单字符集的数组。参è§�5.10.4节,“字符定义数组â€�ã€�

4.    在文件顶部,添加注释ï¼�

5.            /*
6.            * This comment is parsed by configure to create ctype.c,
7.            * so don't change it unless you know what you are doing.
8.            *
9.            * .configure. number_MYSET=MYNUMBER
10.        * .configure. strxfrm_multiply_MYSET=N
11.        * .configure. mbmaxlen_MYSET=N
12.        */

configure程序使用该注释自动将字符集包括进MySQL库中ã€�

在下面章节中解释strxfrm_multiplyå’�mbmaxlen 行。只有需要字符串比较函数或多字节字符集函数时,才需要单独将它们包括进来ã€�

13.然后你应创建下面的函数:

    • my_strncoll_MYSET()
    • my_strcoll_MYSET()
    • my_strxfrm_MYSET()
    • my_like_range_MYSET()

参见5.10.5节,“字符串比较支持â€�

14.将字符集名添加到configurE.inçš�CHARSETS_AVAILABLEå’�COMPILED_CHARSETS列ã€�

15.重新配置、编译并测试ã€�

sql/share/charsets/README文件中包括详细的说明ã€�

如果你想è¦�MySQL分发中的字符集,请向MySQL内部邮件系统发邮件。参è§�1.7.1.1节,“The MySQL邮件列表â€�ã€�

5.10.4. 字符定义数组

to_lower[]å’�to_upper[]是简单数组,含有小写和大写字符,对应字符集的每个成员。例如:

to_lower['A'] should contain 'a'
to_upper['a'] should contain 'A'

sort_order[]是一个映射,表示如何排列字符的顺序,以便进行比较和排序。通常(但非对于所有字符集)ä¸�to_upper[]相同,说明排序对大小写敏感ã€�MySQL排序字符基于sort_order[]元素的值。对于更加复杂的排序规则,参è§�5.10.5节,“字符串比较支持â€�的字符串 校对规则讨论ã€�

ctype[]是一个位数组,每个字符为一个元素ã€�(请注意字符值索å¼�to_lower[]ã€�to_upper[]å’�sort_order[],但用字符å€�+ 1索引ctype[]。这是传统的转换方法,能够处ç��EOFï¼�ã€�

m_ctype.h中有下面的位掩码定义ï¼�

#define _U      01      /* Uppercase */
#define _L      02      /* Lowercase */
#define _N      04      /* Numeral (digit) */
#define _S      010     /* Spacing character */
#define _P      020     /* Punctuation */
#define _C      040     /* Control character */
#define _B      0100    /* Blank */
#define _X      0200    /* heXadecimal digit */

每个字符çš�ctype[]条目应为相应的描述字符的位掩码值的联合。例如,'A'是大写字ç¬�(_U)以及十六进制整数(_X),因æ­�ctype['A'+1]应包å�� 值:

_U + _X = 01 + 0200 = 0201

5.10.5. 字符串比较支æŒ�

如果语言的排序规则比较复杂,不能用简å��sort_order[]表来处理,需要使用字符串比较函数ã€�

最好的文档是已有字符集。以big5ã€�czechã€�gbkã€�sjiså’�tis160字符集作为例子ã€�

你必须在文件顶部的特殊注释处指定strxfrm_multiply_MYSET=N值ã€�N应设置为字符串在my_strxfrm_MYSET过程中可能增长的最大比ä¾�(必须为正整数)ã€�

5.10.6. 多字节字符支æŒ�

如果你想要添加包括多字节字符的新字符集支持,需要使用多字节字符函数ã€�

最好的文档是已有字符集。以euc_krã€�gb2312,gbkã€�sjiså’�ujis字符集作为例子。这些字符集位于strings目录çš�ctype-charset.c文件中ã€�

必须在文件顶部的特殊注释处指å®�mbmaxlen_MYSET=N值ã€�N应设置为字符集内最长字符的字节数ã€�

5.10.7. 字符集问é¢�

如果你想要使用没有编译为二进制的字符集,可能会遇到下面的问题ï¼�

·         你的程序的字符集保存路径不正确ã€�(默认ä¸�/usr/local/mysql/share/mysql/charsets)。可以在运行有问题的程序时通过--character-sets-dir选项来修复ã€�

·         字符集为多字节字符集,不能动态载入。在这种情况下,你必须重新编译程序,以支持字符集ã€�

·         字符集为动态字符集,但你没有对应的配置文件。在这种情况下,你应从新MySQL分发安装该字符集的配置文件ã€�

·         如果Index文件没有包含字符集名,程序将显示下面的错误消息:

·                ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf'
·                not found (Errcodeï¼�2)

在这种情况下,你应获得新Index文件或在当前文件中手动添加字符集ã€�

对于MyISAM表,可以ç”�myisamchk -dvv tbl_name检查表的字符集名和编号ã€�

5.10.8. MySQL服务器时区支æŒ�

 MySQL服务器有几个时区设置ï¼�

·         系统时区。服务器启动时便试图确定主机的时区,用它来设ç½�system_time_zone系统变量ã€�

·         服务器当前的时区。全局系统变量time_zone表示服务器当前使用的时区。初使值为'SYSTEM',说明服务器时区与系统时区相同。可以用--default-time-zone=timez选项显式指定初使值。如果你æœ�SUPER 权限,可以用下面的语句在运行时设置全局变量值:

·                mysql> SET GLOBAL time_zone = timezone;

·         每个连接的时区。每个客户端连接有自己的时区设置,用会话time_zone变量给出。其初使值与全局变量time_zone相同,但可以用下面的语句重设ï¼�

·                mysql> SET time_zone = timezone;

可以用下面的方法查询当前的全局变量值和每个连接的时区:

mysql> SELECT @@global.time_zone, @@session.time_zone;

timezone值为字符串,表示UTC的偏移量,例å¦�'+10:00'æˆ�'-6:00'。如果已经创建并装入mysql数据库中的时区相关表,你还可以使用命名的时区,例å¦�'Europe/Helsinki'ã€�'US/Eastern'æˆ�'MET'。å€�'SYSTEM'说明该时区应与系统时区相同。时区名对大小写不敏感ã€�

MySQL安装程序åœ�mysql数据库中创建时区表,但不装载。你必须手动装载ã€�(如果你正从以前的版本升级åˆ�MySQL 4.1.3或更新版本,你应通过升级mysql数据库来创建表。参è§�2.10.2节,“升级授权表â€�中的说明ï¼�ã€�

如果你的系统有自己的时区信息数据åº�(描述时区的一系列文件),应使用mysql_tzinfo_to_sql程序来填充时区表。示例系统如Linuxã€�FreeBSDã€�Sun Solariså’�Mac OS X。这些文件的可能位置ä¸�/usr/share/zoneinfo目录。如果你的系统没有时区信息数据库,可以使用本节后面描述的下载的软件包ã€�

mysql_tzinfo_to_sql程序用来装载时区表。在命令行中,将时区信息目录路径名传递到mysql_tzinfo_to_sql并输出发送到mysql程序。例如:

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

mysql_tzinfo_to_sql读取系统时区文件并生æˆ�SQL语句ã€�mysql处理这些语句并装载时区表ã€�

mysql_tzinfo_to_sql还可以用来装载单个时区文件,并生成闰秒信息ã€�

要想装载对应时区tz_name的单个时区文ä»�tz_file,应这样调用mysql_tzinfo_to_sqlï¼�

shell> mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql

如果你的时区需要计算闰秒,按下面方法初使化闰秒信息,其ä¸�tz_file是时区文件名ï¼�

shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql

如果你的系统没有时区信息数据åº� (例如ï¼�Windowsæˆ�HP-UX),你可以ä»�http://dev.mysql.com/downloads/timezones.html下载预构建时区表软件包。该软件包包å��MyISAM时区表所用的.frmã€�.MYDå’�.MYI文件。这些表应属äº�mysql数据库,因此应将这些文件放到MySQL服务器数据目录的mysql子目录。操作时应关闭服务器ã€�

警告ï¼�如果你的系统有时区信息数据库,请不要使用下载的软件包。而应使用mysql_tzinfo_to_sql实用工具!否则,MySQL和系统上其它应用程序处理日期时间的方法会有所不同ã€�

关于在复制时时区设置相关请查é˜�6.7节,“复制特性和已知问题â€�ã€�

5.11. MySQL日志文件

MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:

日志文件

记入文件中的信息类型

错误日志

记录启动、运行或停止mysqld时出现的问题ã€�

查询日志

记录建立的客户端连接和执行的语句ã€�

更新日志

记录更改数据的语句。不赞成使用该日志ã€�

二进制日å¿�

记录所有更改数据的语句。还用于复制ã€�

慢日å¿�

记录所有执行时间超è¿�long_query_time秒的所有查询或不使用索引的查询ã€�

默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制 mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日志)。当你执行一ä¸�FLUSH LOGS语句或执è¡�mysqladmin flush-logsæˆ�mysqladmin refresh时,出现日志刷新。参è§�13.5.5.2节,“FLUSH语法â€�ã€�

如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志。相关讨论参è§�ç¬�6章:MySQL中的复制ã€�

5.11.1. 错误日志

错误日志文件包含了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息ã€�

如果mysqld莫名其妙地死掉并ä¸�mysqld_safe需要重新启动它ï¼�mysqld_safe在错误日志中写入一æ��restarted mysqld消息。如æž�mysqld注意到需要自动检查或着修复一个表,则错误日志中写入一条消息ã€�

在一些操作系统中,如æž�mysqld死掉,错误日志包含堆栈跟踪信息。跟踪信息可以用来确å®�mysqld死掉的地方。参è§�E.1.4节,“使用堆栈跟踪â€�ã€�

可以ç”�--log-error[=file_name]选项来指å®�mysqld保存错误日志文件的位置。如果没有给å®�file_name值,mysqld使用错误日志å��host_name.err 并在数据目录中写入日志文件。如果你执行FLUSH LOGS,错误日志用-old重新命名后缀并且mysqld创建一个新的空日志文件ã€�(如果未给å‡�--log-error选项,则不会重新命名ï¼�ã€�

如果不指å®�--log-error,或è€�(åœ�Windowsä¸�)如果你使ç”�--console选项,错误被写入标准错误输出stderr。通常标准输出为你的终端ã€�

åœ�Windows中,如果未给å‡�--console选项,错误输出总是写入.err文件ã€�

5.11.2. 通用查询日志

如果你想要知é��mysqld内部发生了什么,你应该用--log[=file_name]æˆ�-l [file_name]选项启动它。如果没有给å®�file_name的值, 默认名是host_name.logã€�所有连接和语句被记录到日志文件。当你怀疑在客户端发生了错误并想确切地知道该客户端发送给mysqld的语句时,该日志可能非常有用ã€�

mysqld按照它接收的顺序记录语句到查询日志。这可能与执行的顺序不同。这与更新日志和二进制日志不同,它们在查询执行后,但是任何一个锁释放之前记录日志ã€�(查询日志还包含所有语句,而二进制日志不包含只查询数据的语句)ã€�

服务器重新启动和日志刷新不会产生新的一般查询日志文ä»�(尽管刷新关闭并重新打开一般查询日志文ä»�)。在Unix中,你可以通过下面的命令重新命名文件并创建一个新文件ï¼�

shell> mv hostname.log hostname-old.log
shell> mysqladmin flush-logs
shell> cp hostname-old.log to-backup-directory
shell> rm hostname-old.log

åœ�Windows中,服务器打开日志文件期间你不能重新命名日志文件。你必须先停止服务器然后重新命名日志文件。然后,重启服务器来创建新的日志文件ã€�

5.11.3. 二进制日å¿�

二进制日志以一种更有效的格式,并且是事务安全的方式包含更新日志中可用的所有信息ã€�

二进制日志包含了所有更新了数据或者已经潜在更新了数据(例如,没有匹配任何行的一ä¸�DELETE)的所有语句。语句以â€�事件”的形式保存,它描述数据更改ã€�

æ³�释:二进制日志已经代替了老的更新日志,更新日志在MySQL 5.1中不再使用ã€�

二进制日志还包含关于每个更新数据库的语句的执行时间信息。它不包含没有修改任何数据的语句。如果你想要记录所有语句(例如,为了识别有问题的查询),你应使用一般查询日志。参è§�5.11.2节,“通用查询日志â€�ã€�

二进制日志的主要目的是在恢复使能够最大可能地更新数据库,因为二进制日志包含备份后进行的所有更新ã€�

二进制日志还用于在主复制服务器上记录所有将发送给从服务器的语句。参è§�ç¬�6章:MySQL中的复制ã€�

运行服务器时若启用二进制日志则性能大约æ…�1%。但是,二进制日志的好处,即用于恢复并允许设置复制超过了这个小小的性能损失ã€�

当用--log-bin[=file_name]选项启动时,mysqld写入包含所有更新数据的SQL命令的日志文件。如果未给出file_name值, 默认名为-bin后面所跟的主机名。如果给出了文件名,但没有包含路径,则文件被写入数据目录。建议指定一个文件名,原因参è§�A.8.1节,“MySQL中的打开事宜â€�ã€�

如果你在日志名中提供了扩展名(例如ï¼�--log-bin=file_name.extension),则扩展名被悄悄除掉并忽略ã€�

mysqld在每个二进制日志名后面添加一个数字扩展名。每次你启动服务器或刷新日志时该数字则增加。如果当前的日志大小达到max_binlog_size,还会自动创建新的二进制日志。如果你正使用大的事务,二进制日志还会超è¿�max_binlog_size:事务全写入一个二进制日志中,绝对不要写入不同的二进制日志中ã€�

为了能够知道还使用了哪个不同的二进制日志文件ï¼�mysqld还创建一个二进制日志索引文件,包含所有使用的二进制日志文件的文件名。默认情况下与二进制日志文件的文件名相同,扩展名ä¸�'.index'。你可以ç”�--log-bin-index[=file_name]选项更改二进制日志索引文件的文件名。当mysqld在运行时,不应手动编辑该文件;如果这样做将会ä½�mysqld变得混乱ã€�

可以ç”�RESET MASTER语句删除所有二进制日志文件,或ç”�PURGE MASTER LOGS只删除部分二进制文件。参è§�13.5.5.5节,“RESET语法â€�å’�13.6.1节,“用于控制主服务器的SQL语句â€�ã€�

二进制日志格式有一些已知限制,会影响从备份恢复。参è§�6.7节,“复制特性和已知问题â€�ã€�

保存程序和触发器的二进制日志的描述参è§�20.4节,“存储子程序和触发程序的二进制日志功能â€�ã€�

可以使用下面çš�mysqld选项来影响记录到二进制日志知的内容。又见选项后面的讨论ã€�

·         --binlog-do-db=db_name

告诉主服务器,如果当前的数据åº�(å��USE选定的数据库)æ˜�db_name,应将更新记录到二进制日志中。其它所有没有明显指定的数据åº�  被忽略。如果使用该选项,你应确保只对当前的数据库进行更新ã€�

对于CREATE DATABASEã€�ALTER DATABASEå’�DROP DATABASE语句,有一个例外,即通过操作的数据库来决定是否应记录语句,而不是用当前的数据库ã€�

一个不能按照期望执行的例子:如果用binlog-do-db=sales启动服务器,并且执行USE prices; UPDATE sales.january SET amount=amount+1000ï¼�,该语句不写入二进制日志ã€�

·         --binlog-ignore-db=db_name

告诉主服务器,如果当前的数据åº�(å��USE选定的数据库)æ˜�db_name,不应将更新保存到二进制日志中。如果你使用该选项,你应确保只对当前的数据库进行更新ã€�

一个不能按照你期望的执行的例子:如果服务器ç”�binlog-ignore-db=sales启动,并且执è¡�USE prices; UPDATE sales.january SET amount=amount+1000ï¼�,该语句不写入二进制日志ã€�

类似äº�--binlog-do-db,对äº�CREATE DATABASEã€�ALTER DATABASEå’�DROP DATABASE语句,有一个例外,即通过操作的数据库来决定是否应记录语句,而不是用当前的数据库ã€�

要想记录或忽视多个数据库,使用多个选项,为每个数据库指定相应的选项ã€�

服务器根据下面的规则对选项进行评估,以便将更新记录到二进制日志中或忽视。请注意对于CREATE/ALTER/DROP DATABASE语句有一个例外。在这些情况下,根据以下规则,所创建ã€�修改或删除的数据库将代替当前的数据库ã€�

1.    是否æœ�binlog-do-dbæˆ�binlog-ignore-db规则?

·         没有:将语句写入二进制日志并退出ã€�

·         有:执行下一步ã€�

2.    有一些规åˆ�(binlog-do-dbæˆ�binlog-ignore-db或二者都æœ�)。当前有一个数据库(USE是否选择了数据库?)?

·         没有ï¼�不要写入语句,并退出ã€�

·         有:执行下一步ã€�

3.    有当前的数据库。是否有binlog-do-db规则?

·         有:当前的数据库是否匹配binlog-do-db规则?

o        有:写入语句并退出ã€�

o        没有:不要写入语句,退出ã€�

·         No:执行下一步ã€�

4.    有一äº�binlog-ignore-db规则。当前的数据库是否匹é…�binlog-ignore-db规则?

·         有:不要写入语句,并退出ã€�

·         没有:写入查询并退出ã€�

例如,只ç”�binlog-do-db=sales运行的服务器不将当前数据库不ä¸�sales的语句写入二进制日志(换句话说ï¼�binlog-do-db有时可以表示â€�忽视其它数据åº�â€�)ã€�

如果你正进行复制,应确保没有从服务器在使用旧的二进制日志文件,方可删除它们。一种方法是每天一次执è¡�mysqladmin flush-logs并删除三天前的所有日志。可以手动删除,或最好使ç”�PURGE MASTER LOGS(参见13.6.1节,“用于控制主服务器的SQL语句â€�),该语句还会安全地更新二进制日志索引文件(可以采用日期参数)ã€�

具有SUPER权限的客户端可以通过SET SQL_LOG_BIN=0语句禁止将自己的语句记入二进制记录。参è§�13.5.3节,“SET语法â€�ã€�

你可以用mysqlbinlog实用工具检查二进制日志文件。如果你想要重新处理日志止的语句,这很有用。例如,可以从二进制日志更新MySQL服务器,方法如下ï¼�

shell> mysqlbinlog log-file | mysql -h server_name

关于mysqlbinlog实用工具的详细信息以及如何使用它,参è§�8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具â€�ã€�

如果你正使用事务,必须使ç”�MySQL二进制日志进行备份,而不能使用旧的更新日志ã€�

查询结束后、锁定被释放前或提交完成后则立即记入二进制日志。这样可以确保按执行顺序记入日志ã€�

对非事务表的更新执行完毕后立即保存到二进制日志中。对于事务表,例å¦�BDBæˆ�InnoDB表,所有更改表的更æ–�(UPDATEã€�DELETEæˆ�INSERT) 被缓存起来,直到服务器接收到COMMIT语句。在该点,执行完COMMIT之前ï¼�mysqld将整个事务写入二进制日志。当处理事务的线程启动时,它为缓冲查询分é…�binlog_cache_size大小的内存。如果语句大于该值,线程则打开临时文件来保存事务。线程结束后临时文件被删除ã€�

Binlog_cache_use状态变量显示了使用该缓冲区(也可能是临时文件)保存语句的事务的数量ã€�Binlog_cache_disk_use状态变量显示了这些事务中实际上有多少必须使用临时文件。这两个变量可以用于å°�binlog_cache_size调节到足够大的值,以避免使用临时文件ã€�

max_binlog_cache_size(默认4GB)可以用来限制用来缓存多语句事务的缓冲区总大小。如果某个事务大于该值,将会失败å¹� 回滚ã€�

如果你正使用更新日志或二进制日志,当使用CREATE ... SELECT or INSERT ... SELECT时,并行插入被转换为普通插入。这样通过在备份时使用日志可以确保重新创建表的备份ã€�

请注æ„�MySQL 5.1值的二进制日志格式与以前版本çš�MySQL不同,因为复制改进了。参è§�6.5节,“不同MySQL版本之间的复制兼容性â€�ã€�

默认情况下,并不是每次写入时都将二进制日志与硬盘同步。因此如果操作系统或机器(不仅仅是MySQL服务å™�)崩溃,有可能二进制日志中最后的语句丢失了。要想防止这种情况,你可以使ç”�sync_binlog全局变量(1是最安全的值,但也是最慢的),使二进制日志在æ¯�N次二进制日志写入后与硬盘同步。参è§�5.3.3节,“服务器系统变量â€�。即ä½�sync_binlog设置ä¸�1,出现崩溃时,也有可能表内容和二进制日志内容之间存在不一致性。例如,如果使用InnoDB表,MySQL服务器处ç��COMMIT语句,它将整个事务写入二进制日志并将事务提交åˆ�InnoDBä¸�ã€�如果在两次操作之间出现崩溃,重启时,事务è¢�InnoDB回滚,但仍然存在二进制日志中。可以用--innodb-safe-binlog选项解决该问题,可以增加InnoDB表内容和二进制日志之间的一致性ã€�(注释:在MySQL 5.1中不需è¦�--innodb-safe-binlog;由于引入了XA事务支持,该选项作废了)ã€�

该选项可以提供更大程度的安全,还应å¯�MySQL服务器进行配置,使每个事务的二进制日å¿�(sync_binlog =1)å’�(默认情况为真)InnoDB日志与硬盘同步。该选项的效果是崩溃后重启时,在滚回事务后,MySQL服务器从二进制日志剪åˆ� 回滚çš�InnoDB事务。这样可以确保二进制日志反馈InnoDB表的确切数据等,并使从服务器保持与主服务器保持同æ­�(不接æ”� 回滚的语å��)ã€�

请注意即ä½�MySQL服务器更新其它存储引擎而不æ˜�InnoDB,也可以使用--innodb-safe-binlog。在InnoDB崩溃恢复时,只从二进制日志中删除影响InnoDB表的语句/事务。如果崩溃恢复时MySQL服务器发现二进制日志变短äº�(即至少缺少一个成功提交的InnoDB事务),如æž�sync_binlog =1并且硬盘/文件系统的确能根据需要进行同æ­�(有些不需è¦�)则不会发生,则输出错误消æ�� ("二进制日å¿�<å��>比期望的要小")。在这种情况下,二进制日志不准确,复制应从主服务器的数据快照开始ã€�

写入二进制日志文件和二进制日志索引文件的方法与写å…�MyISAM表相同。参è§�A.4.3节,“MySQL处理磁盘满的方式â€�ã€�

5.11.4. 慢速查询日å¿�

ç”�--log-slow-queries[=file_name]选项启动时,mysqld写一个包含所有执行时间超è¿�long_query_time秒的SQL语句的日志文件。获得初使表锁定的时间不算作执行时间ã€�

如果没有给出file_name值, 默认未主机名,后缀ä¸�-slow.log。如果给出了文件名,但不是绝对路径名,文件则写入数据目录ã€�

语句执行完并且所有锁释放后记入慢查询日志。记录顺序可以与执行顺序不相同ã€�

慢查询日志可以用来找到执行时间长的查询,可以用于优化。但是,检查又长又慢的查询日志会很困难。要想容易些,你可以使用mysqldumpslow命令获得日志中显示的查询摘要来处理慢查询日志ã€�

åœ�MySQL 5.1的慢查询日志中,不使用索引的慢查询同使用索引的查询一样记录。要想防止不使用索引的慢查询记入慢查询日志,使用--log-short-format选项。参è§�5.3.1节,â€�mysqld命令行选项â€�ã€�

åœ�MySQL 5.1ä¸�,通过--log-slow-admin-statements服务器选项,你可以请求将慢管理语句,例å¦�OPTIMIZE TABLEã€�ANALYZE TABLEå’� ALTER TABLE写入慢查询日志ã€�

用查询缓存处理的查询不加到慢查询日志中,因为表有零行或一行而不能从索引中受益的查询也不写入慢查询日志ã€�

5.11.5. 日志文件维护

MySQL服务器可以创建各种不同的日志文件,从而可以很容易地看见所进行的操作。参è§�5.11节,“MySQL日志文件â€�。但是,你必须定期清理这些文件,确保日志不会占用太多的硬盘空间ã€�

当启用日志使ç”�MySQL时,你可能想要不时地备份并删除旧的日志文件,并告è¯�MySQL开始记入新文件。参è§�5.9.1节,“数据库备份â€�ã€�

åœ� Linux (Redhat)的安装上,你可为此使ç”�mysql-log-rotate脚本。如果你ä»�RPM分发安装MySQL,脚本应该自动被安装了ã€�

在其它系统上,你必须自己安装短脚本,你可ä»�cron等入手处理日志文件ã€�

你可以通过mysqladmin flush-logsæˆ�SQL语句FLUSH LOGS来强åˆ�MySQL开始使用新的日志文件ã€�

日志清空操作做下列事情:

  • 如果使用标准日志(--log)或慢查询日志(--log-slow-queries),关闭并重新打开日志文件ã€�(默认ä¸�mysql.logå’�`hostname`-slow.log)ã€�
  • 如果使用更新日志(--log-update)或二进制日志(--log-bin),关闭日志并且打开有更高序列号的新日志文件ã€�

如果你只使用更新日志,你只需要重新命名日志文件,然后在备份前清空日志。例如,你可以这样做ï¼�

shell> cd mysql-data-directory
shell> mv mysql.log mysql.old
shell> mysqladmin flush-logs

然后做备份并删除â€�mysql.oldâ€�ã€�

5.12. 在同一台机器上运行多个MySQL服务å™�

在一些情况下,你可能想要在同一台机器上运行多个mysqld服务å™�。你可能想要测试一个新çš�MySQL发布,同时不影响现有产品的设置。或者,你可能想使不同的用户访问来访问不同的mysqld服务å™�以便他们自己来管理ã€�(例如,你可能是一ä¸�Internet服务提供商,希望为不同的客户来提供独立的MySQL安装ï¼�ã€�

要想在一个单独的机器上运行多个服务器,每个服务器必须有唯一的各运行参数值。这些值可以在命令行中设置或在选项文件中设置。参è§�4.3节,“指定程序选项â€�ã€�

至少下面的选项对每个服务器必须是不同的ï¼�

·         --port=port_num

--port控制着TCP/IP连接的端口号ã€�

·         --socket=path

--socket控制Unix中的Unix套接字文件路径和åœ�Windows中的命名管道名称。在Windows中,只有支持命名管道连接的服务器才需要明确指定管道名称ã€�

·         --shared-memory-base-name=name

该选项当前只在Windows中使用。它指定Windows服务器使用的、允许客户端通过共享内存来连接的共享内存名ã€�

·         --pid-file=path

该选项只在Unix中使用。它指出服务器在其中写入进程ID的文件名ã€�

如果你使用下面的日志文件选项,对于每个服务器来说,它们必须是不同的:

·           --log=path

·         --log-bin=path

·         --log-update=path

·         --log-error=path

·         --bdb-logdir=path

日志文件选项的描述参è§�5.11.5节,“日志文件维护â€�ã€�

为了提高性能,你可以为每个服务器指定下面选项的不同的值,以便在物理磁盘之间平均分配负荷:

·         --tmpdir=path

·         --bdb-tmpdir=path

还推荐使用不同的临时目录,以便容易地确定哪个MySQL服务器创建了给定的临时文件ã€�

一般情况,每个服务器应还使用不同的数据目录,可以通过--datadir=path选项来指定ã€�

警告ï¼�一般情况,你决不要让两个服务器更新相同数据库中的数据。否则,如果你的操作系统不支持故障排除系统锁定,该可能会导致非常奇怪的结果。如果(不理会该警告)运行的多个服务器使用相同的数据目录并且启用了日志记录,你必须使用适当的选项来为每个服务器指定唯一的日志文件名。否则,服务器尝试用相同的文件来记录日志。请注意这种类型的设置只能在MyISAMå’�MERGE表上工作,对其它任何存储引擎不起作用ã€�

多个服务器共享一个数据目录的警告也适用äº�NFS环境。允许多ä¸�MySQL服务器通过NFS访问一个共同的数据目录是一ä¸�非常不好的主ä¹�ã€�

·         主要问题æ˜�NFS存在速度瓶颈。它不是用于这种用途ã€�

·         ç”�NFS的另一个冒险是你必须提出一个方法来确保两个或多个服务器不会相互干扰ã€�NFS文件的锁定通常ç”�lockd后台程序处理,但是目前,没有一个运行平台能够在每种情况ä¸�100%可靠地进行锁定ã€�

使你更加容易:忘记在服务器之间通过NFS共享数据目录。一个较好的解决方案是使用包含几ä¸�CPU并且和使用有效处理多线程的操作系统的机器ã€�

如果在不同的位置有多ä¸�MySQL的安装,一般情况可以用--basedir=path选项为每个服务器指定基本安装目录,使每个服务器使用不同的数据目录、日志文件和PID文件。(所有这些值的 默认值相对于根目录来确定)。那样的话, 你唯一需要指定的其它选项æ˜�--socketå’�--port选项。例如,假如使用tar文件二进制分发版安装不同çš�MySQL版本。这些安装在不同的位置,因此可以使用各个安装服务器相应的根目录中çš�bin/mysqld_safe命令æ��启动服务器ã€�mysqld_safe确定正确çš�--basedir选项传递给mysqld,你仅需要为mysqld_safe指定--socketå’�--port选项ã€�

正如下面几节所讨论的那样,可以通过设置环境变量或用指定的命令行选项来启动更多的服务器。但是,如果你需要在一个更稳定的基础上运行多个服务器,一个更方便的方法是使用选项文件来为每个服务器指定那些选项值,它对每个服务器必须是唯一的ã€�

5.12.1. 在Windows下运行多个服务器

åœ�Windows中,可以从命令行手动启动来运行多个服务器,每个服务器使用合适的操作参数。在基于Windows NT的系统中,安装几个服务器时,你还有将多个服务器安装为Windows服务并运行的选项。关于从命令行运è¡�MySQL服务器或作为服务运行的一般说明在 2.3节,“在Windows上安装MySQLâ€�中给出。本节描述怎样确保你用不同的启动选项值(对于每个服务器必须是唯一的,例如数据目录)启动各个服务器。这些选项的描述见5.12节,“在同一台机器上运行多个MySQL服务器â€�ã€�

5.12.1.1. 在命令行中启动多个Windows服务å™�

为了从命令行手动启动多个服务器,可以在命令行中或在选项文件中指定适当的选项。把选项放在选项文件中比较方便,但是需要确保每个服务器可以获得自己的选项。为了实现,为每个创建一个选项文件,并且运行服务时通过--defaults-file选项告诉服务器选项文件名ã€�

假设你想要在端口3307使用数据目录C:\mydata1运行mysqld,并且想在端å��3308使用数据目录C:\mydata1运行mysqld-maxã€�(要想这样做,启动服务器之前要确保,每个数据目录存在并且有自己çš�mysql数据库拷贝,它包å�� 授权表)ã€�

然后创建两个选项文件。例如,创建一个文件名ä¸�C:\my-opts1.cnf的配置文件,它看起来象这个样子:

[mysqld]
datadir = C:/mydata1
port = 3307

创建第二个文件名ä¸�C:\my-opts1.cnf的配置文件,它看起来象这个样子:

mysqld]
datadir = C:/mydata2
port = 3308

然后,用它们自己的选项文件启动每个服务器:

C:\> C:\mysql\bin\mysqld --defaults-file=C:\my-opts1.cnf
C:\> C:\mysql\bin\mysqld-max --defaults-file=C:\my-opts2.cnf

åœ�NT中,每个服务器在前台启动(服务器退出前,不会显示新的提示符);需要在两个控制台窗口中执行这两个命令ã€�

要想关闭服务器,必须连接到相应的端口号:

C:\> C:\mysql\bin\mysqladmin --port=3307 shutdown

C:\> C:\mysql\bin\mysqladmin --port=3308 shutdown

如刚才所讨论的,服务器配置允许客户端通过TCP/IP来连接。如果你çš�Windows版本支持命名管道并且你想允许命名管道连接,使ç”�mysqld-ntæˆ�mysqld-max-nt服务器并指定启用命名管道并且指定管道名的选项。支持命名管道连接的每个服务器必须使用一个唯一的管道名。例如,C:\my-opts1.cnf文件可能象这样来书写ï¼�

[mysqld]
datadir = C:/mydata1
port = 3307
enable-named-pipe
socket = mypipe1

然后,这样启动服务器ï¼�

C:\> C:\mysql\bin\mysqld-nt --defaults-file=C:\my-opts1.cnf

同样修改ç¬�2个服务器使用çš�C:\my-opts2.cnf文件ã€�

5.12.1.2. 做为服务启动多个Windows服务å™�

在基äº�NT的系统中ï¼�MySQL服务器可以以Windows服务的方式来运行。安装、控制和删除单个MySQL服务的过程描述见2.3.12节,“以Windows服务方式启动MySQLâ€�ã€�

你还可以以服务的方式安装多个MySQL服务器。此时,除了所有参数对每个服务器必须是唯一的,你还必须确保每个服务器使用不同的服务名ã€�

在下面的说明中,假设你想要运è¡�mysqld-nt服务器的两个不同的版本,它们分别安装åœ�C:\mysql-4.1.8å’�C:\mysql-5.1.2-alpha目录中ã€�(可能存在这种情况,如果你正在运行版本4.1.8作为你的产品服务器,还想使用5.1.2-alpha版本来进行测试)ã€�

当用--installæˆ�--install-manual选项安装一ä¸�MySQL服务时,应遵从以下原则:

·         如果你没有指定服务名,服务器使用默认çš�MySQL服务名,从标准选项文件çš�[mysqld]组中读取选项ã€�

·         如果你在--install选项后指定了服务名,服务器忽ç•�[mysqld]选项组,从具有相同名的组中读取选项作为服务名。服务器从标准选项文件中读取选项ã€�

·         如果你在服务名后面指定一ä¸�--defaults-file选项,服务器忽略标准选项文件,只从命名的文件çš�[mysqld]组读取选项ã€�

æ³�释:MySQL 4.0.17之前,只有使用默认服务名ï¼�MySQLï¼�安装的一个服务器或使用服务名mysqld显式安装的一个服务器从标准选项文件è¯�[mysqld]组。到4.0.17时,如果服务器读标准选项文件,则它们均读[mysqld]组,即使它们安装时使用了另一个服务名。这样允许你为选项使用[mysqld]组,用于所æœ�MySQL服务器,并将根据每个服务器命名的选项组用于该服务å™�,即使用那个服务名安装的服务器ã€�

根据前面叙述,你可以通过几个方法来设置多个服务器。下面的说明描述了一些示例。在尝试之前,应确保你首先关闭并且卸载了所有已有的MySQL服务器ã€�

·         方法1ï¼�在一个标准选项文件中指定所有服务器选项。要想这样做,为每个服务器使用不同的服务名。假设你想使用服务名mysqld1运行4.1.8版的mysqld-ntå¹�使用服务å��mysqld2运行5.1.2-alpha版的mysqld-nt。在这种情况下,你可以为4.1.8使用[mysqld1]组,ä¸�5.1.2-alpha使用[mysqld2]组。例如,你可以象这样建立 C:\my.cnf文件ï¼�

·                # options for mysqld1 service
·                [mysqld1]
·                basedir = C:/mysql-4.1.8
·                port = 3307
·                enable-named-pipe
·                socket = mypipe1
·                 
·                # options for mysqld2 service
·                [mysqld2]
·                basedir = C:/mysql-5.1.2-alpha
·                port = 3308
·                enable-named-pipe
·                socket = mypipe2

如下面所示安装服务器,使用服务器的全路径名来确保Windows为每个服务注册正确的可执行程序:

C:\> C:\mysql-4.1.8\bin\mysqld-nt --install mysqld1
C:\> C:\mysql-5.1.2-alpha\bin\mysqld-nt --install mysqld2

为了启动服务器,使用服务管理器,或用带有适当的服务名çš�NET STARTï¼�

C:\> NET START mysqld1

C:\> NET START mysqld2

要想停止服务,使用服务管理器,或用带有适当的服务名çš�NET STOPï¼�

C:\> NET STOP mysqld1
C:\> NET STOP mysqld2

·         方法2ï¼�为每个服务器用不同的文件指定选项,当你安装服务时使用--defaults-file告诉每个服务器使用什么文件。此时,每个文件应用一ä¸�[mysqld]组列出选项ã€�

使用这种方法ä¸�4.1.8版本çš�mysqld-nt指定选项,应象这样创建一ä¸�C:\my-opts1.cnf文件ï¼�

[mysqld]
basedir = C:/mysql-4.1.8
port = 3307
enable-named-pipe
socket = mypipe1

对于5.1.2-alpha版的mysqld-nt,象这样创建一ä¸�C:\my-opts2.cnf文件ï¼�

[mysqld]
basedir = C:/mysql-5.1.2-alpha port = 3308
enable-named-pipe
socket = mypipe2

安装服务如下(在一个单一行中输入每个命令):

C:\> C:\mysql-4.1.8\bin\mysqld-nt -- installmysqld1
           --defaults-file=C:\my-opts1.cnf
C:\> C:\mysql-5.1.2-alpha\bin\mysqld-nt -- installmysqld2
           --defaults-file=C:\my-opts2.cnf

当你作为服务安装一ä¸�MySQL服务器时,要想使ç”�--defaults-file选项,你必须在此选项之前加服务名ã€�

安装服务后,按照与前面的示例相同的方法启动和停止ã€�

要想卸载多个服务,对每个服务使用mysqld --remove,在--remove选项后指定服务名。如果服务名æ˜� 默认çš�(MySQL),你可以不指定ã€�

5.12.2. 在Unix中运行多个服务器

åœ�Unix中运行多个服务器最容易的方法是使用不同çš�TCP/IP端口så’�Unix套接字文件编译,因此每个实例在不同的网络接口侦听。另外,每个安装应在不同的基础目录中编译,那将自动为你的每个服务器产生使用不同的编译进来的数据目录、日志文件和PID文件位置ã€�

假设一个现有的4.1.8版本服务器配置为默认TCP/IP端口å��(3306)å’�Unix套接字文ä»�(/tmp/mysql.sock)。要想配置一个新çš�5.1.2-alpha版的服务器来使用不同的操作参数,使用一ä¸�configure命令,大概象这样使用ï¼�

shell> ./configure --with-tcp-port=port_number \
             --with-unix-socket-path=file_name \
             --prefix=/usr/local/mysql-5.1.2-alpha

这里ï¼�port_numberå’�file_name必须不同于默è®�TCP/IP端口号和Unix套接字文件路径名,并ä¸�--prefix值应指定一个不同于现有MySQL安装目录的安装目录ã€�

如果你有一ä¸�MySQL服务器正侦听一个给定的端口号,你可以使用下面的命令来找出针对一些重要配置变量它使用了那些操作参数,包括基础目录å’�Unix套接字文件名ï¼�

shell> mysqladmin --host=host_name --port=port_number variables

通过该命令显示的信息,当配置其它服务器时,你可以告诉服务器该选项没有使用的值ã€�

请注意,如果你指å®�localhost作为一个主机名ï¼�mysqladmin默认使用Unix套接字文件连接,而不æ˜�TCP/IP。从 MySQL 4.1开始,通过--protocol= TCP | SOCKET | PIPE | MEMORY}选项,你可以显示地指定连接协议ã€�

如果只是用一个不同的Unix套接字文件和TCP/IP端口号启动,不必编译新的MySQL服务器。还可以在运行时指定这些值。这样做的一个方法是使用命令行选项ï¼�

shell> mysqld_safe --socket=file_name --port=port_number

要启动第二个服务器,提供不同çš�--socketå’�--port选项值,并且传递一ä¸�--datadir=path选项ç»�mysqld_safe,以便服务器使用一个不同的数据目录ã€�

达到相似效果的另一个方法是使用环境变量来设ç½� Unix套接字文件名å’�TCP/IP端口号:

shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
shell> MYSQL_TCP_PORT=3307
shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
shell> mysql_install_db --user=mysql
shell> mysqld_safe --datadir=/path/to/datadir &

这是一个快速启动第二个服务器以用于测试的方法。该方法的最大好处是环境变量设定值适用于你从相同的shell调用的任何客户端程序。因而,那些客户端连接自动指向第二个服务器!

附录Fï¼�环境变量包括你可以使用的影响mysqld的其它环境变量列è¡�ã€�

对于自动服务器启动,对于每个服务器,机器引导时执行的启动脚本应执行下面的命令,每个命令用一个相应的选项文件路径ï¼�

mysqld_safe --defaults-file=path

每个选项文件应包含一个给定服务器特定的选项值ã€�

åœ�Unix中,mysqld_multi脚本是启动多个服务器的另一个方法。参è§�5.1.5节,“mysqld_multi:管理多个MySQL服务器的程序â€�ã€�

5.12.3. 在多服务器环境中使用客户端程åº�

当你想要用一个客户端程序连接一ä¸�MySQL服务器时,该服务器侦听不同的网络接口,而不是编译到你的客户端的网络接口,你可以使用下面的方法:

·         启动客户端,ç”�--host=host_name --port=port_number通过TCP/IP来连接一个远程服务器,用--host=127.0.0.1 --port=port_number通过TCP/IP来连接一个本地服务器,或者用--host=localhost --socket=file_name通过一ä¸�Unix套接字文件或一ä¸�Windows命名管道来连接一个本地服务器ã€�

·         ä»�MySQL 4.1起,启动客户端时ç”�--protocol=tcp通过TCP/IP来连接,ç”�--protocol=socket通过一ä¸�Unix套接字文件来连接,用--protocol=pipe通过一个命名管道来连接,或ç”�--protocol=memory通过共享内存来连接。对äº�TCP/IP连接,你可能还需要指å®�--hostå’�--port选项。对于其它类型的连接,你可能需要指定一ä¸�--socket选项来指定一ä¸�Unix套接字文件或命名管道名,或者一ä¸�--shared-memory-base-name选项来指定共享内存名。共享内存连接仅åœ�Windows中支持ã€�

·         åœ�Unix中,在你启动客户端之前,设置MYSQL_UNIX_PORTå’�MYSQL_TCP_PORT环境变量来指å®�Unix套接字文件和TCP/IP端口号。如果你经常使用具体的套接字文件或端口号,你可以åœ�.login文件中放置命令来设置环境变量以便你每次登录时该命令起作用。参è§�附录Fï¼�环境变量ã€�

·         在一个选项文件çš�[client]组中指定默认Unix套接字文件和TCP/IP端口号。例如,你可以在Windows中使ç”�C:\my.cnf文件,或åœ�Unix中主目录内使ç”�.my.cnf文件。参è§�4.3.2节,“使用选项文件â€�ã€�

·         åœ�C程序中,åœ�mysql_real_connect()调用时,你可以指定套接字文件或端口号参数。通过调用mysql_options()ï¼�你还可以有程序读选项文件。参è§�25.2.3节,“C API函数描述â€�ã€�

·         如果你正在使ç”�Perl DBD::mysql模块,你可以ä»�MySQL选项文件中读取选项。例如:

·                $dsn = "DBI:mysql:test;mysql_read_default_group=client;"
·                        . "mysql_read_default_file=/usr/local/mysql/data/my.cnf";
·                    $dbh = DBI->connect($dsn, $user, $password);

参见25.4节,“MySQL Perl APIâ€�ã€�

其它程序接口可以为读选项文件提供相似的功能ã€�

5.13. MySQL查询高速缓å†�

查询缓存存储SELECT查询的文本以及发送给客户端的相应结果。如果随后收到一个相同的查询,服务器从查询缓存中重新得到查询结果,而不再需要解析和执行查询ã€�

如果你有一个不经常改变的表并且服务器收到该表的大量相同查询,查询缓存在这样的应用环境中十分有用。对于许å¤�Web服务器来说存在这种典型情况,它根据数据库内容生成大量的动态页靀€�

æ³�释:查询缓存不返回旧的数据。当表更改后,查询缓存值的相关条目被清空ã€�

æ³�释:如果你有许多mysqld服务器更新相同的MyISAM表,在这种情况下查询缓存不起作用ã€�

æ³�释:查询缓存不适用于服务器方编写的语句。如果正在使用服务器方编写的语句,要考虑到这些语句将不会应用查询缓存。参è§� 25.2.4节,“C API预处理语句â€�ã€�

下面是查询缓存的一些性能数据。这些结果是åœ�Linux Alpha 2 x 500MHz系统ï¼�2GB RAMï¼�64MB查询缓存)上运行MySQL基准组件产生的ã€�

·         如果执行的所有查询是简单的(如从只有一行数据的表中选取一è¡�),但查询是不同的,查询不能被缓存,查询缓存激活率æ˜�13%。这可以看作是最坏的情形。在实际应用中,查询要复杂得多,因此,查询缓存使用率一般会很低ã€�

·         从只有一行的表中查找一行数据时,使用查询缓存比不使用速度å¿�238%。这可以看作查询使用缓存时速度提高最小的情况ã€�

服务器启动时要禁用查询缓存,设置query_cache_size系统变量ä¸�0。禁用查询缓存代码后ï¼�没有明显的速度提高ã€�编译MySQL时,通过åœ�configureä¸�使用--without-query-cache选项,可以从服务器中彻底去除查询缓存能力ã€�

5.13.1. 查询高速缓冲如何工ä½�

本节描述查询缓存的工作原理ã€�5.13.3节,“查询高速缓冲配置â€�描述了怎样控制是否使用查询缓存ã€�

查询解析之前进行比较,因此下面的两个查询被查询缓存认为是不相同的ï¼�

SELECT * FROM tbl_name
Select * from tbl_name

查询必须是完全相同的(逐字节相å��)才能够被认为是相同的。另外,同样的查询字符串由于其它原因可能认为是不同的。使用不同的数据库、不同的协议版本或者不å�� 默认字符集的查询被认为是不同的查询并且分别进行缓存ã€�

从查询缓存中提取一个查询之前,MySQL检查用户对所有相关数据库和表çš�SELECT权限ã€�如果没有权限ï¼�不使用缓存结果ã€�

如果从查询缓存中返回一个查询结果,服务器把Qcache_hits状态变量的值加一,而不æ˜�Com_select变量。参è§�5.13.4节,“查询高速缓冲状态和维护â€�ã€�

如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使ç”�MERGE表的查询。一个表可以被许多类型的语句更改,例å¦�INSERTã€�UPDATEã€�DELETEã€�TRUNCATEã€�ALTER TABLEã€�DROP TABLEæˆ�DROP DATABASEã€�

COMMIT执行完后,被更改的事åŠ�InnoDB表不再有效ã€�

使用InnoDB表时,查询缓存也在事务中工作,使用该表的版本号来检测其内容是否仍旧是当前的ã€�

åœ�MySQL 5.1中,视图产生的查询被缓存ã€�

SELECT SQL_CALC_FOUND_ROWS ...å’�SELECT FOUND_ROWS() type类型的查询使用查询缓存。即使因创建的行数也被保存在缓冲区内,前面的查询从缓存中提取ï¼�FOUND_ROWS()也返回正确的值ã€�

如果一个查询包含下面函数中的任何一个,它不会被缓存ï¼�

BENCHMARK()

CONNECTION_ID()

CURDATE()

CURRENT_DATE()

CURRENT_TIME()

CURRENT_TIMESTAMP()

CURTIME()

DATABASE()

带一个参数的ENCRYPT()

FOUND_ROWS()

GET_LOCK()

LAST_INSERT_ID()

LOAD_FILE()

MASTER_POS_WAIT()

NOW()

RAND()

RELEASE_LOCK()

SYSDATE()

不带参数çš�UNIX_TIMESTAMP()

USER()

 

在下面的这些条件下,查询也不会被缓存ï¼�

·         引用自定义函æ•�(UDFs)ã€�

·         引用自定义变量ã€�

·         引用mysql系统数据库中的表ã€�

·         下面方式中的任何一种:

SELECT ...IN SHARE MODE
SELECT ...FOR UPDATE
SELECT ...INTO OUTFILE ...
SELECT ...INTO DUMPFILE ...
SELECT * FROM ...WHERE autoincrement_col IS NULL

最后一种方式不能被缓存是因为它被用作为ODBC工作区来获取最近插入的ID值。参è§�26.1.14.1节,“如何在ODBC中获取AUTO_INCREMENT列的å€�â€�ã€�

·          被作为编写好的语句,即使没有使用占位符。例如,下面使用的查询:

char *my_sql_stmt = "SELECT a�b FROM table_c";
   /* ...*/
mysql_stmt_prepare(stmt�my_sql_stmt�strlen(my_sql_stmt));

不被缓存。参è§�25.2.4节,“C API预处理语句â€�ã€�

·         使用TEMPORARY表ã€�

·         不使用任何表ã€�

·         用户有某个表的列级权限ã€�

5.13.2. 查询高速缓冲SELECT选项

可以åœ�SELECT语句中指定查询缓存相关选项ï¼�

·          SQL_CACHE

如果query_cache_type系统变量的值是ONæˆ�DEMANDï¼�查询结果被缓存ã€�

·          SQL_NO_CACHE

查询结果不被缓存ã€�

示例ï¼�

SELECT SQL_CACHE id, name FROM customer;
SELECT SQL_NO_CACHE id, name FROM customer;

5.13.3. 查询高速缓冲配ç½�

通过have_query_cache服务器系统变量指示查询缓存是否可用:

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+

即使禁用查询缓存,当使用标准 MySQL二进制时,这个值总是YESã€�

其它几个系统变量控制查询缓存操作。当启动mysqld时,这些变量可以在选项文件或者命令行中设置。所有查询缓存系统变量名ä»�query_cache_ 开头。它们的详细描述è§�5.3.3节,“服务器系统变量â€�,还给出了额外的配置信息ã€�

为了设置查询缓存大小,设ç½�query_cache_size系统变量。设置为0表示禁用查询缓存ã€� 默认缓存大小设置ä¸�0;也就是禁用查询缓存ã€�

当设ç½�query_cache_size变量为非零值时,应记住查询缓存至少大约需è¦�40KB来分配其数据结构ã€�(具体大小取决于系统结构)ã€�如果你把该值设置的太小,将会得到一个警告,如本例所示:

mysql> SET GLOBAL query_cache_size = 40000;

Query OK, 0 rows affected, 1 warning (0.00 sec)

 

mysql> SHOW WARNINGS\G

*************************** 1. row ***************************

  Level: Warning

   Code: 1282

Message: Query cache failed to set size 39936; new query cache size is 0

 

mysql> SET GLOBAL query_cache_size = 41984;

Query OK, 0 rows affected (0.00 sec)

 

mysql> SHOW VARIABLES LIKE 'query_cache_size';

+------------------+-------+

| Variable_name    | Value |

+------------------+-------+

| query_cache_size | 41984 |

+------------------+-------+

如果查询缓存大小设置为大äº�0ï¼�query_cache_type变量影响其工作方式。这个变量可以设置为下面的值:

·         0æˆ�OFF将阻止缓存或查询缓存结果ã€�

·         1æˆ�ON将允许缓存,ä»�SELECT SQL_NO_CACHE开始的查询语句除外ã€�

·         2æˆ�DEMAND,仅对以SELECT SQL_CACHE开始的那些查询语句启用缓存ã€�

设置query_cache_type变量çš�GLOBAL值将决定更改后所有连接客户端的缓存行为。具体客户端可以通过设置query_cache_type变量的会话值控制它们本身连接的缓存行为。例如,一个客户可以禁用自己的查询缓存,方法如下:

mysql> SET SESSION query_cache_type = OFF;

要控制可以被缓存的具体查询结果的最大值,应设ç½�query_cache_limit变量ã€� 默认值是1MBã€�

当一个查询结果(返回给客户端的数据)从查询缓冲中提取期间,它在查询缓存中排序。因此,数据通常不在大的数据块中处理。查询缓存根据数据排序要求分配数据块,因此,当一个数据块用完后分配一个新的数据块。因为内存分配操作是昂贵çš�(费时çš�),所以通过query_cache_min_res_unit系统变量给查询缓存分配最小值。当查询执行时,最新的结果数据块根据实际数据大小来确定,因此可以释放不使用的内存。根据你的服务器执行查询的类型,你会发现调整query_cache_min_res_unit变量的值是有用的:

·         query_cache_min_res_unit默认值是4KB。这应该适合大部分情况ã€�

·         如果你有大量返回小结果数据的查询,默认数据块大小可能会导致内存碎片,显示为大量空闲内存块。由于缺少内存,内存碎片会强制查询缓存从缓存内存中修整(删除)查诀€‚这时,你应该减å°�query_cache_min_res_unit变量的值。空闲块和由于修整而移出的查询的数量通过Qcache_free_blockså’�Qcache_lowmem_prunes变量的值给出ã€�

·          如果大量查询返回大结果(检æŸ� Qcache_total_blockså’�Qcache_queries_in_cache状态变量),你可以通过增加query_cache_min_res_unit变量的值来提高性能。但是,注意不要使它变得太大(参见前面的条目)ã€�

5.13.4. 查询高速缓冲状态和维护

可以使用下面的语句检æŸ�MySQL服务器是否提供查询缓存功能:

mysql> SHOW VARIABLES LIKE 'have_query_cache';

+------------------+-------+

| Variable_name    | Value |

+------------------+-------+

| have_query_cache | YES   |

+------------------+-------+

可以使用FLUSH QUERY CACHE语句来清理查询缓存碎片以提高内存使用性能。该语句不从缓存中移出任何查诀€�

RESET QUERY CACHE语句从查询缓存中移出所有查诀€�FLUSH TABLES语句也执行同样的工作ã€�

为了监视查询缓存性能,使ç”�SHOW STATUS查看缓存状态变量:

mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+--------+
|变量å��                   |å€� |
+-------------------------+--------+
| Qcache_free_blocks      | 36     |
| Qcache_free_memory      | 138488 |
| Qcache_hits             | 79570  |
| Qcache_inserts          | 27087  |
| Qcache_lowmem_prunes    | 3114   |
| Qcache_not_cached       | 22989  |
| Qcache_queries_in_cache | 415    |
| Qcache_total_blocks     | 912    |
+-------------------------+--------+

这些变量的描述见5.3.4节,“服务器状态变量â€�。这里描述它们的一些应用ã€�

SELECT查询的总数量等价于ï¼�

Com_select
+ Qcache_hits
+ queries with errors found by parser

Com_select的值等价于ï¼�

Qcache_inserts
+ Qcache_not_cached
+ queries with errors found during columns/rights check

查询缓存使用长度可变块,因此Qcache_total_blockså’�Qcache_free_blocks可以显示查询缓存内存碎片。执è¡�FLUSH QUERY CACHE后,只保留一个空闲块ã€�

每个缓存查询至少需要两个块(一个块用于查询文本,一个或多个块用于查询结果)。并且,每一个查询使用的每个表需要一个块。但是,如果两个或多个查询使用相同的表,仅需要分配一个块ã€�

Qcache_lowmem_prunes状态变量提供的信息能够帮助你你调整查询缓存的大小。它计算为了缓存新的查询而从查询缓冲区中移出到自由内存中的查询的数目。查询缓冲区使用最近最少使ç”�(LRU)策略来确定哪些查询从缓冲区中移出。调整信息在5.13.3节,“查询高速缓冲配置â€�中给出ã€�


这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访é—�dev.mysql.comã€� 原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的ã€�