mysql5.5手册读书日记(1)

<?php

//mysql语句使用技巧

/*
* 我的数据库是5.5.2
*
* 查询当前用户的登陆的名字
* select user();
*
* 查询当前mysql服务器时间和服务器版本
* select version(),current_time;
*
*
* 修改一个字段的属性
*
*
* 查看mysql数据库的user表,查看授权用户
* use user;
* select host,user,password from user;
*
* 在shell 或者dos下登陆mysql
* 2者都需要吧mysql命令加入服务,或者切换到对应的目录下
* mysql -h 127.0.0.1 -u root -p root
*
* 查询所有数据库
* show databases;
*
* 查询所有表
* show tables;
*
*
* 修改表名字,表字段属性
* ALTER TABLE `shopnc_address` CHANGE `address` `address1` VARCHAR( 2000 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址'
* 原表名 新表名 字段属性和长度改变 字符集 为NULL
*
*
*
* 授权
* GRANT ALL PRIVILEGES ON *.* TO 'zx'@'localhost' IDENTIFIED BY 'zx123456' WITH GRANT OPTION;
* 所有权限 数据库.表 用户名 host主机 密码
*
* 刷新权限
* FLUSH PRIVILEGES;
*
* 查看用户授权
* show grants for user_name;可能是因为版本原因不能显示
*
*
* --safe-user-create
如果启用,用户不能用GRANT语句创建新用户,除非用户有mysql.user表的INSERT权限。如果你想让用户具有授权权限来创建新用户,你应给用户授予下面
的权限:
* GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name';
*
*
*
* 收回权限
* REVOKE ALL PRIVILEGES ON *.* FROM myuser;
* 或者直接去user表删除用户也可以
* delete from user where user = 'myuser';
*
* 查看表结果
* DESCRIBE user;或者 show create table shopnc_orders;
*
*
* 查看一张表的索引
* show index from shopnc_orders;
*
* 查看系统的变量
* show variables;
*
* 查看每个表的信息
* show table status;
*
* 查看mysql的状态信息
* show status;
*
* 查看显示服务器所支持的不同权限
* show privileges;
*
* 查看创建数据库的信息
* show create database shopnc;
*
* 查看mysql支持那些数据库引擎
* show engines;
*
* 查看innodb的状态
* show innodb status;//有些有版本问题,无法显示
*
*
* 给表增加一个字段
* ALTER TABLE `shopnc_address` ADD `ss` VARCHAR( 24 ) NOT NULL AFTER `dlyp_id`
*
*
*
*
* 从本文件导入数据库
*
* windows和linux路径的斜杠是不一样的,请注意如果用Windows中的编辑器(使用 做为行的结束符)创建文件,应使用:
* LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet
* LINES TERMINATED BY ' ';
* 在运行OS X的Apple机上,应使用行结束符' '。
* 因为不同系统和文件格式的需要不一样,请更具详细文档在使用
*
*
* 匹配模式,
* 匹配p大头的数据
*SELECT * FROM zx WHERE name LIKE 'p%';
*
* 匹配p结尾的数据
* SELECT * FROM zx WHERE name LIKE '%p';
*
* 匹配含有p的数据
* SELECT * FROM zx WHERE name LIKE '%p%';
*
*
* 匹配长度为3的数据
* SELECT * FROM zx WHERE name LIKE '___';
*
* mysql还可以使用正则表达式函数
* 用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它们是同义词)。
*
* SELECT * FROM pet WHERE name REGEXP BINARY '^b'; 匹配以b大头的name
*
* SELECT * FROM pet WHERE name REGEXP 'fy$';匹配以fy结尾的name
*
*
* 选择最大的article数值,别名为article字段名,表别名也是一样
* SELECT MAX(article) AS article FROM shop;
*
*
* concat函数
* 返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL
*
* mysql> select concat('11','22','33');
+------------------------+
| concat('11','22','33') |
+------------------------+
| 112233 |
+------------------------+
*
mysql> select concat('11','22',NULL);
+------------------------+
| concat('11','22',NULL) |
+------------------------+
| NULL |
+------------------------+
*
*
*
mysqld是MySQL服务器
mysqld_safe、mysql.server和mysqld_multi是服务器启动脚本
mysql_install_db初始化数据目录和初始数据库
*
mysql是一个命令行客户程序,用于交互式或以批处理模式执行SQL语句。
o mysqladmin是用于管理功能的客户程序。
o mysqlcheck执行表维护操作。
o mysqldump和mysqlhotcopy负责数据库备份。
o mysqlimport导入数据文件。
o mysqlshow显示信息数据库和表的相关信息。
*
myisamchk执行表维护操作。
o myisampack产生压缩、只读的表。
o mysqlbinlog是处理二进制日志文件的实用工具。
o perror显示错误代码的含义。
*
* 一些命令的使用
shell> mysql test
shell> mysqladmin extended-status variables
shell> mysqlshow --help
shell> mysqldump --user=root personnel
*
*
*
* 对于带选项值的长选项,通过一个‘=’将选项名和值隔离开来。对于带选项值的短选项,选项值可以紧随选项字母后面,或者二者之间可以用一个空格隔开。(-hlocalhost和-h localhost是等效的)。该规则的
例外情况是指定MySQL密码的选项。该选项的形式可以为--password=pass_val或--password。在后一种情况(未给出密码值),程序将提示输入密码。也可以给出密码选项,短形式为-ppass_val或-p。然而,对于
短形式,如果给出了密码值,必须紧跟在选项后面,中间不能插入空格。这样要求的原因是如果选项后面有空格,程序没有办法来告知后面的参量是密码值还是其它某种参量。因此,下面两个命令的含义完全不
同:
· shell> mysql -ptest
· shell> mysql -p test

第一个命令让mysql使用密码test,但没有指定默认数据库。第二个命令让mysql提示输入密码并使用test作为默认数据库。
*
*
*
*
*
部分选项控制可以开关的行为。例如,mysql客户端支持--column-names选项,确定是否在查询结果开头显示一行栏目名。默认情况,该选项被启用。但是可能在某些情况下你想要禁用它,例如将mysql的输出
发送到另一个只希望看到数据而不希望看到开始的标题行的程序中。
要想禁用列名,可以使用下面的形式来指定选项:
--disable-column-names
--skip-column-names
--column-names=0
--disable和--skip前缀与=0后缀的效果相同:它们均关闭选项。
可以用下述方法“启用”选项:
--column-names
--enable-column-names
--column-names=1
*
*
*
*
*
对mysql偶尔有用的另一个选项是-e或--execute选项,可用来将SQL语句传递给服务器。该语句必须用引号引起来(单引号或双引号)。(然而,如果想要在查询中将值引起来,则对于查询应使用双引号,查询中引
用的值应使用单引号)。当使用该选项时,语句被执行,然后mysql立即退出命令外壳。
例如,你可以用下面的命令获得用户账户列表:
shell> mysql -u root -p -e "SELECT User, Host FROM User" mysql
Enter password: ******
+------+-----------+
| User | Host |
+------+-----------+
| | gigan |
| root | gigan |
| | localhost |
| jon | localhost |
| root | localhost |
+------+-----------+
后面的mysql是数据库名字
*
*
* 查看系统变量
* show variables like '%log%';
* 查看所有系统变量
* show variables
*
查看是否支持分区
mysql> show variables like '%partition%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| have_partitioning | YES |
+-------------------+-------+
* 查看支持的插件
mysql> show plugins;
+-----------------------+----------+--------------------+---------+---------+
| Name | Status | Type | Library | License |
+-----------------------+----------+--------------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| mysql_old_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
+-----------------------+----------+--------------------+---------+---------+
*
*
*
*

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节,“升级授权表”。
服务器主机上还运行其它几个程序:
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
· 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节,“如何
通报缺陷和问题”)。

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

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版本,因此你应对你修改的版本进行备份以便将
来重装。


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
指定日志文件名。如果该文件存在,后面为日志输出。
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
· --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]组来说明你的选项文件可以稍有不同。这样给你更大的灵活
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
性。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

START INSTANCE mysqld4;启动一个MySQL实例 配置在my.cnf里面的[mysqld4]段里配置

显示所有载入的实例名:
mysql> show instances;


显示选定的实例的状态和版本信息:
SHOW INSTANCE STATUS mysqld3;


显示实例使用的选项:
mysql> SHOW INSTANCE OPTIONS mysqld3;、


该命令提供实例使用的所有日志文件
SHOW mysqld LOG FILES;


查看所有的日志文件所在位置 很方便
SHOW VARIABLES LIKE '%log%'
以上所有的命令都可以在phpmyadmin上运行,这样看起来就更方便,控制台的显示方式不太友好

Variable_name Value
back_log 50
binlog_cache_size 32768
binlog_direct_non_transactional_updates OFF
binlog_format MIXED
binlog_stmt_cache_size 32768
expire_logs_days 0
general_log OFF
general_log_file c:wampinmysqlmysql5.5.20dataUSER-20141003JG...
innodb_flush_log_at_trx_commit 1
innodb_locks_unsafe_for_binlog OFF
innodb_log_buffer_size 8388608
innodb_log_file_size 5242880
innodb_log_files_in_group 2
innodb_log_group_home_dir .
innodb_mirrored_log_groups 1
log OFF
log_bin ON
log_bin_trust_function_creators OFF
log_error c:wamplogsmysql.log
log_output FILE
log_queries_not_using_indexes OFF
log_slave_updates OFF
log_slow_queries OFF
log_warnings 1
max_binlog_cache_size 18446744073709547520
max_binlog_size 1073741824
max_binlog_stmt_cache_size 18446744073709547520
max_relay_log_size 0
relay_log
relay_log_index
relay_log_info_file relay-log.info
relay_log_purge ON
relay_log_recovery OFF
relay_log_space_limit 0
slow_query_log OFF
slow_query_log_file c:wampinmysqlmysql5.5.20dataUSER-20141003JG...
sql_log_bin ON
sql_log_off OFF
sync_binlog 0
sync_relay_log 0
sync_relay_log_info 0


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 |
+-------------+------------------------------------+----------+
*
*
*
*
*
*
* 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的启动模式
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
*
*
*
*
*
* 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;
*
*
*
*
*
*
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
FilesMySQLMySQL Server 5.1,命令应为:
C:> C:Program FilesMySQLMySQL Server 5.1inmysql -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警告;你可以忽略它们。
运行完脚本后,停止服务器并重启。
*
*
*
*
*
*
* 尝试访问mysql端口是否可以联通
* telnet server_IP或者server_HOST 3306
*
*
*
* 如果你从源码构建MySQL但没有使用--enable-local-infile选项来进行configure,则客户不能使用LOAD DATA LOCAL,除非显式调用mysql_options
(...MYSQL_OPT_本地_INFILE,0)
你可以用--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选项。但是,为了便面不理解localinfile
的程序产生问题,则规定使用loose- prefix:
· [client]
· loose-local-infile=1
· 如果LOAD DATA LOCAL INFILE在服务器或客户端被禁用,试图执行该语句的客户端将收到下面的错误消息:
ERROR 1148: The used command is not allowed with this MySQL version
*
*
* MySQL提供的权限

权限 列 上下文
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 服务器管理
*
*
*
* 其余的权限用于管理性操作,它使用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权限系统做到:
你不能明显地指定某个给定的用户应该被拒绝访问。即,你不能明显地匹配用户然后拒绝连接。
你不能指定用户有权创建立或删除数据库中的表,但不能创建或删除数据库本身。
*
*
*
*
*
*
如果你连接时指定主机名,但得到错误消息主机名未显示或为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主机名缓存
*
*
*
* 一些常用的解决方案包括:
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密码后,在清
空权限前,你不需要指定新密码,因为服务器还不知道你已经更改了密码!
*
*
*
*
在MySQL 4.1之前,用PASSWORD()函数计算的密码哈希值有16个字节长。应为:
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
*
*
在MySQL 4.1中,已经对PASSWORD()函数进行了修改,可以生成41字节的哈希值:
mysql> SELECT PASSWORD('mypass');
+-------------------------------------------+
| PASSWORD('mypass') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
*
*
*
*
限制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限制。
当服务器启动时所有记数从零开始。
*
*
*
*
*
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=tonu@example.com';
请注意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=tonu@example.com';
请注意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=tonu@example.com'
-> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
-> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
请注意SUBJECT和ISSUER值应做为单一字符串输入。
在MySQL 5.1中,在REQUIRE选项之间可以选用AND关键字。
选项的顺序不重要,但任何选项不能用两次。
*
*
*
*
备份数据库的另一个技术是使用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. 卸载快照。
*
*
*
*
*
*
*
*
*
*
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
这是在线非块备份,不会干扰对表的读写。我们以前假定我们的表为InnoDB表,因此--single-transaction使用一致性地读,并且保证mysqldump所看见的数
据不会更改。(其它客户端对InnoDB表进行的更改不会被mysqldump进程看见)。如果我们还有其它类型的表,我们必须假定在备份过程中它们不会更改。
例如,对于mysql数据库中的MyISAM表,我们必须假定在备份过程中没有对MySQL账户进行管理更改。

--single-transaction
InnoDB 表在备份时,通常启用选项 --single-transaction 来保证备份的一致性,实际上它的工作原理是设定本次会话的隔离级别为:REPEATABLE READ,以确保本次会话(dump)时,不会看到其他会话已经提交了的数据。
*
*
*
在星期一下午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二进制日志之前应进行确认
*
*
*
*
*
*
*
为恢复进行备份
现在假设在星期三上午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文件,我们可以用它来恢复大部分最新的数据更改,而不会丢失到崩溃时的数据
*
*
*
* 指定恢复时间
如果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密码。
指定恢复时间
对于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前一秒钟。你应检查日志
以确保时间确切。下一节介绍如何实现。
*
*
*
表维护和崩溃恢复
后面几节讨论如何使用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和服务器之
间会出现不期望的相互干涉。
*
*
*
*
可以使用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
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
该命令假定你有大于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来检查表
*
*
*
*
*
*
可以使用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来检查表
*
*
*
*
*
*
*
*
服务器时区支持
MySQL服务器有几个时区设置:
· 系统时区。服务器启动时便试图确定主机的时区,用它来设置system_time_zone系统变量。
· 服务器当前的时区。全局系统变量time_zone表示服务器当前使用的时区。初使值为'SYSTEM',说明服务器时区与系统时区相同。可以用--defaulttime-
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和系统上其它应用程序处理日
期时间的方法会有所不同。
*
*
*
MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:
日志文件记入文件中的信息类型
错误日志记录启动、运行或停止mysqld时出现的问题。
查询日志记录建立的客户端连接和执行的语句。
更新日志记录更改数据的语句。不赞成使用该日志。
二进制日志记录所有更改数据的语句。还用于复制。
慢日志记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。
默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日
志)。当你执行一个FLUSH LOGS语句或执行mysqladmin flush-logs或mysqladmin refresh时,出现日志刷新。参见13.5.5.2节,“FLUSH语法”。
如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志
*
*
*
*
*
*
*
*
MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:
日志文件记入文件中的信息类型
错误日志记录启动、运行或停止mysqld时出现的问题。
查询日志记录建立的客户端连接和执行的语句。
更新日志记录更改数据的语句。不赞成使用该日志。
二进制日志记录所有更改数据的语句。还用于复制。
慢日志记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。
默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日
志)。当你执行一个FLUSH LOGS语句或执行mysqladmin flush-logs或mysqladmin refresh时,出现日志刷新。参见13.5.5.2节,“FLUSH语法”。
如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志
*
*
*
*
*
*
*
*
*
做为服务启动多个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.8inmysqld-nt --install mysqld1
C:> C:mysql-5.1.2-alphainmysqld-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.8inmysqld-nt -- installmysqld1
--defaults-file=C:my-opts1.cnf
C:> C:mysql-5.1.2-alphainmysqld-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脚本是启动多个服务器的另一个方法
*
*
*
*
在多服务器环境中使用客户端程序
当你想要用一个客户端程序连接一个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.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表。
· 不使用任何表。
· 用户有某个表的列级权限。
*
*
*
*
*
*
查询高速缓冲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 WARNINGSG
*************************** 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节,“查询高速缓冲配置”中给出。
*
*
*
*
从服务器设置为复制主服务器的数据后,它连接主服务器并等待更新过程。如果主服务器失败,或者从服务器
失去与主服务器之间的连接,从服务器保持定期尝试连接,直到它能够继续帧听更新。由--master-connectretry
选项控制重试间隔。默认为60秒
*
*

复制实施细节
MySQL使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,
从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线
程将二进制日志中的内容发送到从服务器。该线程可以识别为主服务器上SHOW PROCESSLIST的输出中
的Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器
数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,是从服务器创建用于读取中继日志并执行日
志中包含的更新。
在前面的描述中,每个从服务器有3个线程。有多个从服务器的主服务器创建为每个当前连接的从服务器创建
一个线程;每个从服务器有自己的I/O和SQL线程。
这样读取和执行语句被分成两个独立的任务。如果语句执行较慢则语句读取任务没有慢下来。例如,如果从服
I/O

务器有一段时间没有运行了,当从服务器启动时,其线程可以很快地从主服务器索取所有二进制日志内
容,即使SQL线程远远滞后。如果从服务器在SQL线程执行完所有索取的语句前停止,I/O 线程至少已经索取
了所有内容,以便语句的安全拷贝保存到本地从服务器的中继日志中,供从服务器下次启动时执行。这样允许
清空主服务器上的二进制日志,因为不再需要等候从服务器来索取其内容。
SHOW PROCESSLIST语句可以提供在主服务器上和从服务器上发生的关于复制的信息。
下面的例子说明了这3个线程在SHOW PROCESSLIST中的显示。
在主服务器上,SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLISTG
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL
这儿,线程2是一个连接从服务器的复制线程。该信息表示所有主要更新已经被发送到从服务器,主服务器正
等待更多的更新出现。
在从服务器上,SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLISTG
*************************** 1. row ***************************
Id: 10
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 11
User: system user
Host:
db: NULL
Command: Connect
Time: 11

State: Has read all relay log; waiting for the slave I/O
thread to update it
Info: NULL
该信息表示线程10是同主服务器通信的I/O线程,线程11是处理保存在中继日志中的更新的SQL线程。SHOW
PROCESSLIST运行时,两个线程均空闲,等待其它更新。
请注意Time列的值可以显示从服务器比主服务器滞后多长时间
*
*
*
*
*
*
*
复制主线程状态
下面列出了主服务器的Binlog Dump线程的State列的最常见的状态。如果你没有在主服务器上看见任何Binlog
Dump线程,这说明复制没有在运行—即,目前没有连接任何从服务器。
· Sending binlog event to slave
二进制日志由各种事件组成,一个事件通常为一个更新加一些其它信息。线程已经从二进制日志读取了一个事
件并且正将它发送到从服务器。
· Finished reading one binlog; switching to next binlog
线程已经读完二进制日志文件并且正打开下一个要发送到从服务器的日志文件。
· Has sent all binlog to slave; waiting for binlog to be updated
线程已经从二进制日志读取所有主要的更新并已经发送到了从服务器。线程现在正空闲,等待由主服务器上新
的更新导致的出现在二进制日志中的新事件。
· Waiting to finalize termination
线程停止时发生的一个很简单的状态。
6.3.2. 复制从I/O线程状态
下面列出了从服务器的I/O线程的State列的最常见的状态。该状态也出现在Slave_IO_State列,由SHOW
SLAVE STATUS显示。这说明你可以只通过该语句仔细浏览所发生的事情。
· Connecting to master
线程正试图连接主服务器。
· Checking master version
建立同主服务器之间的连接后立即临时出现的状态。
· Registering slave on master
建立同主服务器之间的连接后立即临时出现的状态。
· Requesting binlog dump
建立同主服务器之间的连接后立即临时出现的状态。线程向主服务器发送一条请求,索取从请求的二进制日志
文件名和位置开始的二进制日志的内容。
· Waiting to reconnect after a failed binlog dump request

如果二进制日志转储请求失败(由于没有连接),线程进入睡眠状态,然后定期尝试重新连接。可以使用--
master-connect-retry选项指定重试之间的间隔。
· Reconnecting after a failed binlog dump request
线程正尝试重新连接主服务器。
· Waiting for master to send event
线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待
持续slave_read_timeout秒,则发生超时。此时,线程认为连接被中断并企图重新连接。
· Queueing master event to the relay log
线程已经读取一个事件,正将它复制到中继日志供SQL线程来处理。
· Waiting to reconnect after a failed master event read
读取时(由于没有连接)出现错误。线程企图重新连接前将睡眠master-connect-retry秒。
· Reconnecting after a failed master event read
线程正尝试重新连接主服务器。当连接重新建立后,状态变为Waiting for master to send event。
· Waiting for the slave SQL thread to free enough relay log space
正使用一个非零relay_log_space_limit值,中继日志已经增长到其组合大小超过该值。I/O线程正等待直
到SQL线程处理中继日志内容并删除部分中继日志文件来释放足够的空间。
· Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
6.3.3. 复制从SQL线程状态
下面列出了从服务器的SQL线程的State列的最常见的状态。
· Reading event from the relay log
线程已经从中继日志读取一个事件,可以对事件进行处理了。
· Has read all relay log; waiting for the slave I/O thread to update it
线程已经处理了中继日志文件中的所有事件,现在正等待I/O线程将新事件写入中继日志。
· Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
I/O线程的State列也可以显示语句的文本。这说明线程已经从中继日志读取了一个事件,从中提取了语句,并
且正在执行语句。
6.3.4. 复制传递和状态文件
默认情况,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机

名,nnnnnn是序列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪索引文件中目
前正使用的中继日志。默认中继日志索引文件名为host_name-relay-bin.index。默认情况,在从服务器的数据
目录中创建这些文件。可以用--relay-log和--relay-log-index服务器选项覆盖默认文件名。参见6.8节,“复制启
动选项”。
中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并
且不再需要之后,立即自动删除它。没有直接的删除中继日志的机制,因为SQL线程可以负责完成。然
而,FLUSH LOGS可以循环中继日志,当SQL线程删除日志时会有影响。
在下面的条件下创建新的中继日志:
· 每次I/O线程启动时创建一个新的中继日志。
· 当日志被刷新时;例如,用FLUSH LOGS或mysqladmin flush-logs。
· 当当前的中继日志文件变得太大时。“太大”含义的确定方法:
o max_relay_log_size,如果max_relay_log_size > 0
o max_binlog_size,如果max_relay_log_size = 0
从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。它
们包含SHOW SLAVE STATUS语句的输出所显示的信息(关于该语句的描述参见13.6.2节,“用于控制从服务器
的SQL语句”)。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确
定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。
由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
行描述
1 文件中的行号
2 Master_Log_File
3 Read_Master_Log_Pos
4 Master_Host
5 Master_User
6 密码(不由SHOW SLAVE STATUS显示)
7 Master_Port
8 Connect_Retry
9 Master_SSL_Allowed
10 Master_SSL_CA_File
11 Master_SSL_CA_Path
12 Master_SSL_Cert
13 Master_SSL_Cipher
14 Master_SSL_Key
由SQL线程更新relay-log.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
行描述
1 Relay_Log_File
2 Relay_Log_Pos
3 Relay_Master_Log_File
4 Exec_Master_Log_Pos
Chapter 6. Replication in MySQL
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/replication.html[2010/2/24 5:22:02]
当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继
续进行复制。如果丢失了中继日志但仍然有relay-log.info文件,你可以通过检查该文件来确定SQL线程已经执
行的主服务器中二进制日志的程度。然后可以用Master_Log_File和Master_LOG_POS选项执行CHANGE
MASTER TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。
如果从服务器正复制LOAD DATA INFILE语句,你应也备份该目录内从服务器用于该目的的任何SQL_LOAD-
*文件。从服务器需要这些文件继续复制任何中断的LOAD DATA INFILE操作。用--slave-load-tmpdir选项来指
定目录的位置。如果未指定, 默认值为tmpdir变量的值。
*
*
*
*
*
*
*
假定你的域为mydomain.com,想要创建用户名为repl的一个账户,从服务器可以使用该账户从你的域内的任何
主机使用密码slavepass来访问主服务器。要创建该账户,可使用GRANT语句:
mysql> GRANT REPLICATION SLAVE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
如果你计划从从属服务器主机使用LOAD TABLE FROM MASTER或LOAD DATA FROM MASTER语句,你需要授
予该账户其它权限:
· 授予账户SUPER和RELOAD全局权限。
· 为所有想要装载的表授予SELECT权限。任何该账户不能SELECT的主服务器上的表被LOAD DATA
FROM MASTER忽略掉。
3. 执行FLUSH TABLES WITH READ LOCK语句清空所有表和块写入语句:
4. mysql> FLUSH TABLES WITH READ LOCK;
对于InnoDB表,请注意:FLUSH TABLES WITH READ LOCK还锁定COMMIT操作。当获得全局读锁定后,可以

开始InnoDB表的文件系统快照。快照不能保证内部(在InnoDB存储引擎内部)一致性(因为InnoDB缓存没有刷
新),但并不需要关心该问题,因为InnoDB可以在启动时解决该问题并给出一致的结果。这说明InnoDB在启动
快照时可以进行崩溃恢复,而不会破坏。然而,当保证一致的InnoDB表快照时,还没有途径来停止MySQL服
务器。
让客户程序保持运行,发出FLUSH TABLES语句让读锁定保持有效。(如果退出客户程序,锁被释放)。然后对
主服务器上的数据进行快照。
创建快照最简单的途径是使用归档程序对主服务器上的数据目录中的数据库进行二进制备份。例如,在Unix中
使用tar,或者在Windows中使用PowerArchiver、WinRAR、WinZip或者类似的软件。要使用tar来创建包
括所有数据库的归档文件,进入主服务器的数据目录,然后执行命令:
shell> tar -cvf /tmp/mysql-snapshot.tar .
如果你想让归档只包括this_db数据库,应使用命令:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
然后将归档文件复制到从服务器主机的/tmp目录。在该机器上,进入从服务器的数据目录,并使用下述命令解
压缩归档文件:
shell> tar -xvf /tmp/mysql-snapshot.tar
如果从服务器的用户账户与主服务器的不同,你可能不想复制mysql数据库。在这种情况下,应从归档中排除
该数据库。你也不需要在归档中包括任何日志文件或者master.info或relay-log.info文件。
当FLUSH TABLES WITH READ LOCK所置读锁定有效时,读取主服务器上当前的二进制日志名和偏移量值:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
File列显示日志名,而Position显示偏移量。在该例子中,二进制日志值为mysql-bin.003,偏移量为73。记录
该值。以后设置从服务器时需要使用这些值。它们表示复制坐标,从服务器应从该点开始从主服务器上进行新
的更新。
取得快照并记录日志名和偏移量后,可以在主服务器上重新启用写活动:
mysql> UNLOCK TABLES;
如果你正使用InnoDB表,理想情况应使用InnoDB Hot Backup工具,使用该工具可以获得一致的快照而不需
要在主服务器上进行锁定,并且可以对应从服务器上使用的快照来记录日志名和偏移量。Hot Backup是一个
附加的非免费(商业)工具,没有包含在标准 MySQL分发中。详细信息参
见http://www.innodb.com/manual.php的InnoDB Hot Backup主页。
不使用Hot Backup工具,最快捷的途径是使用InnoDB表的二进制快照来关闭主服务器并复制InnoDB数据文
件、日志文件和表定义文件(.frm文件)。要记录当前的日志文件名和偏移量,关闭服务器之前应发出下面的语
句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

然后记录前面所示的SHOW MASTER STATUS的输出中显示的日志名和偏移量。记录日志名和偏移量后,不解
锁表关闭服务器以确保服务器关闭时的快照与当前的日志文件和偏移量相对应:
shell> mysqladmin -u root shutdown
适合MyISAM和InnoDB表的另一个方法是对主服务器上的SQL进行转储而不是对前面讨论的二进制复制进行转
储。为了实现,可以在主服务器上使用mysqldump --master-data,以后将SQL转储文件装入从服务器。但
是,这样比二进制复制要慢一些。
如果主服务器运行时没有启用--logs-bin,SHOW MASTER STATUS或mysqldump --master-data显示的日
志名和位置值为空。在这种情况下,当以后指定从服务器的日志文件和位置时需要使用的值为空字符串('')和4.
5. 确保主服务器主机上my.cnf文件的[mysqld]部分包括一个log-bin选项。该部分还应有一个serverid=
Master_id选项,其中master_id必须为1到232–1之间的一个正整数值。例如:
6. [mysqld]
7. log-bin=mysql-bin
8. server-id=1
如果没有提供那些选项,应添加它们并重启服务器。
9. 停止用于从服务器的服务器并在其my.cnf文件中添加下面的行:
10. [mysqld]
11. server-id=slave_id
slave_id值同Master_id值一样,必须为1到232–1之间的一个正整数值。并且,从服务器的ID必须与主服务器
的ID不相同。例如:
[mysqld]
server-id=2
如果设置多个从服务器,每个从服务器必须有一个唯一的server-id值,必须与主服务器的以及其它从服务器的
不相同。可以认为server-id值类似于IP地址:这些ID值能唯一识别复制服务器群集中的每个服务器实例。
如果不指定一个server-id值,如果没有定义master-host,则将它设置为1;否则设置为2。请注意如果serverid
太长,主服务器拒绝所有来自从服务器的连接,并且从服务器拒绝连接到主服务器。这样,省略server-id只
适合用二进制日志备份。
12.如果对主服务器的数据进行二进制备份,启动从服务器之前将它复制到从服务器的数据目录中。确保对这
些文件和目录的权限正确。服务器 MySQL运行的用户必须能够读写文件,如同在主服务器上一样。
如果使用mysqldum备份,先启动从服务器(看下一步)。
13.启动从服务器。如果前面已经复制了,用--skip-slave-start选项启动从服务器,以便它不立即尝试连接主服
务器。你也可能想要用--logs-warnings选项启动从服务器(默认设置启用),以便在错误日志中显示更多的问题
相关的信息(例如,网络或连接问题)。放弃的连接将记入错误日志,除非其值大于1。
14.如果使用mysqldump备份主服务器的数据,将转储文件装载到从服务器:
15. shell> mysql -u root -p < dump_file.sql
16. 在从服务器上执行下面的语句,用你的系统的实际值替换选项值:
17. mysql> CHANGE MASTER TO
18. -> MASTER_HOST='master_host_name',

19. -> MASTER_USER='replication_user_name',
20. -> MASTER_PASSWORD='replication_password',
21. -> MASTER_LOG_FILE='recorded_log_file_name',
22. -> MASTER_LOG_POS=recorded_log_position;
下面的表显示了字符串选项的最大长度:
Master_Host 60
Master_USER 16
Master_PASSWORD 32
Master_Log_File 255
23.启动从服务器线程:
24. mysql> START SLAVE;
执行这些程序后,从服务器应连接主服务器,并补充自从快照以来发生的任何更新。
如果你忘记设置主服务器的server-id值,从服务器不能连接主服务器。
如果你忘记设置从服务器的server-id值,在从服务器的错误日志中会出现下面的错误:
Warning: You should set server-id to a non-0 value if master_host is set;
we will force server id to 2, but this MySQL server will not act as a slave.
如果由于其它原因不能复制,从服务器的错误日志中也会出现错误消息。
从服务器复制时,会在其数据目录中发现文件dmaster.info和relay-log.info。从服务器使用这两个文件跟踪已
经处理了多少主服务器的二进制日志。不要移除或编辑这些文件,除非你确切知你正在做什么并完全理解其意
义。即使这样,最好是使用CHANGE MASTER TO语句。
注释:master.info的内容会覆盖命令行或in my.cnf中指定的部分选项。详情参见6.8节,“复制启动选项”。
有了一个快照,你可以用它根据刚刚描述的从服务器部分来设置其它从服务器。你不需要主服务器的另一个快
照;每个从服务器可以使用相同的快照。
注释:为了保证事务InnoDB复制设置的最大可能的耐受性和一致性,应在主服务器的my.cnf文件中使
用innodb_flush_log_at_trx_commit=1和sync-binlog=1。
*
*
*
*
*
复制特性和已知问题
一般原则,SQL级复制兼容性要求主服务器和从服务器均支持使用的特性。例如,在MySQL 5.0.0中开始使
用TIMESTAMPADD()函数。如果在主服务器上使用该函数,不能复制到MySQL 5.0.0之前的从服务器。如果你
计划在5.1和以前版本的MySQL之间进行复制,你应查阅对应以前版本系列的MySQL参考手册,查询该系列复
制特征相关信息。
下面列出了关于支持什么和不支持什么的详细信息。关于复制的其它InnoDB具体信息参
见15.2.6.5节,“InnoDB和MySQL复制”。
关于保存的程序和触发器的复制问题在20.4节,“存储子程序和触发程序的二进制日志功能”中讨论。
· 用AUTO_INCREMENT、LAST_INSERT_ID()和TIMESTAMP值正确实现复制。
· USER()、UUID()和LOAD_FILE()函数毫无改变地被,这样不能可靠地在从服务器上工作。
· 下面的限制只适合基于语句的复制,而不是基于行的复制。处理用户级锁定的函
数GET_LOCK()、RELEASE_LOCK()、IS_FREE_LOCK()、IS_USED_LOCK()复制时从服务器不知道在主服务器
上同时进行的相关文本;因此如果从服务器上的内容不同,这些函数不用来插入到主服务器的表中(例如不执
行INSERT INTO mytable VALUES(GET_LOCK(...)))。
· 在MySQL 5.1中FOREIGN_KEY_CHECKS、SQL_MODE、UNIQUE_CHECKS和SQL_AUTO_IS_NULL变量
均复制。但TABLE_TYPE,即STORAGE_ENGINE变量不复制,有利于在不同的存储引擎之间进行复制。
· 即使主服务器和从服务器有不同的全局字符集变量,以及即使有不同的全局时区变量仍可以复制。

· 下面适合使用不同字符集的MySQL服务器之间的复制:
1. 必须在主服务器和从服务器上总是使用相同的全局字符集和校对规则(--default-character-set、--defaultcollation)
。否则,会在从服务器上遇到复制键值错误,因为在主服务器的字符集中被认为是唯一的键值在从服
务器的字符集中可能不是唯一的。
2. 如果主服务器早于MySQL 4.1.3,则会话中的字符集不应与其全局值不同(换句话说,不要使用SET
NAMES、SET CHARACTER SET等等),因为从服务器不知道该字符集的更改。如果主服务器和从服务器均
为4.1.3或更新版,可以随便将会话的字符集变量设置为本地值(例如NAMES、CHARACTER
SET、COLLATION_CLIENT和COLLATION_SERVER),因为这些设定值被写入二进制日志,因此从服务器知
道。然而,禁止更改会话中这些变量的全局值;如前面所述,主服务器和从服务器必须具有唯一的全局字符集
值。
3. 如果在主服务器上的数据库的字符集与全局collation_server值不同,则应设计CREATE TABLE语句,以便
它们不隐含依赖数据库的默认字符集(Bug #2326);一个好的解决办法是在CREATE TABLE中明显说明字符集
和校对规则。
· 应在主服务器和从服务器上设置相同的系统时区。否则一些语句,例如使
用NOW()或FROM_UNIXTIME()函数的语句,将不会正确复制。可以使用脚本mysqld_safe的--
timezone=timezone_name选项或通过设置TZ环境变量设置MySQL服务器运行的系统的时区。主服务器和从服
务器还应有相同的默认连接时区设置;即主服务器和从服务器应有相同的--default-time-zone参数值。
· CONVERT_TZ(...,...,@global.time_zone)不能正确复制。只有主服务器和从服务器均为5.0.4或更新版才
能正确复制CONVERT_TZ(...,...,@session.time_zone)。
· 会话变量只有在更新表的语句中使用时才能正确复制;例如:SET MAX_JOIN_SIZE=1000;INSERT
INTO mytable VALUES(@MAX_JOIN_SIZE)不能将相同的数据插入到主服务器上和从服务器上。不适用于通用
的SET TIME_ZONE=...;INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone))。
· 可以将从服务器上的非事务表复为主服务器上的事务表。例如,可以将主服务器上的InnoDB表复制为
从服务器上的MyISAM表。然而,复制过程中,如果从服务器在BEGIN/COMMIT块过程中停止则会产生问题,
因为从服务器在BEGIN块开始时会重启。该问题出现在TODO中,不久将会得到修复。
· 在MySQL 5.1中可以正确复制引用用户变量(即@var_name形式的变量)的更新语句;但在4.1以前的版
本中却不可能。请注意从MySQL 5.1开始对用户变量名的大小写不再敏感;当在5.1和旧版本之间设置复制时应
考虑该问题。
· 从服务器可以使用SSL连接到主服务器。
· 有一个全局系统变量slave_transaction_retries:如果因为某个InnoDB死锁或超过
InnoDB的innodb_lock_wait_timeout或NDB簇
的TransactionDeadlockDetectionTimeout或TransactionInactiveTimeout,REPLICATION SLAVESQL线程未能
执行某个事务,在给出错误停止前自动重试slave_transaction_retries次。默认值是10。从MySQL 5.0.4开始,
可以从SHOW STATUS的输出中看到重试总次数;参见5.3.4节,“服务器状态变量”。
· 如果在主服务器上的CREATE TABLE语句中使用了DATA DIRECTORY或INDEX DIRECTORY子句,子句
也可以在从服务器上使用。如果在从服务器主机文件系统中不存在一致的目录或虽然存在但不能被从服务器访
问,则会带来问题。MySQL 5.1支持一个称为NO_DIR_IN_CREATE的sql_mode选项。如果从服务器运行时
将SQL模式设置为包括该选项,复制CREATE TABLE语句时将忽略这些子句。结果是在表的数据库目录中创建
了MyISAM数据和索引文件。
· 下面的限制只适合基于语句的复制,而不是基于行的复制:如果在查询中数据修改不确定,主服务器和
从服务器上的数据可以不同;也就是由查询优化器确定。(这是常用的但不是很好的习惯,即使不是在复制中
也不好)。关于该问题的详细解释,参见A.8.1节,“MySQL中的打开事宜”。

· 带READ LOCK的FLUSH LOGS、FLUSH MASTER、FLUSH SLAVE和FLUSH TABLES不记入日志,因为如
果复制到从服务器会造成问题。关于语法示例,参见13.5.5.2节,“FLUSH语法”。FLUSH TABLES、ANALYZE
TABLE、OPTIMIZE TABLE和REPAIR TABLE语句被写入二进制日志并会复制到从服务器。一般情况不会造成问
题,因为这些语句不修改表的数据。但是在某些情况下会带来问题。如果你复制mysql数据库中的授权表并且
不使用GRANT直接更新那些表,必须在从服务器上执行FLUSH PRIVILEGES使新的权限生效。并且,如果使
用FLUSH TABLES重新命名MERGE表的MyISAM表,必须手动在从服务器上执行FLUSH TABLES。如果不指
定NO_WRITE_TO_BINLOG或其别名LOCAL,则这些语句被写入二进制日志。
· MySQL只支持一个主服务器和多个从服务器。我们计划将来添加一个投票算法,当前的主服务器出现问
题时自动切换。我们还计划引入代理过程通过向不同的从服务器发送SELECT查询以帮助进行负载均衡。
· 当服务器关闭、重启时,其MEMORY表将变为空。主服务器按下述方法复制该结果:启动后第1次主服
务器使用每个MEMORY表,它通知从服务器需要向表写入DELETE FROM语句来清空二进制日志的表。详细信
息参见15.4节,“MEMORY (HEAP)存储引擎”。
· 除了关闭从服务器(而不仅仅是从服务器线程) 临时表都被复制,并且还没有在从服务器上执行的更新
所使用的临时表也已经复制。如果关闭从服务器,从服务器重启后更新需要的那些临时表不可再用。为了避免
该问题,临时表打开时不要关闭从服务器。而应遵照下面的程序:
1. 执行STOP SLAVE语句。
2. 使用SHOW STATUS检查slave_open_temp_tables变量的值。
3. 如果值为0,使用mysqladmin shutdown命令关闭从服务器。
4. 如果值不为0,用START SLAVE重启从服务器线程。
5. 后面再重复该程序看下次的运气是否好一些。
我们计划在不久的将来修复该问题。
· 可以很安全地连接用--logs-slave-updates选项指定的循环主服务器/从服务器关系中的服务器。但请注
意许多语句在这种设置中不能正确工作,除非你的客户代码关注了潜在的在不同的服务器不同顺序的更新中可
能发生的这类问题。
这说明你可以象这样创建设置:
A -> B -> C -> A
服务器ID被编码在二进制日志事件中,因此服务器A知道何时自己首次创建它读取的事件并且不执行事件(除非
用--replicate-same-server-id选项启动了服务器A,只在很少情况下有意义)。这样,没有无限循环。只有对表
执行没有冲突的更新时该类循环设置才能工作。换句话说,如果在A和C中插入数据,绝对不应在A中插入键值
可能与插入到C中的行相冲突的一行。如果更新的顺序很重要,还不应更新两个服务器上相同的行。
· 如果从服务器上的某个语句产生错误,则从服务器上的SQL线程终止,并且从服务器向错误日志写入一
条消息。此时应手动连接从服务器,修复该问题(例如,一个不存在的表),然后运行START SLAVE。
· 可以很安全地关闭主服务器并在以后重启。如果某个从服务器丢失与主服务器的连接,从服务器尝试立
即重新连接。如果失败,从服务器定期重试。(默认设置是每60秒重试一次。可以通过--master-connectretry
选项更改)。从服务器也能够处理网络连接中断。但是,只有从服务器超过slave_net_timeout秒没有从主
服务器收到数据才通知网络中断。如果中断时间短,可以降低slave_net_timeout。参见5.3.3节,“服务器系统
变量”。
· 关闭从服务器(净关闭)也很安全,因为它可以跟踪它离开的地点。不纯净的关闭操作会产生问题,特
别是系统关闭前硬盘缓存未刷新到硬盘上时。如果有不间断电源,可以大大提高系统容错能力。不纯净的关闭
主服务器会造成主服务器上的表和二进制日志内容之间的不一致性;在主服务器上使用InnoDB表和--innodbChapter

safe-binlog选项可以避免该问题。参见5.11.3节,“二进制日志”。(注释:MySQL 5.1中不需要--innodb-safebinlog,
由于引入了XA事务支持已经作废了)。
· 由于MyISAM表的非事务属性,可以有一个语句只是更新一个表并返回错误代码。例如,多行插入时有
一个行超过键值约束,或者如果长的更新语句更新部分行后被杀掉了。如果发生在主服务器上,除非错误代码
合法并且语句执行产生相同的错误代码,从服务器线程将退出并等待数据库管理员决定如何做。如果该错误代
码验证行为不理想,可以用--slave-skip-errors选项掩盖(忽视)部分或全部错误。
· 如果从BEGIN/COMMIT系列的非事务表更新事务表,如果提交事务前更新非事务表,对二进制日志的更
新可能会不同步。这是因为事务提交后才被写入二进制日志。
· 事务混合更新事务表和非事务表时,二进制日志中语句的顺序是正确的,即使在ROLLBACK时,所有需
要的语句也会写入二进制日志。但是如果在第1个连接的事务完成前,第2个连接更新非事务表,语句记入日志
时会出现顺序错误,因为第2个连接的更新执行完后立即写入日志,而不管第1个连接执行的事务的状态如何
*
*
*
*
如果你的问题是与具体MySQL表达式或函数有关,可以使用mysql客户程序所带的BENCHMARK()函数执行定
时测试。其语法为BENCHMARK(loop_count,expression)。例如:
mysql> SELECT BENCHMARK(1000000,1+1);
+------------------------+
| BENCHMARK(1000000,1+1) |
+------------------------+
| 0 |
+------------------------+
1 row in set (0.32 sec)
上面结果在PentiumII 400MHz系统上获得。它显示MySQL在该系统上在0.32秒内可以执行1,000,000个简单
的+表达式运算。
所有MySQL函数应该被高度优化,但是总有可能有一些例外。BENCHMARK()是一个找出是否查询有问题的优
秀的工具
*
*
mysql> ANALYZE TABLE tt;
*
*

*
*
*
锁定方法
MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行页级锁定,对InnoDB表进行行级锁定。
在许多情况下,可以根据培训猜测应用程序使用哪类锁定类型最好,但一般很难说出某个给出的锁类型就比另
一个好。一切取决于应用程序,应用程序的不同部分可能需要不同的锁类型。
为了确定是否想要使用行级锁定的存储引擎,应看看应用程序做什么并且混合使用什么样的选择和更新语句。
例如,大多数Web应用程序执行许多选择,而很少进行删除,只对关键字的值进行更新,并且只插入少量具体
的表。基本MySQL MyISAM设置已经调节得很好。
在MySQL中对于使用表级锁定的存储引擎,表锁定时不会死锁的。这通过总是在一个查询开始时立即请求所有
必要的锁定并且总是以同样的顺序锁定表来管理。
对WRITE,MySQL使用的表锁定方法原理如下:
如果在表上没有锁,在它上面放一个写锁。
否则,把锁定请求放在写锁定队列中。
对READ,MySQL使用的锁定方法原理如下:
如果在表上没有写锁定,把一个读锁定放在它上面。
否则,把锁请求放在读锁定队列中。
当一个锁定被释放时,锁定可被写锁定队列中的线程得到,然后是读锁定队列中的线程。
这意味着,如果你在一个表上有许多更新,SELECT语句将等待直到没有更多的更新。
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
如果INSERT语句不冲突,可以自由为MyISAM表混合并行的INSERT和SELECT语句而不需要锁定。也就是说,
你可以在其它客户正读取MyISAM表的时候插入行。如果数据文件中间不包含空闲块,不会发生冲突,因为在
这种情况下,记录总是插入在数据文件的尾部。(从表的中部删除或更新的行可能导致空洞)。如果有空洞,
当所有空洞填入新的数据时,并行的插入能够重新自动启用。
如果不能同时插入,为了在一个表中进行多次INSERT和SELECT操作,可以在临时表中插入行并且立即用临时
表中的记录更新真正的表。
这可用下列代码做到:
mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;
InnoDB使用行锁定,BDB使用页锁定。对于这两种存储引擎,都可能存在死锁。这是因为,在SQL语句处理期
间,InnoDB自动获得行锁定和BDB获得页锁定,而不是在事务启动时获得。
行级锁定的优点:
· 当在许多线程中访问不同的行时只存在少量锁定冲突。
· 回滚时只有少量的更改。
· 可以长时间锁定单一的行。
行级锁定的缺点:
· 比页级或表级锁定占用更多的内存。
· 当在表的大部分中使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。
· 如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多。
· 用高级别锁定,通过支持不同的类型锁定,你也可以很容易地调节应用程序,因为其锁成本小于行级锁
定。
在以下情况下,表锁定优先于页级或行级锁定:
· 表的大部分语句用于读取。
· 对严格的关键字进行读取和更新,你可以更新或删除可以用单一的读取的关键字来提取的一行:
· UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
· DELETE FROM tbl_name WHERE unique_key_col=key_value;
· SELECT 结合并行的INSERT语句,并且只有很少的UPDATE或DELETE语句。

· 在整个表上有许多扫描或GROUP BY操作,没有任何写操作。
不同于行级或页级锁定的选项:
· 版本(例如,为并行的插入在MySQL中使用的技术),其中可以一个写操作,同时有许多读取操作。这说
明数据库或表支持数据依赖的不同视图,取决于访问何时开始。其它共同的术语是“时间跟踪”、“写复制”或
者“按需复制”。
· 按需复制在许多情况下优先于页级或行级锁定。然而,在最坏的情况下,它可能比使用常规锁定使用更
多的内存。
· 除了行级锁定外,你可以使用应用程序级锁定,例如在MySQL中使
用GET_LOCK()和RELEASE_LOCK()。这些是建议性锁定,它们只能在运行良好的应用程序中工作。
*
*
*
*
*
MyISAM键高速缓冲

为了使硬盘I/O最小化,MyISAM存储引擎使用一个被许多数据库管理系统使用的策略。它使用一个缓存机制将
经常访问的表锁在内存中:
Chapter 7. Optimization
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/optimization.html[2010/2/24 5:22:07]
· 对于索引块,维护一个称之为键高速缓冲(或键高速缓冲区)的特殊结构。该结构包含大量块缓存区,其
中放置了最常用的索引块。
· 对于数据块,MySQL不使用特殊缓存。而使用原生的操作系统文件系统的缓存。
本节首先描述了MyISAM键高速缓冲的基本操作。然后讨论了提高键高速缓冲性能并使你更好地控制缓存操作
的最新的更改:
· 多个线程可以并行访问缓存。
· 可以设置多个键高速缓冲,并将表索引指定给具体缓存。
可以使用key_buffer_size系统变量控制键高速缓冲的大小。如果该变量设置为零,不使用键高速缓冲。如
果key_buffer_size值太小不能分配最小数量的块缓存区(8),也不使用键高速缓冲。
如果键高速缓冲不工作,只使用操作系统提供的原生文件系统缓存区访问索引文件。(换句话说,使用与表数
据块相同的策略表来访问索引块)。
索引块是一个连续的访问MyISAM索引文件的单位。通常一个索引块的大小等于索引B-树节点的大小。(在硬盘
上使用B-树数据结构表示索引。树底部的节点为叶子节点。叶子节点上面的节点为非叶子节点)。
键高速缓冲结构中的所有块缓存区大小相同。该大小可以等于、大于或小于表索引块的大小。通常这两个值中
的一个是另一个的几倍。
当必须访问表索引块中的数据时,服务器首先检查是否它可以用于键高速缓冲中的某些块缓存区。如果适用,
服务器访问键高速缓冲中的数据而不是硬盘上的数据。也就是说,从缓存读取或写入缓存,而不是从硬盘读
写。否则,服务器选择一个包含一个不同的表索引块的缓存块缓存区,并用需要的表索引块的拷贝替换那里的
数据。一旦新的索引块位于缓存中,可以访问索引数据。
如果用于替换的块已经被修改了,块被视为“脏了”。在这种情况下,在替换前,其内容被刷新到它来自的表索
引。
通常服务器遵从LRU(最近最少使用)策略:当选择一个块用于替换时,它选择最近最少使用的索引块。为了使
该选择更容易, 键高速缓冲模块维护所有使用的块的专门队列(LRU链)。当访问块时,它被放到队列最后。当
块需要替换时,队列开头的块是最近最少使用的块,并成为第1个候选者。
7.4.6.1. 共享键高速缓冲访问
在以下条件下,线程可以同时访问键高速缓冲缓存区:
· 没有被更新的缓存区可以被多个线程访问。
· 正被更新的缓存区让需要使用它的线程等待直到更新完成。
· 多个线程可以发起请求替换缓存块,只要它们不彼此干扰(也就是说,只要它们需要不同的索引块,并
且使不同的缓存块被替换)。
对键高速缓冲的共享访问允许服务器大大提高吞吐量。
7.4.6.2. 多键高速缓冲
对键高速缓冲的共享访问可以提高性能但不能完全消除线程之间的竟争。它们仍然竞争对键高速缓冲缓存区的
访问进行管理的控制结构。为了进一步降低键高速缓冲访问竟争,MySQL 5.1还提供了多个键高速缓冲,允许
你为不同的键高速缓冲分配不同的表索引。

有多个键高速缓冲时,当为给定的MyISAM表处理查询时,服务器必须知道使用哪个缓存。默认情况,所
有MyISAM表索引被缓存到默认键高速缓冲中。要想为具体键高速缓冲分配表索引,应使用CACHE INDEX语
句(参见13.5.5.1节,“CACHE INDEX语法”)。
例如,下面的语句将表t1、t2和t3的索引分配给名为hot_cache的键高速缓冲:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status | OK |
| test.t2 | assign_to_keycache | status | OK |
| test.t3 | assign_to_keycache | status | OK |
+---------+--------------------+----------+----------+
可以用SET GLOBAL参数设置语句或使用服务器启动选项设置在CACHE INDEX语句中引用的键高速缓冲的大小
来创建键高速缓冲。例如:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
要想删除键高速缓冲,将其大小设置为零:
mysql> SET GLOBAL keycache1.key_buffer_size=0;
请注意不能删除默认键高速缓冲。删除默认键高速缓冲的尝试将被忽略:
mysql> set global key_buffer_size = 0;
mysql> show variables like 'key_buffer_size';
+-----------------+---------+
| Variable_name | Value |
+-----------------+---------+
| key_buffer_size | 8384512 |
+-----------------+---------+
键高速缓冲变量是结构式系统变量,有一个名和组件。对于keycache1.key_buffer_size,keycache1是缓存变
量名,key_buffer_size是缓存组件。关于引用结构式键高速缓冲系统变量所使用的语法的描述,参
见9.4.1节,“结构式系统变量”
默认情况下,表索引被分配给服务器启动时创建的主要(默认)键高速缓冲。当键高速缓冲被删除后,所有分配
给它的索引被重新分配给默认键高速缓冲。
对于一个忙的服务器,我们建议采用使用三个键高速缓冲的策略:
· 占用为所有键高速缓冲分配的空间的20%的“热”键高速缓冲。该缓存用于频繁用于搜索但没有更新的
表。
· 占用为所有键高速缓冲分配的空间的20%的“冷”键高速缓冲。该缓存用于中等大小、大量修改的表,例

如临时表。
· 占用键高速缓冲空间的20%的“温”键高速缓冲。使用它作为默认键高速缓冲,默认情况被所有其它表
使用。
使用3个键高速缓冲有好处的一个原因是对一个键高速缓冲结构的访问不会阻挡对其它的访问。访问分配给一
个缓存的表的查询不会与访问分配给其它缓存的表的查询竞争。由于其它原因也会提高性能:
· 热缓存只用于检索查询,因此其内容决不会被修改。结果是,无论何时需要从硬盘上拉入索引块,选择
用于替换的缓存块的内容不需要先刷新。
· 对于分配给热缓存的索引,如果没有查询需要索引扫描,很有可能对应索引B-树的非叶子节点的索引块
仍然在缓存中。
· 当更新的节点位于缓存中并且不需要先从硬盘读入时,为临时表频繁执行的更新操作会执行得更快。如
果临时表的索引的大小可以与冷键高速缓冲相比较,很可能更新的节点位于缓存中。
CACHE INDEX在一个表和键高速缓冲之间建立一种联系,但每次服务器重启时该联系被丢失。如果你想要每
次服务器重启时该联系生效,一个发办法是使用选项文件:包括配置键高速缓冲的变量设定值,和一个initfile
选项用来命名包含待执行的CACHE INDEX语句的一个文件。例如:
key_buffer_size = 4G
hot_cache.key_buffer_size = 2G
cold_cache.key_buffer_size = 2G
init_file=/path/to/data-directory/mysqld_init.sql
每次服务器启动时执行mysqld_init.sql中的语句。该文件每行应包含一个SQL语句。下面的例子分配几个表,
分别对应hot_cache和cold_cache:
CACHE INDEX a.t1, a.t2, b.t3 IN hot_cache
CACHE INDEX a.t4, b.t5, b.t6 IN cold_cache
7.4.6.3. 中点插入策略
默认情况,键高速缓冲管理系统采用LRU策略选择要收回的键高速缓冲块,但它也支持更复杂的方法,称之
为“中点插入策略”。
当使用中点插入策略时,LRU链被分为两个部分:一条热子链和一条温子链。两部分之间的划分点不固定,但
键高速缓冲管理系统关注温部分不“太短”,总是包含至少key_cache_division_limit比例的键高速缓冲
块。key_cache_division_limit是结构式键高速缓冲变量的一个组件,因此其值是一个可以根据每个缓存进行设
置的参数。
当一个索引块从表中读入键高速缓冲,它被放入温子链的末端。经过一定量的访问后(访问块),它被提升给热
子链。目前,需要用来提升一个块(3)的访问次数与所有索引块的相同。
提升到热子链的块被放到子链的末端。块然后在该子链中循环。如果块在子链的开头停留足够长的时间,它被
降到温链。该时间由键高速缓冲key_cache_age_threshold组件的值确定。
对于包含N个块的键高速缓冲,阈值表示,热子链开头的没有在最后N *key_cache_age_threshold/100次访问
中被访问的块将被移动到温子链开头。该块然后变为第1个挤出的候选者,因为替换的块总是来自温子链的开
头。
中点插入策略允许你将更有价值的块总是在缓存中。如果你想使用简单的LRU策略,
使key_cache_division_limit值保持其默认值100。

若执行的查询要求索引扫描有效推出所有索引块对应有数值的高级B-树节点的缓存,中点插入策略可以帮助提
高性能。要想避免,必须使用中点插入策略,而key_cache_division_limit设置为远小于100。然后在索引扫描
操作过程中,有数值的经常访问的节点被保留在热子链中。
7.4.6.4. 索引预加载
如果键高速缓冲内有足够的块以容纳整个索引的块,或者至少容纳对应其非叶节点的块,则在使用前,预装含
索引块的键高速缓冲很有意义。预装可以以更有效的方式将表索引块放入键高速缓冲缓存区中:通过顺序地从
硬盘读取索引块。
不进行预装,块仍然根据查询需要放入键高速缓冲中。尽管块将仍然在缓存中(因为有足够的缓存区保存它
们),它们以随机方式从硬盘上索取,而不是以顺序方式。
要想将索引预装到缓存中,使用LOAD INDEX INTO CACHE语句。例如,下面的语句可以预装表t1和t2索引的
节点(索引块):
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status | OK |
| test.t2 | preload_keys | status | OK |
+---------+--------------+----------+----------+
IGNORE LEAVES修改器只允许预装索引非叶节点所用的块。这样,上述的语句预装t1中的所有索引块,但只预
装t2中的非叶节点对应的块。
如果已经使用CACHE INDEX语句为一个索引分配了一个键高速缓冲,预装可以将索引块放入该缓存。否则,索
引被装入默认键高速缓冲。
7.4.6.5. 键高速缓冲块大小
可以使用key_cache_block_size变量为具体的键高速缓冲指定块缓存区的大小。这样允许为索引文件调
节I/O操作的性能。
当读缓存区的大小等于原生操作系统I/O缓存区的大小时,可以获得I/O操作的最佳性能。但是将关键字节点的
大小设置为等于I/O缓存区的大小并不总是能保证最佳整体性能。当读取大的叶节点时,服务器读入大量的不
需要的数据,结果防止读入其它叶子的节点。
目前,你不能控制表内索引块的大小。该大小由服务器在创建.MYI索引文件时设置,取决于表定义中索引的关
键字大小。在大多数情况下,它被设置为与I/O缓存区大小相等。
7.4.6.6. 重构键高速缓冲
键高速缓冲可以通过更新其参数值随时重新构建。例如:
mysql> SET GLOBAL cold_cache。key_buffer_size=4*1024*1024;
如果你为key_buffer_size或key_cache_block_size键高速缓冲组件分配的值与组件当前的值不同,服务器将毁
掉缓存的旧结构并根据新值创建一个新的。如果缓存包含任何脏的块,服务器在销毁前将它们保存到硬盘上并
重新创建缓存。如果你设置其它键高速缓冲参数,则不会发生重新构建。

当重新构建键高速缓冲时,服务器首先将任何脏缓存区的内容刷新到硬盘上。之后,缓存内容不再需要。然
而,重新构建并不阻塞需要使用分配给缓存的索引的查询。相反,服务器使用原生文件系统缓存直接访问表索
引。文件系统缓存不如使用键高速缓冲有效,因此尽管查询可以执行,但速度会减慢。缓存被重新构建后,它
又可以缓存分配给它的索引了,并且索引不再使用文件系统缓存。
*
*
*
MySQL如何计算打开的表
当运行mysqladmin status时,将看见象这样的一些东西:
Uptime: 426 Running threads: 1 Questions: 11082
Reloads: 1 Open tables: 12
如果你仅有6个表,Open tables值为12可能有点令人困惑。
MySQL是多线程的,因此许多客户可以同时在同一个表上进行查询。为了使多个客户线程在同一个表上有不
同状态的问题减到最小,表被每个并发进程独立地打开。这样需要额外的内存但一般会提高性能。对
于MyISAM表,数据文件需要为每个打开表的客户提供一个额外的文件描述符。(索引文件描述符在所有线程之
间共享)。
*
*
*
MySQL如何使用DNS
当新的客户连接mysqld时,mysqld创建一个新的线程来处理请求。该线程先检查是否主机名在主机名缓存
中。如果不在,线程试图解析主机名:

· 如果操作系统支持线程安全gethostbyaddr_r ()和gethostbyname_r()调用,线程使用它们来执行主机名
解析。
· 如果操作系统不支持线程安全调用,线程锁定一个互斥体并调用gethostbyaddr()和gethostbyname()。
在这种情况下,在第1个线程解锁互斥体前,没有其它线程可以解析不在主机名缓存中的主机名。
你可以用--skip-name-resolve选项启动mysqld来禁用DNS主机名查找。然而,在这种情况下,你只可以使
用MySQL中的授权表中的IP号。
如果你有一个很慢的DNS和许多主机,你可以通过用--skip-name-resolve禁用DNS查找或增
加HOST_CACHE_SIZE定义(默认值:128)并重新编译mysqld来提高性能。
你可以用--skip-host-cache选项启动服务器来禁用主机名缓存。要想清除主机名缓存,执行FLUSH HOSTS语句
或执行mysqladmin flush-hosts命令。
如果你想要完全禁止TCP/IP连接,用--skip-networking选项启动mysqld。
*
*
*
*
*
磁盘事宜
7.6.1. 使用符号链接
· 磁盘搜索是巨大的性能瓶颈。当数据量变得非常大以致于缓存性能变得不可能有效时,该问题变
得更加明显。对于大数据库,其中你或多或少地随机访问数据,你可以确信对读取操作需要至少一次硬
盘搜索,写操作需要多次硬盘搜索。要想使该问题最小化,应使用搜索次数较少的磁盘。
· 通过链接文件到不同的磁盘或对硬盘分段来增加可用磁盘锭数量(因此降低搜索成本):
o 使用符号链接
这说明,对于MyISAM表,你符号链接索引文件和/或数据文件,从它们数据目录内的通常位置到另一个
硬盘(也可以被条纹化)。这将使搜索和读次数达到最好,假定硬盘不再为其它目的使用。参
见7.6.1节,“使用符号链接”。
o 分条
分条意味着你有许多磁盘,将第1个块放到第1个硬盘,第2个块放到第2个磁盘,并且第N块在(N mod
number_of_disks)磁盘上等等。这意味着如果正常数据大小小于分条大小(或完全匹配),能够得到最
佳性能。分条完全取决于操作系统和分条大小,因此用不同的条纹大小对应用程序进行基准测试。参
见7.1.5节,“使用自己的基准”。
分条的不同速度完全依赖于参数。依赖于怎样设置条纹参数和硬盘数量,可以根据不同数量级别得到不
同的标准。你必须进行选择以便优化随机或顺序存取。
· 为了高可靠性你可能想使用RAID 0+1(条纹加镜像),但在这种情况下,需要2*N块磁盘来保
持N个磁盘的数据。如果你肯为它花钱,这可能是最好的选项。然而,你可能还必须投资一部分资金到卷
管理软件中以便有效地管理它。
· 一个较好的选择是根据数据类型的重要性程度改变RAID级别。例如,保存可以在RAID 0硬盘上重
新生成的不太重要的数据,但保存真正重要数据(例如主机信息和日志)到RAID 0+1或RAID N硬盘。
如果你有许多写操作,RAID N可能会存在问题,因为需要时间来更新校验位。
· 在Linux上,通过配置磁盘接口时使用hdparm,你可以获得更多的性能。(在一般负载下达
到100%并不困难。)下面的hdparm选项应该非常适用于MySQL,并且可能适用于许多其它应用程序:
hdparm -m 16 -d 1

请注意,当使用该命令时,性能和可靠性依赖于硬件,因此我们强烈建议,使用hdparm后,完全测试你
的系统。为获取更多详细信息,请查阅hdparm手册帮助页。如果hdparm使用的不好,会导致文件系统
破坏,因此试验之前请做好每个备份!
· 也可以设置数据库使用的文件系统参数:
如果不需要知道文件最后一次访问的时间(这对数据库服务器并没有实际的用途),可以用-o noatime选
项安装文件系统。这将跳过对文件系统中的节点的最后一次访问时间的更新,从而能够避免一些硬盘搜
索。
在许多操作系统中,用-o async选项安装,可以将文件系统设置为异步更新。如果电脑相当稳定,这应该
给予你更高的性能而不需要牺牲太多的可靠性。(该标志是Linux中默认开启。)
*
*
*
客户端脚本和实用工具概述
下面简单列出了MySQL客户端程序和实用工具:
· myisampack
压缩MyISAM表以产生更小的只读表的一个工具。参见8.2节,“myisampack:生成压缩、只读MyISAM表”。
· mysql
交互式输入SQL语句或从文件以批处理模式执行它们的命令行工具。参见8.3节,“mysql:MySQL命令行工具”。
· mysqlaccess
检查访问主机名、用户名和数据库组合的权限的脚本。
· mysqladmin
执行管理操作的客户程序,例如创建或删除数据库,重载授权表,将表刷新到硬盘上,以及重新打开日志文
件。mysqladmin还可以用来检索版本、进程,以及服务器的状态信息。参见8.5节,“mysqladmin:用于管
理MySQL服务器的客户端”。

· mysqlbinlog
从二进制日志读取语句的工具。在二进制日志文件中包含的执行过的语句的日志可用来帮助从崩溃中恢复。参
见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具”。
· mysqlcheck
检查、修复、分析以及优化表的表维护客户程序。参见8.7节,“mysqlcheck:表维护和维修程序”。
· mysqldump
将MySQL数据库转储到一个文件(例如SQL语句或tab分隔符文本文件)的客户程序。增强版免费软件首先
由Igor Romanenko提供。参见8.8节,“mysqldump:数据库备份程序”。
· mysqlhotcopy
当服务器在运行时,快速备份MyISAM或ISAM表的工具。参见8.9节,“mysqlhotcopy:数据库备份程序”。
· mysql import
使用LOAD DATA INFILE将文本文件导入相关表的客户程序。参见8.10节,“mysqlimport:数据导入程序”。
· mysqlshow
显示数据库、表、列以及索引相关信息的客户程序。参见8.11节,“mysqlshow:显示数据库、表和列信息”。
· perror
显示系统或MySQL错误代码含义的工具。参见8.13节,“perror:解释错误代码”。
· replace
更改文件中或标准输入中的字符串的实用工具。参见8.14节,“replace:字符串替换实用工具”。
MySQL AB还提供了大量GUI工具用于管理和MySQL服务器的其它工作。相关基本信息参见第4章:MySQL程序
概述。
每个MySQL程序有许多不同的选项。但每个MySQL程序均提供一个---help选项,可以用来全面描述程序不同的
选项。例如,可以试试mysql---help。
使用mysqlclient库同服务器进行通讯的MySQL客户使用下面的环境变量:
MYSQL_UNIX_PORT 默认Unix套接字文件;用于连接localhost
MYSQL_TCP_PORT 默认端口号;用于TCP/IP连接
MYSQL_PWD 默认密码
MYSQL_DEBUG 调试过程中的调试跟踪选项
TMPDIR 创建临时表和文件的目录
使用MYSQL_PWD不安全。参见5.8.6节,“使你的密码安全”。
可以在选项文件中或在命令行中指定选项来替换所有标准程序的默认选项值或指定的环境变量的值
*
*
*
*
*
*
mysql技巧
8.3.4.1. 垂直显示查询结果
一些查询结果如果垂直显示而不用通常的水平表格式显示,则更容易读取。用G而不用分号结束查询可以垂直
显示查询。例如,包括新行的更长的文本值垂直输出时通常更容易读取:
mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
reply: monty@no.spam.com
mail_to: "Thimble Smith" <tim@no.spam.com>
sbj: UTF-8
Chapter 8. Client and Utility Programs
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/client-side-scripts.html[2010/2/24 5:22:14]
txt: >>>>> "Thimble" == Thimble Smith writes:
Thimble> Hi. I think this is a good idea. Is anyone familiar
Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my
Thimble> TODO list and see what happens.
Yes, please do that.
Regards,
Monty
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)
8.3.4.2. 使用--safe-updates选项
对于新手,有一个有用的启动选项--safe-updates(或--i-am-a-dummy,具有相同的效果)。当你已经发出一
个DELETE FROM tbl_name语句但忘记了WHERE子句时很有用。通常情况,这样的语句从表中删除所有行。用-
-safe-updates,可以通过指定可以识别它们的键值只删除某些行。这样可以帮助防止事故。
若使用--safe-updates选项,mysql连接MySQL服务器时发出下面的语句:
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=1000, SQL_MAX_JOIN_SIZE=1000000;
参见13.5.3节,“SET语法”。
SET语句有下面的效果:
· 不允许你执行UPDATE或DELETE语句,除非在WHERE子句中指定一个键值约束或提供一个LIMIT子
句(或二者皆使用)。例如:
· UPDATE tbl_name SET not_key_column=val WHERE key_column=val;
·
· UPDATE tbl_name SET not_key_column=val LIMIT 1;
· 所有大的SELECT结果自动限制到1,000行,除非语句包括一个LIMIT子句。
· 放弃可能需要检查1,000,000多行组合的多表SELECT语句。
要将限制指定为1,000和1,000,000之外的值,可以使用--select_limit和--max_join_size选项覆盖默认值:
shell> mysql --safe-updates --select_limit=500 --max_join_size=10000
8.3.4.3. 禁用mysql自动连接
如果mysql客户程序发送查询时断开与服务器的连接,它立即并自动尝试重新连接服务器并再次发送查询。然
而,即使mysql重新连接成功,你的第1个连接也已经结束,并且以前的会话对象和设定值被丢失:包括临时
表、自动提交模式,以及用户和会话变量。该行为很危险,如下面的例子所示,服务器将在你不知道的情况下
关闭并重启:
mysql> SET @a=1;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO t VALUES(@a);
ERROR 2006: MySQL server has gone away
No connection. Trying to reconnect...

Connection id: 1
Current database: test
Query OK, 1 row affected (1.30 sec)
mysql> SELECT * FROM t;
+------+
| a |
+------+
| NULL |
+------+
1 row in set (0.05 sec)
@a用户变量已经随连接丢失,并且重新连接后它也没有定义。如果有必要在连接断开时终止mysql并提示错
误,你可以用--skip-reconnect选项启动mysql客户程序
*
*
mysql_zap:杀死符合某一模式的进程
mysql_zap杀死匹配某一模式的进程。象这样调用它:
shell> mysql_zap [-signal] [-?Ift] pattern
如果进程的ps命令的输出行包含该模式,则认为其匹配。默认情况,mysql_zap对每个进程请求确认。响
应y则杀死该进程,或者q退出mysql_zap。对于其它响应,mysql_zap不试图杀死进程。
如果给出-signal选项,它指定发送到每个进程的信号名或信号编号。否则,mysql_zap首先尝试TERM(信
号15)然后用KILL(信号9)。
mysql_zap理解下面的额外选项:
· ---help,-?,-I
显示一条帮助消息并退出。

· -f
强制模式。mysql_zap 视图杀死每个匹配的进程而不需要确认。
· -t
测试模式。显示每个进程的信息但不杀死它。
*
*
*
*
*
*
*
*
在MySQL中,下表中的字显式被保留。其中大多数字进制被标准SQL用作列名和/或表名(例如,GROUP)。少
数被保留了,因为MySQL需要它们,(目前)使用yacc解析程序。保留字被引起来后可以用作识别符。
ADD ALL ALTER
ANALYZE AND AS
ASC ASENSITIVE BEFORE
BETWEEN BIGINT BINARY
BLOB BOTH BY
CALL CASCADE CASE
CHANGE CHAR CHARACTER
CHECK COLLATE COLUMN
CONDITION CONNECTION CONSTRAINT
CONTINUE CONVERT CREATE
CROSS CURRENT_DATE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR
DATABASE DATABASES DAY_HOUR
DAY_MICROSECOND DAY_MINUTE DAY_SECOND
DEC DECIMAL DECLARE
DEFAULT DELAYED DELETE
DESC DESCRIBE DETERMINISTIC
DISTINCT DISTINCTROW DIV
DOUBLE DROP DUAL
EACH ELSE ELSEIF
ENCLOSED ESCAPED EXISTS
EXIT EXPLAIN FALSE
FETCH FLOAT FLOAT4
FLOAT8 FOR FORCE
FOREIGN FROM FULLTEXT
GOTO GRANT GROUP
HAVING HIGH_PRIORITY HOUR_MICROSECOND
HOUR_MINUTE HOUR_SECOND IF
IGNORE IN INDEX
INFILE INNER INOUT
Chapter 9. Language Structure
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/language-structure.html[2010/2/24 5:22:18]
INSENSITIVE INSERT INT
INT1 INT2 INT3
INT4 INT8 INTEGER
INTERVAL INTO IS
ITERATE JOIN KEY
KEYS KILL LABEL
LEADING LEAVE LEFT
LIKE LIMIT LINEAR
LINES LOAD LOCALTIME
LOCALTIMESTAMP LOCK LONG
LONGBLOB LONGTEXT LOOP
LOW_PRIORITY MATCH MEDIUMBLOB
MEDIUMINT MEDIUMTEXT MIDDLEINT
MINUTE_MICROSECOND MINUTE_SECOND MOD
MODIFIES NATURAL NOT
NO_WRITE_TO_BINLOG NULL NUMERIC
ON OPTIMIZE OPTION
OPTIONALLY OR ORDER
OUT OUTER OUTFILE
PRECISION PRIMARY PROCEDURE
PURGE RAID0 RANGE
READ READS REAL
REFERENCES REGEXP RELEASE
RENAME REPEAT REPLACE
REQUIRE RESTRICT RETURN
REVOKE RIGHT RLIKE
SCHEMA SCHEMAS SECOND_MICROSECOND
SELECT SENSITIVE SEPARATOR
SET SHOW SMALLINT
SPATIAL SPECIFIC SQL
SQLEXCEPTION SQLSTATE SQLWARNING
SQL_BIG_RESULT SQL_CALC_FOUND_ROWS SQL_SMALL_RESULT
SSL STARTING STRAIGHT_JOIN
TABLE TERMINATED THEN
TINYBLOB TINYINT TINYTEXT
TO TRAILING TRIGGER
TRUE UNDO UNION
UNIQUE UNLOCK UNSIGNED
UPDATE USAGE USE
USING UTC_DATE UTC_TIME
UTC_TIMESTAMP VALUES VARBINARY
VARCHAR VARCHARACTER VARYING
Chapter 9. Language Structure
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/language-structure.html[2010/2/24 5:22:18]
WHEN WHERE WHILE
WITH WRITE X509
XOR YEAR_MONTH ZEROFILL
MySQL允许部分关键字用做未引起来的识别符,因为许多人以前曾使用过它们。下面列出了一些例子:
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
*
*
*
*
*

*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*



*
*
*
* mysql内置函数
* 时间类型字段
mysql> select YEAR('2013-08-11');
+--------------------+
| YEAR('2013-08-11') |
+--------------------+
| 2013 |
+--------------------+
注意时间戳不行
*
*
* mysql> select month('2013-08-11');
+---------------------+
| month('2013-08-11') |
+---------------------+
| 8 |
+---------------------+
1 row in set (0.00 sec)
*
*
* mysql> select day('2013-08-11');
+-------------------+
| day('2013-08-11') |
+-------------------+
| 11 |
+-------------------+
*
* 从最右边取5个长度
* mysql> select right('2015-05-15',5);
+-----------------------+
| right('2015-05-15',5) |
+-----------------------+
| 05-15 |
+-----------------------+
*
*
*
* 从最左边取4个长度
* mysql> select left('2015-05-15',4);
+----------------------+
| left('2015-05-15',4) |
+----------------------+
| 2015 |
+----------------------+
*
*
*
*
*
*/

<?php

//mysql语句使用技巧

/*
 * 我的数据库是5.5.2
 * 
 * 查询当前用户的登陆的名字
 * select user();
 * 
 * 查询当前mysql服务器时间和服务器版本
 * select version(),current_time;
 * 
 * 
 * 修改一个字段的属性
 * 
 * 
 * 查看mysql数据库的user表,查看授权用户
 * use user;
 * select host,user,password from user;
 * 
 * 在shell 或者dos下登陆mysql
 * 2者都需要吧mysql命令加入服务,或者切换到对应的目录下
 * mysql -h 127.0.0.1 -u root -p root 
 * 
 * 查询所有数据库
 *  show databases;
 * 
 * 查询所有表
 * show tables;
 * 
 * 
 * 修改表名字,表字段属性
 * ALTER TABLE  `shopnc_address` CHANGE  `address`  `address1` VARCHAR( 2000 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT  '地址'
 *                                       原表名      新表名      字段属性和长度改变       字符集                                为NULL 
 * 
 * 
 * 
 * 授权
 * GRANT ALL PRIVILEGES    ON         *.*        TO 'zx'@'localhost' IDENTIFIED BY 'zx123456' WITH GRANT OPTION;
 *       所有权限                 数据库.表           用户名    host主机                   密码
 * 
 * 刷新权限
 * FLUSH PRIVILEGES;
 * 
 * 查看用户授权
 * show grants for user_name;可能是因为版本原因不能显示
 * 
 * 
 * --safe-user-create
如果启用,用户不能用GRANT语句创建新用户,除非用户有mysql.user表的INSERT权限。如果你想让用户具有授权权限来创建新用户,你应给用户授予下面
的权限:
 * GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name';
 * 
 * 
 * 
 * 收回权限
 * REVOKE ALL PRIVILEGES ON *.* FROM myuser;  
 * 或者直接去user表删除用户也可以
 * delete from user where user = 'myuser';
 * 
 * 查看表结果
 * DESCRIBE user;或者 show create table shopnc_orders;
 * 
 * 
 * 查看一张表的索引
 *  show index from shopnc_orders;
 * 
 * 查看系统的变量
 * show variables;
 * 
 * 查看每个表的信息
 * show table status;
 * 
 * 查看mysql的状态信息
 * show status;
 * 
 * 查看显示服务器所支持的不同权限
 * show privileges;
 * 
 * 查看创建数据库的信息
 * show create database shopnc;
 * 
 * 查看mysql支持那些数据库引擎
 * show engines;
 * 
 * 查看innodb的状态
 * show innodb status;//有些有版本问题,无法显示
 * 
 * 
 * 给表增加一个字段
 * ALTER TABLE  `shopnc_address` ADD  `ss` VARCHAR( 24 ) NOT NULL AFTER  `dlyp_id`
 * 
 * 
 * 
 * 
 * 从本文件导入数据库
 * 
 * windows和linux路径的斜杠是不一样的,请注意如果用Windows中的编辑器(使用
做为行的结束符)创建文件,应使用:
 * LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet
 * LINES TERMINATED BY '
';
 * 在运行OS X的Apple机上,应使用行结束符'
'。
 * 因为不同系统和文件格式的需要不一样,请更具详细文档在使用
 * 
 * 
 * 匹配模式,
 * 匹配p大头的数据
 *SELECT * FROM zx WHERE name LIKE 'p%'; 
 * 
 * 匹配p结尾的数据
 * SELECT * FROM zx WHERE name LIKE '%p'; 
 * 
 * 匹配含有p的数据
 * SELECT * FROM zx WHERE name LIKE '%p%'; 
 * 
 * 
 * 匹配长度为3的数据
 * SELECT * FROM zx WHERE name LIKE '___';
 * 
 * mysql还可以使用正则表达式函数
 * 用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它们是同义词)。
 * 
 * SELECT * FROM pet WHERE name REGEXP BINARY '^b'; 匹配以b大头的name
 * 
 * SELECT * FROM pet WHERE name REGEXP 'fy$';匹配以fy结尾的name
 * 
 * 
 * 选择最大的article数值,别名为article字段名,表别名也是一样
 * SELECT MAX(article) AS article FROM shop;
 * 
 * 
 * concat函数
 * 返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL
 * 
 * mysql> select concat('11','22','33');
+------------------------+
| concat('11','22','33') |
+------------------------+
| 112233                 |
+------------------------+
 * 
mysql> select concat('11','22',NULL);
+------------------------+
| concat('11','22',NULL) |
+------------------------+
| NULL                   |
+------------------------+
 * 
 * 
 * 
mysqld是MySQL服务器
mysqld_safe、mysql.server和mysqld_multi是服务器启动脚本
mysql_install_db初始化数据目录和初始数据库
 * 
mysql是一个命令行客户程序,用于交互式或以批处理模式执行SQL语句。
o mysqladmin是用于管理功能的客户程序。
o mysqlcheck执行表维护操作。
o mysqldump和mysqlhotcopy负责数据库备份。
o mysqlimport导入数据文件。
o mysqlshow显示信息数据库和表的相关信息。
 * 
myisamchk执行表维护操作。
o myisampack产生压缩、只读的表。
o mysqlbinlog是处理二进制日志文件的实用工具。
o perror显示错误代码的含义。
 * 
 * 一些命令的使用
shell> mysql test
shell> mysqladmin extended-status variables
shell> mysqlshow --help
shell> mysqldump --user=root personnel
 * 
 * 
 * 
 * 对于带选项值的长选项,通过一个‘=’将选项名和值隔离开来。对于带选项值的短选项,选项值可以紧随选项字母后面,或者二者之间可以用一个空格隔开。(-hlocalhost和-h localhost是等效的)。该规则的
例外情况是指定MySQL密码的选项。该选项的形式可以为--password=pass_val或--password。在后一种情况(未给出密码值),程序将提示输入密码。也可以给出密码选项,短形式为-ppass_val或-p。然而,对于
短形式,如果给出了密码值,必须紧跟在选项后面,中间不能插入空格。这样要求的原因是如果选项后面有空格,程序没有办法来告知后面的参量是密码值还是其它某种参量。因此,下面两个命令的含义完全不
同:
· shell> mysql -ptest
· shell> mysql -p test

第一个命令让mysql使用密码test,但没有指定默认数据库。第二个命令让mysql提示输入密码并使用test作为默认数据库。
 * 
 * 
 * 
 * 
 * 
部分选项控制可以开关的行为。例如,mysql客户端支持--column-names选项,确定是否在查询结果开头显示一行栏目名。默认情况,该选项被启用。但是可能在某些情况下你想要禁用它,例如将mysql的输出
发送到另一个只希望看到数据而不希望看到开始的标题行的程序中。
要想禁用列名,可以使用下面的形式来指定选项:
--disable-column-names
--skip-column-names
--column-names=0
--disable和--skip前缀与=0后缀的效果相同:它们均关闭选项。
可以用下述方法“启用”选项:
--column-names
--enable-column-names
--column-names=1
 * 
 * 
 * 
 * 
 * 
对mysql偶尔有用的另一个选项是-e或--execute选项,可用来将SQL语句传递给服务器。该语句必须用引号引起来(单引号或双引号)。(然而,如果想要在查询中将值引起来,则对于查询应使用双引号,查询中引
用的值应使用单引号)。当使用该选项时,语句被执行,然后mysql立即退出命令外壳。
例如,你可以用下面的命令获得用户账户列表:
shell> mysql -u root -p -e "SELECT User, Host FROM User" mysql
Enter password: ******
+------+-----------+
| User | Host |
+------+-----------+
| | gigan |
| root | gigan |
| | localhost |
| jon | localhost |
| root | localhost |
+------+-----------+
后面的mysql是数据库名字
 * 
 * 
 * 查看系统变量
 *  show variables like '%log%';
 * 查看所有系统变量
 * show variables
 * 
 查看是否支持分区
mysql> show variables like '%partition%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
 * 查看支持的插件
mysql> show plugins;
+-----------------------+----------+--------------------+---------+---------+
| Name                  | Status   | Type               | Library | License |
+-----------------------+----------+--------------------+---------+---------+
| binlog                | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| mysql_native_password | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| mysql_old_password    | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| CSV                   | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MEMORY                | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MyISAM                | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MRG_MYISAM            | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| ARCHIVE               | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| BLACKHOLE             | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| FEDERATED             | DISABLED | STORAGE ENGINE     | NULL    | GPL     |
| InnoDB                | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| INNODB_TRX            | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_LOCKS          | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_LOCK_WAITS     | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP            | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP_RESET      | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMPMEM         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMPMEM_RESET   | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| PERFORMANCE_SCHEMA    | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| partition             | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
+-----------------------+----------+--------------------+---------+---------+
 * 
 * 
 * 
 * 

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节,“升级授权表”。
服务器主机上还运行其它几个程序:
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
· 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节,“如何
通报缺陷和问题”)。



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







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版本,因此你应对你修改的版本进行备份以便将
来重装。






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
指定日志文件名。如果该文件存在,后面为日志输出。
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
· --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]组来说明你的选项文件可以稍有不同。这样给你更大的灵活
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
性。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





START INSTANCE mysqld4;启动一个MySQL实例 配置在my.cnf里面的[mysqld4]段里配置

显示所有载入的实例名:
mysql> show instances;


显示选定的实例的状态和版本信息:
SHOW INSTANCE STATUS mysqld3;




显示实例使用的选项:
mysql> SHOW INSTANCE OPTIONS mysqld3;、


该命令提供实例使用的所有日志文件
SHOW mysqld LOG FILES;


查看所有的日志文件所在位置 很方便
SHOW VARIABLES LIKE  '%log%'
以上所有的命令都可以在phpmyadmin上运行,这样看起来就更方便,控制台的显示方式不太友好

Variable_name    Value
back_log    50
binlog_cache_size    32768
binlog_direct_non_transactional_updates    OFF
binlog_format    MIXED
binlog_stmt_cache_size    32768
expire_logs_days    0
general_log    OFF
general_log_file    c:wampinmysqlmysql5.5.20dataUSER-20141003JG...
innodb_flush_log_at_trx_commit    1
innodb_locks_unsafe_for_binlog    OFF
innodb_log_buffer_size    8388608
innodb_log_file_size    5242880
innodb_log_files_in_group    2
innodb_log_group_home_dir    .
innodb_mirrored_log_groups    1
log    OFF
log_bin    ON
log_bin_trust_function_creators    OFF
log_error    c:wamplogsmysql.log
log_output    FILE
log_queries_not_using_indexes    OFF
log_slave_updates    OFF
log_slow_queries    OFF
log_warnings    1
max_binlog_cache_size    18446744073709547520
max_binlog_size    1073741824
max_binlog_stmt_cache_size    18446744073709547520
max_relay_log_size    0
relay_log    
relay_log_index    
relay_log_info_file    relay-log.info
relay_log_purge    ON
relay_log_recovery    OFF
relay_log_space_limit    0
slow_query_log    OFF
slow_query_log_file    c:wampinmysqlmysql5.5.20dataUSER-20141003JG...
sql_log_bin    ON
sql_log_off    OFF
sync_binlog    0
sync_relay_log    0
sync_relay_log_info    0


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 |
+-------------+------------------------------------+----------+
 * 
 * 
 * 
 * 
 *
 * 
 * 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的启动模式
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
 * 
 * 
 * 
 * 
 * 
 * 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;
 * 
 * 
 * 
 * 
 * 
 * 
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
FilesMySQLMySQL Server 5.1,命令应为:
C:> C:Program FilesMySQLMySQL Server 5.1inmysql -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警告;你可以忽略它们。
运行完脚本后,停止服务器并重启。
 * 
 * 
 * 
 * 
 * 
 * 
 * 尝试访问mysql端口是否可以联通
 * telnet server_IP或者server_HOST 3306
 * 
 * 
 * 
 * 如果你从源码构建MySQL但没有使用--enable-local-infile选项来进行configure,则客户不能使用LOAD DATA LOCAL,除非显式调用mysql_options
(...MYSQL_OPT_本地_INFILE,0)
你可以用--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选项。但是,为了便面不理解localinfile
的程序产生问题,则规定使用loose- prefix:
· [client]
· loose-local-infile=1
· 如果LOAD DATA LOCAL INFILE在服务器或客户端被禁用,试图执行该语句的客户端将收到下面的错误消息:
ERROR 1148: The used command is not allowed with this MySQL version
 * 
 * 
 * MySQL提供的权限
。
权限             列          上下文
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 服务器管理
 * 
 * 
 * 
 * 其余的权限用于管理性操作,它使用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权限系统做到:
你不能明显地指定某个给定的用户应该被拒绝访问。即,你不能明显地匹配用户然后拒绝连接。
你不能指定用户有权创建立或删除数据库中的表,但不能创建或删除数据库本身。
 * 
 * 
 * 
 * 
 * 
 * 
如果你连接时指定主机名,但得到错误消息主机名未显示或为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主机名缓存
 * 
 * 
 * 
 * 一些常用的解决方案包括:
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密码后,在清
空权限前,你不需要指定新密码,因为服务器还不知道你已经更改了密码!
 * 
 * 
 * 
 * 
在MySQL 4.1之前,用PASSWORD()函数计算的密码哈希值有16个字节长。应为:
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
 * 
 * 
在MySQL 4.1中,已经对PASSWORD()函数进行了修改,可以生成41字节的哈希值:
mysql> SELECT PASSWORD('mypass');
+-------------------------------------------+
| PASSWORD('mypass') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
 * 
 * 
 * 
 * 
限制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限制。
当服务器启动时所有记数从零开始。
 * 
 *
 * 
 * 
 * 
 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=tonu@example.com';
请注意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=tonu@example.com';
请注意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=tonu@example.com'
-> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
-> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
请注意SUBJECT和ISSUER值应做为单一字符串输入。
在MySQL 5.1中,在REQUIRE选项之间可以选用AND关键字。
选项的顺序不重要,但任何选项不能用两次。
 * 
 * 
 * 
 * 
备份数据库的另一个技术是使用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. 卸载快照。
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
这是在线非块备份,不会干扰对表的读写。我们以前假定我们的表为InnoDB表,因此--single-transaction使用一致性地读,并且保证mysqldump所看见的数
据不会更改。(其它客户端对InnoDB表进行的更改不会被mysqldump进程看见)。如果我们还有其它类型的表,我们必须假定在备份过程中它们不会更改。
例如,对于mysql数据库中的MyISAM表,我们必须假定在备份过程中没有对MySQL账户进行管理更改。

--single-transaction
InnoDB 表在备份时,通常启用选项 --single-transaction 来保证备份的一致性,实际上它的工作原理是设定本次会话的隔离级别为:REPEATABLE READ,以确保本次会话(dump)时,不会看到其他会话已经提交了的数据。
 * 
 * 
 * 
在星期一下午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二进制日志之前应进行确认
 * 
 * 
 * 
 * 
 * 
 * 
 * 
为恢复进行备份
现在假设在星期三上午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文件,我们可以用它来恢复大部分最新的数据更改,而不会丢失到崩溃时的数据
 * 
 * 
 * 
 * 指定恢复时间
如果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密码。
 指定恢复时间
对于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前一秒钟。你应检查日志
以确保时间确切。下一节介绍如何实现。
 * 
 * 
 * 
表维护和崩溃恢复
后面几节讨论如何使用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和服务器之
间会出现不期望的相互干涉。
 * 
 * 
 * 
 * 
可以使用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
Chapter 5. Database Administration
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/database-administration.html[2010/2/24 5:21:46]
该命令假定你有大于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来检查表
 * 
 * 
 * 
 * 
 * 
 * 
可以使用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来检查表
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
服务器时区支持
MySQL服务器有几个时区设置:
· 系统时区。服务器启动时便试图确定主机的时区,用它来设置system_time_zone系统变量。
· 服务器当前的时区。全局系统变量time_zone表示服务器当前使用的时区。初使值为'SYSTEM',说明服务器时区与系统时区相同。可以用--defaulttime-
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和系统上其它应用程序处理日
期时间的方法会有所不同。
 * 
 * 
 * 
 MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:
日志文件记入文件中的信息类型
错误日志记录启动、运行或停止mysqld时出现的问题。
查询日志记录建立的客户端连接和执行的语句。
更新日志记录更改数据的语句。不赞成使用该日志。
二进制日志记录所有更改数据的语句。还用于复制。
慢日志记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。
默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日
志)。当你执行一个FLUSH LOGS语句或执行mysqladmin flush-logs或mysqladmin refresh时,出现日志刷新。参见13.5.5.2节,“FLUSH语法”。
如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:
日志文件记入文件中的信息类型
错误日志记录启动、运行或停止mysqld时出现的问题。
查询日志记录建立的客户端连接和执行的语句。
更新日志记录更改数据的语句。不赞成使用该日志。
二进制日志记录所有更改数据的语句。还用于复制。
慢日志记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。
默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日
志)。当你执行一个FLUSH LOGS语句或执行mysqladmin flush-logs或mysqladmin refresh时,出现日志刷新。参见13.5.5.2节,“FLUSH语法”。
如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
做为服务启动多个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.8inmysqld-nt --install mysqld1
C:> C:mysql-5.1.2-alphainmysqld-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.8inmysqld-nt -- installmysqld1
--defaults-file=C:my-opts1.cnf
C:> C:mysql-5.1.2-alphainmysqld-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脚本是启动多个服务器的另一个方法
 * 
 * 
 * 
 * 
在多服务器环境中使用客户端程序
当你想要用一个客户端程序连接一个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.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表。
· 不使用任何表。
· 用户有某个表的列级权限。 
 * 
 * 
 * 
 * 
 * 
 * 
查询高速缓冲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 WARNINGSG
*************************** 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节,“查询高速缓冲配置”中给出。
 * 
 * 
 * 
 * 
从服务器设置为复制主服务器的数据后,它连接主服务器并等待更新过程。如果主服务器失败,或者从服务器
失去与主服务器之间的连接,从服务器保持定期尝试连接,直到它能够继续帧听更新。由--master-connectretry
选项控制重试间隔。默认为60秒
 * 
 * 

复制实施细节
MySQL使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,
从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线
程将二进制日志中的内容发送到从服务器。该线程可以识别为主服务器上SHOW PROCESSLIST的输出中
的Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器
数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,是从服务器创建用于读取中继日志并执行日
志中包含的更新。
在前面的描述中,每个从服务器有3个线程。有多个从服务器的主服务器创建为每个当前连接的从服务器创建
一个线程;每个从服务器有自己的I/O和SQL线程。
这样读取和执行语句被分成两个独立的任务。如果语句执行较慢则语句读取任务没有慢下来。例如,如果从服
I/O

务器有一段时间没有运行了,当从服务器启动时,其线程可以很快地从主服务器索取所有二进制日志内
容,即使SQL线程远远滞后。如果从服务器在SQL线程执行完所有索取的语句前停止,I/O 线程至少已经索取
了所有内容,以便语句的安全拷贝保存到本地从服务器的中继日志中,供从服务器下次启动时执行。这样允许
清空主服务器上的二进制日志,因为不再需要等候从服务器来索取其内容。
SHOW PROCESSLIST语句可以提供在主服务器上和从服务器上发生的关于复制的信息。
下面的例子说明了这3个线程在SHOW PROCESSLIST中的显示。
在主服务器上,SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLISTG
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL
这儿,线程2是一个连接从服务器的复制线程。该信息表示所有主要更新已经被发送到从服务器,主服务器正
等待更多的更新出现。
在从服务器上,SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLISTG
*************************** 1. row ***************************
Id: 10
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 11
User: system user
Host:
db: NULL
Command: Connect
Time: 11

State: Has read all relay log; waiting for the slave I/O
thread to update it
Info: NULL
该信息表示线程10是同主服务器通信的I/O线程,线程11是处理保存在中继日志中的更新的SQL线程。SHOW
PROCESSLIST运行时,两个线程均空闲,等待其它更新。
请注意Time列的值可以显示从服务器比主服务器滞后多长时间
 * 
 * 
 * 
 * 
 * 
 * 
 * 
复制主线程状态
下面列出了主服务器的Binlog Dump线程的State列的最常见的状态。如果你没有在主服务器上看见任何Binlog
Dump线程,这说明复制没有在运行—即,目前没有连接任何从服务器。
· Sending binlog event to slave
二进制日志由各种事件组成,一个事件通常为一个更新加一些其它信息。线程已经从二进制日志读取了一个事
件并且正将它发送到从服务器。
· Finished reading one binlog; switching to next binlog
线程已经读完二进制日志文件并且正打开下一个要发送到从服务器的日志文件。
· Has sent all binlog to slave; waiting for binlog to be updated
线程已经从二进制日志读取所有主要的更新并已经发送到了从服务器。线程现在正空闲,等待由主服务器上新
的更新导致的出现在二进制日志中的新事件。
· Waiting to finalize termination
线程停止时发生的一个很简单的状态。
6.3.2. 复制从I/O线程状态
下面列出了从服务器的I/O线程的State列的最常见的状态。该状态也出现在Slave_IO_State列,由SHOW
SLAVE STATUS显示。这说明你可以只通过该语句仔细浏览所发生的事情。
· Connecting to master
线程正试图连接主服务器。
· Checking master version
建立同主服务器之间的连接后立即临时出现的状态。
· Registering slave on master
建立同主服务器之间的连接后立即临时出现的状态。
· Requesting binlog dump
建立同主服务器之间的连接后立即临时出现的状态。线程向主服务器发送一条请求,索取从请求的二进制日志
文件名和位置开始的二进制日志的内容。
· Waiting to reconnect after a failed binlog dump request

如果二进制日志转储请求失败(由于没有连接),线程进入睡眠状态,然后定期尝试重新连接。可以使用--
master-connect-retry选项指定重试之间的间隔。
· Reconnecting after a failed binlog dump request
线程正尝试重新连接主服务器。
· Waiting for master to send event
线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待
持续slave_read_timeout秒,则发生超时。此时,线程认为连接被中断并企图重新连接。
· Queueing master event to the relay log
线程已经读取一个事件,正将它复制到中继日志供SQL线程来处理。
· Waiting to reconnect after a failed master event read
读取时(由于没有连接)出现错误。线程企图重新连接前将睡眠master-connect-retry秒。
· Reconnecting after a failed master event read
线程正尝试重新连接主服务器。当连接重新建立后,状态变为Waiting for master to send event。
· Waiting for the slave SQL thread to free enough relay log space
正使用一个非零relay_log_space_limit值,中继日志已经增长到其组合大小超过该值。I/O线程正等待直
到SQL线程处理中继日志内容并删除部分中继日志文件来释放足够的空间。
· Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
6.3.3. 复制从SQL线程状态
下面列出了从服务器的SQL线程的State列的最常见的状态。
· Reading event from the relay log
线程已经从中继日志读取一个事件,可以对事件进行处理了。
· Has read all relay log; waiting for the slave I/O thread to update it
线程已经处理了中继日志文件中的所有事件,现在正等待I/O线程将新事件写入中继日志。
· Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
I/O线程的State列也可以显示语句的文本。这说明线程已经从中继日志读取了一个事件,从中提取了语句,并
且正在执行语句。
6.3.4. 复制传递和状态文件
默认情况,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机

名,nnnnnn是序列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪索引文件中目
前正使用的中继日志。默认中继日志索引文件名为host_name-relay-bin.index。默认情况,在从服务器的数据
目录中创建这些文件。可以用--relay-log和--relay-log-index服务器选项覆盖默认文件名。参见6.8节,“复制启
动选项”。
中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并
且不再需要之后,立即自动删除它。没有直接的删除中继日志的机制,因为SQL线程可以负责完成。然
而,FLUSH LOGS可以循环中继日志,当SQL线程删除日志时会有影响。
在下面的条件下创建新的中继日志:
· 每次I/O线程启动时创建一个新的中继日志。
· 当日志被刷新时;例如,用FLUSH LOGS或mysqladmin flush-logs。
· 当当前的中继日志文件变得太大时。“太大”含义的确定方法:
o max_relay_log_size,如果max_relay_log_size > 0
o max_binlog_size,如果max_relay_log_size = 0
从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。它
们包含SHOW SLAVE STATUS语句的输出所显示的信息(关于该语句的描述参见13.6.2节,“用于控制从服务器
的SQL语句”)。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确
定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。
由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
行描述
1 文件中的行号
2 Master_Log_File
3 Read_Master_Log_Pos
4 Master_Host
5 Master_User
6 密码(不由SHOW SLAVE STATUS显示)
7 Master_Port
8 Connect_Retry
9 Master_SSL_Allowed
10 Master_SSL_CA_File
11 Master_SSL_CA_Path
12 Master_SSL_Cert
13 Master_SSL_Cipher
14 Master_SSL_Key
由SQL线程更新relay-log.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
行描述
1 Relay_Log_File
2 Relay_Log_Pos
3 Relay_Master_Log_File
4 Exec_Master_Log_Pos
Chapter 6. Replication in MySQL
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/replication.html[2010/2/24 5:22:02]
当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继
续进行复制。如果丢失了中继日志但仍然有relay-log.info文件,你可以通过检查该文件来确定SQL线程已经执
行的主服务器中二进制日志的程度。然后可以用Master_Log_File和Master_LOG_POS选项执行CHANGE
MASTER TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。
如果从服务器正复制LOAD DATA INFILE语句,你应也备份该目录内从服务器用于该目的的任何SQL_LOAD-
*文件。从服务器需要这些文件继续复制任何中断的LOAD DATA INFILE操作。用--slave-load-tmpdir选项来指
定目录的位置。如果未指定, 默认值为tmpdir变量的值。
 * 
 * 
 * 
 * 
 * 
 * 
 * 
假定你的域为mydomain.com,想要创建用户名为repl的一个账户,从服务器可以使用该账户从你的域内的任何
主机使用密码slavepass来访问主服务器。要创建该账户,可使用GRANT语句:
mysql> GRANT REPLICATION SLAVE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
如果你计划从从属服务器主机使用LOAD TABLE FROM MASTER或LOAD DATA FROM MASTER语句,你需要授
予该账户其它权限:
· 授予账户SUPER和RELOAD全局权限。
· 为所有想要装载的表授予SELECT权限。任何该账户不能SELECT的主服务器上的表被LOAD DATA
FROM MASTER忽略掉。
3. 执行FLUSH TABLES WITH READ LOCK语句清空所有表和块写入语句:
4. mysql> FLUSH TABLES WITH READ LOCK;
对于InnoDB表,请注意:FLUSH TABLES WITH READ LOCK还锁定COMMIT操作。当获得全局读锁定后,可以

开始InnoDB表的文件系统快照。快照不能保证内部(在InnoDB存储引擎内部)一致性(因为InnoDB缓存没有刷
新),但并不需要关心该问题,因为InnoDB可以在启动时解决该问题并给出一致的结果。这说明InnoDB在启动
快照时可以进行崩溃恢复,而不会破坏。然而,当保证一致的InnoDB表快照时,还没有途径来停止MySQL服
务器。
让客户程序保持运行,发出FLUSH TABLES语句让读锁定保持有效。(如果退出客户程序,锁被释放)。然后对
主服务器上的数据进行快照。
创建快照最简单的途径是使用归档程序对主服务器上的数据目录中的数据库进行二进制备份。例如,在Unix中
使用tar,或者在Windows中使用PowerArchiver、WinRAR、WinZip或者类似的软件。要使用tar来创建包
括所有数据库的归档文件,进入主服务器的数据目录,然后执行命令:
shell> tar -cvf /tmp/mysql-snapshot.tar .
如果你想让归档只包括this_db数据库,应使用命令:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
然后将归档文件复制到从服务器主机的/tmp目录。在该机器上,进入从服务器的数据目录,并使用下述命令解
压缩归档文件:
shell> tar -xvf /tmp/mysql-snapshot.tar
如果从服务器的用户账户与主服务器的不同,你可能不想复制mysql数据库。在这种情况下,应从归档中排除
该数据库。你也不需要在归档中包括任何日志文件或者master.info或relay-log.info文件。
当FLUSH TABLES WITH READ LOCK所置读锁定有效时,读取主服务器上当前的二进制日志名和偏移量值:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
File列显示日志名,而Position显示偏移量。在该例子中,二进制日志值为mysql-bin.003,偏移量为73。记录
该值。以后设置从服务器时需要使用这些值。它们表示复制坐标,从服务器应从该点开始从主服务器上进行新
的更新。
取得快照并记录日志名和偏移量后,可以在主服务器上重新启用写活动:
mysql> UNLOCK TABLES;
如果你正使用InnoDB表,理想情况应使用InnoDB Hot Backup工具,使用该工具可以获得一致的快照而不需
要在主服务器上进行锁定,并且可以对应从服务器上使用的快照来记录日志名和偏移量。Hot Backup是一个
附加的非免费(商业)工具,没有包含在标准 MySQL分发中。详细信息参
见http://www.innodb.com/manual.php的InnoDB Hot Backup主页。
不使用Hot Backup工具,最快捷的途径是使用InnoDB表的二进制快照来关闭主服务器并复制InnoDB数据文
件、日志文件和表定义文件(.frm文件)。要记录当前的日志文件名和偏移量,关闭服务器之前应发出下面的语
句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

然后记录前面所示的SHOW MASTER STATUS的输出中显示的日志名和偏移量。记录日志名和偏移量后,不解
锁表关闭服务器以确保服务器关闭时的快照与当前的日志文件和偏移量相对应:
shell> mysqladmin -u root shutdown
适合MyISAM和InnoDB表的另一个方法是对主服务器上的SQL进行转储而不是对前面讨论的二进制复制进行转
储。为了实现,可以在主服务器上使用mysqldump --master-data,以后将SQL转储文件装入从服务器。但
是,这样比二进制复制要慢一些。
如果主服务器运行时没有启用--logs-bin,SHOW MASTER STATUS或mysqldump --master-data显示的日
志名和位置值为空。在这种情况下,当以后指定从服务器的日志文件和位置时需要使用的值为空字符串('')和4.
5. 确保主服务器主机上my.cnf文件的[mysqld]部分包括一个log-bin选项。该部分还应有一个serverid=
Master_id选项,其中master_id必须为1到232–1之间的一个正整数值。例如:
6. [mysqld]
7. log-bin=mysql-bin
8. server-id=1
如果没有提供那些选项,应添加它们并重启服务器。
9. 停止用于从服务器的服务器并在其my.cnf文件中添加下面的行:
10. [mysqld]
11. server-id=slave_id
slave_id值同Master_id值一样,必须为1到232–1之间的一个正整数值。并且,从服务器的ID必须与主服务器
的ID不相同。例如:
[mysqld]
server-id=2
如果设置多个从服务器,每个从服务器必须有一个唯一的server-id值,必须与主服务器的以及其它从服务器的
不相同。可以认为server-id值类似于IP地址:这些ID值能唯一识别复制服务器群集中的每个服务器实例。
如果不指定一个server-id值,如果没有定义master-host,则将它设置为1;否则设置为2。请注意如果serverid
太长,主服务器拒绝所有来自从服务器的连接,并且从服务器拒绝连接到主服务器。这样,省略server-id只
适合用二进制日志备份。
12.如果对主服务器的数据进行二进制备份,启动从服务器之前将它复制到从服务器的数据目录中。确保对这
些文件和目录的权限正确。服务器 MySQL运行的用户必须能够读写文件,如同在主服务器上一样。
如果使用mysqldum备份,先启动从服务器(看下一步)。
13.启动从服务器。如果前面已经复制了,用--skip-slave-start选项启动从服务器,以便它不立即尝试连接主服
务器。你也可能想要用--logs-warnings选项启动从服务器(默认设置启用),以便在错误日志中显示更多的问题
相关的信息(例如,网络或连接问题)。放弃的连接将记入错误日志,除非其值大于1。
14.如果使用mysqldump备份主服务器的数据,将转储文件装载到从服务器:
15. shell> mysql -u root -p < dump_file.sql
16. 在从服务器上执行下面的语句,用你的系统的实际值替换选项值:
17. mysql> CHANGE MASTER TO
18. -> MASTER_HOST='master_host_name',

19. -> MASTER_USER='replication_user_name',
20. -> MASTER_PASSWORD='replication_password',
21. -> MASTER_LOG_FILE='recorded_log_file_name',
22. -> MASTER_LOG_POS=recorded_log_position;
下面的表显示了字符串选项的最大长度:
Master_Host 60
Master_USER 16
Master_PASSWORD 32
Master_Log_File 255
23.启动从服务器线程:
24. mysql> START SLAVE;
执行这些程序后,从服务器应连接主服务器,并补充自从快照以来发生的任何更新。
如果你忘记设置主服务器的server-id值,从服务器不能连接主服务器。
如果你忘记设置从服务器的server-id值,在从服务器的错误日志中会出现下面的错误:
Warning: You should set server-id to a non-0 value if master_host is set;
we will force server id to 2, but this MySQL server will not act as a slave.
如果由于其它原因不能复制,从服务器的错误日志中也会出现错误消息。
从服务器复制时,会在其数据目录中发现文件dmaster.info和relay-log.info。从服务器使用这两个文件跟踪已
经处理了多少主服务器的二进制日志。不要移除或编辑这些文件,除非你确切知你正在做什么并完全理解其意
义。即使这样,最好是使用CHANGE MASTER TO语句。
注释:master.info的内容会覆盖命令行或in my.cnf中指定的部分选项。详情参见6.8节,“复制启动选项”。
有了一个快照,你可以用它根据刚刚描述的从服务器部分来设置其它从服务器。你不需要主服务器的另一个快
照;每个从服务器可以使用相同的快照。
注释:为了保证事务InnoDB复制设置的最大可能的耐受性和一致性,应在主服务器的my.cnf文件中使
用innodb_flush_log_at_trx_commit=1和sync-binlog=1* 
 * 
 * 
 * 
 * 
复制特性和已知问题
一般原则,SQL级复制兼容性要求主服务器和从服务器均支持使用的特性。例如,在MySQL 5.0.0中开始使
用TIMESTAMPADD()函数。如果在主服务器上使用该函数,不能复制到MySQL 5.0.0之前的从服务器。如果你
计划在5.1和以前版本的MySQL之间进行复制,你应查阅对应以前版本系列的MySQL参考手册,查询该系列复
制特征相关信息。
下面列出了关于支持什么和不支持什么的详细信息。关于复制的其它InnoDB具体信息参
见15.2.6.5节,“InnoDB和MySQL复制”。
关于保存的程序和触发器的复制问题在20.4节,“存储子程序和触发程序的二进制日志功能”中讨论。
· 用AUTO_INCREMENT、LAST_INSERT_ID()和TIMESTAMP值正确实现复制。
· USER()、UUID()和LOAD_FILE()函数毫无改变地被,这样不能可靠地在从服务器上工作。
· 下面的限制只适合基于语句的复制,而不是基于行的复制。处理用户级锁定的函
数GET_LOCK()、RELEASE_LOCK()、IS_FREE_LOCK()、IS_USED_LOCK()复制时从服务器不知道在主服务器
上同时进行的相关文本;因此如果从服务器上的内容不同,这些函数不用来插入到主服务器的表中(例如不执
行INSERT INTO mytable VALUES(GET_LOCK(...)))。
· 在MySQL 5.1中FOREIGN_KEY_CHECKS、SQL_MODE、UNIQUE_CHECKS和SQL_AUTO_IS_NULL变量
均复制。但TABLE_TYPE,即STORAGE_ENGINE变量不复制,有利于在不同的存储引擎之间进行复制。
· 即使主服务器和从服务器有不同的全局字符集变量,以及即使有不同的全局时区变量仍可以复制。

· 下面适合使用不同字符集的MySQL服务器之间的复制:
1. 必须在主服务器和从服务器上总是使用相同的全局字符集和校对规则(--default-character-set、--defaultcollation)
。否则,会在从服务器上遇到复制键值错误,因为在主服务器的字符集中被认为是唯一的键值在从服
务器的字符集中可能不是唯一的。
2. 如果主服务器早于MySQL 4.1.3,则会话中的字符集不应与其全局值不同(换句话说,不要使用SET
NAMES、SET CHARACTER SET等等),因为从服务器不知道该字符集的更改。如果主服务器和从服务器均
为4.1.3或更新版,可以随便将会话的字符集变量设置为本地值(例如NAMES、CHARACTER
SET、COLLATION_CLIENT和COLLATION_SERVER),因为这些设定值被写入二进制日志,因此从服务器知
道。然而,禁止更改会话中这些变量的全局值;如前面所述,主服务器和从服务器必须具有唯一的全局字符集
值。
3. 如果在主服务器上的数据库的字符集与全局collation_server值不同,则应设计CREATE TABLE语句,以便
它们不隐含依赖数据库的默认字符集(Bug #2326);一个好的解决办法是在CREATE TABLE中明显说明字符集
和校对规则。
· 应在主服务器和从服务器上设置相同的系统时区。否则一些语句,例如使
用NOW()或FROM_UNIXTIME()函数的语句,将不会正确复制。可以使用脚本mysqld_safe的--
timezone=timezone_name选项或通过设置TZ环境变量设置MySQL服务器运行的系统的时区。主服务器和从服
务器还应有相同的默认连接时区设置;即主服务器和从服务器应有相同的--default-time-zone参数值。
· CONVERT_TZ(...,...,@global.time_zone)不能正确复制。只有主服务器和从服务器均为5.0.4或更新版才
能正确复制CONVERT_TZ(...,...,@session.time_zone)。
· 会话变量只有在更新表的语句中使用时才能正确复制;例如:SET MAX_JOIN_SIZE=1000;INSERT
INTO mytable VALUES(@MAX_JOIN_SIZE)不能将相同的数据插入到主服务器上和从服务器上。不适用于通用
的SET TIME_ZONE=...;INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone))。
· 可以将从服务器上的非事务表复为主服务器上的事务表。例如,可以将主服务器上的InnoDB表复制为
从服务器上的MyISAM表。然而,复制过程中,如果从服务器在BEGIN/COMMIT块过程中停止则会产生问题,
因为从服务器在BEGIN块开始时会重启。该问题出现在TODO中,不久将会得到修复。
· 在MySQL 5.1中可以正确复制引用用户变量(即@var_name形式的变量)的更新语句;但在4.1以前的版
本中却不可能。请注意从MySQL 5.1开始对用户变量名的大小写不再敏感;当在5.1和旧版本之间设置复制时应
考虑该问题。
· 从服务器可以使用SSL连接到主服务器。
· 有一个全局系统变量slave_transaction_retries:如果因为某个InnoDB死锁或超过
InnoDB的innodb_lock_wait_timeout或NDB簇
的TransactionDeadlockDetectionTimeout或TransactionInactiveTimeout,REPLICATION SLAVESQL线程未能
执行某个事务,在给出错误停止前自动重试slave_transaction_retries次。默认值是10。从MySQL 5.0.4开始,
可以从SHOW STATUS的输出中看到重试总次数;参见5.3.4节,“服务器状态变量”。
· 如果在主服务器上的CREATE TABLE语句中使用了DATA DIRECTORY或INDEX DIRECTORY子句,子句
也可以在从服务器上使用。如果在从服务器主机文件系统中不存在一致的目录或虽然存在但不能被从服务器访
问,则会带来问题。MySQL 5.1支持一个称为NO_DIR_IN_CREATE的sql_mode选项。如果从服务器运行时
将SQL模式设置为包括该选项,复制CREATE TABLE语句时将忽略这些子句。结果是在表的数据库目录中创建
了MyISAM数据和索引文件。
· 下面的限制只适合基于语句的复制,而不是基于行的复制:如果在查询中数据修改不确定,主服务器和
从服务器上的数据可以不同;也就是由查询优化器确定。(这是常用的但不是很好的习惯,即使不是在复制中
也不好)。关于该问题的详细解释,参见A.8.1节,“MySQL中的打开事宜”。

· 带READ LOCK的FLUSH LOGS、FLUSH MASTER、FLUSH SLAVE和FLUSH TABLES不记入日志,因为如
果复制到从服务器会造成问题。关于语法示例,参见13.5.5.2节,“FLUSH语法”。FLUSH TABLES、ANALYZE
TABLE、OPTIMIZE TABLE和REPAIR TABLE语句被写入二进制日志并会复制到从服务器。一般情况不会造成问
题,因为这些语句不修改表的数据。但是在某些情况下会带来问题。如果你复制mysql数据库中的授权表并且
不使用GRANT直接更新那些表,必须在从服务器上执行FLUSH PRIVILEGES使新的权限生效。并且,如果使
用FLUSH TABLES重新命名MERGE表的MyISAM表,必须手动在从服务器上执行FLUSH TABLES。如果不指
定NO_WRITE_TO_BINLOG或其别名LOCAL,则这些语句被写入二进制日志。
· MySQL只支持一个主服务器和多个从服务器。我们计划将来添加一个投票算法,当前的主服务器出现问
题时自动切换。我们还计划引入代理过程通过向不同的从服务器发送SELECT查询以帮助进行负载均衡。
· 当服务器关闭、重启时,其MEMORY表将变为空。主服务器按下述方法复制该结果:启动后第1次主服
务器使用每个MEMORY表,它通知从服务器需要向表写入DELETE FROM语句来清空二进制日志的表。详细信
息参见15.4节,“MEMORY (HEAP)存储引擎”。
· 除了关闭从服务器(而不仅仅是从服务器线程) 临时表都被复制,并且还没有在从服务器上执行的更新
所使用的临时表也已经复制。如果关闭从服务器,从服务器重启后更新需要的那些临时表不可再用。为了避免
该问题,临时表打开时不要关闭从服务器。而应遵照下面的程序:
1. 执行STOP SLAVE语句。
2. 使用SHOW STATUS检查slave_open_temp_tables变量的值。
3. 如果值为0,使用mysqladmin shutdown命令关闭从服务器。
4. 如果值不为0,用START SLAVE重启从服务器线程。
5. 后面再重复该程序看下次的运气是否好一些。
我们计划在不久的将来修复该问题。
· 可以很安全地连接用--logs-slave-updates选项指定的循环主服务器/从服务器关系中的服务器。但请注
意许多语句在这种设置中不能正确工作,除非你的客户代码关注了潜在的在不同的服务器不同顺序的更新中可
能发生的这类问题。
这说明你可以象这样创建设置:
A -> B -> C -> A
服务器ID被编码在二进制日志事件中,因此服务器A知道何时自己首次创建它读取的事件并且不执行事件(除非
用--replicate-same-server-id选项启动了服务器A,只在很少情况下有意义)。这样,没有无限循环。只有对表
执行没有冲突的更新时该类循环设置才能工作。换句话说,如果在A和C中插入数据,绝对不应在A中插入键值
可能与插入到C中的行相冲突的一行。如果更新的顺序很重要,还不应更新两个服务器上相同的行。
· 如果从服务器上的某个语句产生错误,则从服务器上的SQL线程终止,并且从服务器向错误日志写入一
条消息。此时应手动连接从服务器,修复该问题(例如,一个不存在的表),然后运行START SLAVE。
· 可以很安全地关闭主服务器并在以后重启。如果某个从服务器丢失与主服务器的连接,从服务器尝试立
即重新连接。如果失败,从服务器定期重试。(默认设置是每60秒重试一次。可以通过--master-connectretry
选项更改)。从服务器也能够处理网络连接中断。但是,只有从服务器超过slave_net_timeout秒没有从主
服务器收到数据才通知网络中断。如果中断时间短,可以降低slave_net_timeout。参见5.3.3节,“服务器系统
变量”。
· 关闭从服务器(净关闭)也很安全,因为它可以跟踪它离开的地点。不纯净的关闭操作会产生问题,特
别是系统关闭前硬盘缓存未刷新到硬盘上时。如果有不间断电源,可以大大提高系统容错能力。不纯净的关闭
主服务器会造成主服务器上的表和二进制日志内容之间的不一致性;在主服务器上使用InnoDB表和--innodbChapter

safe-binlog选项可以避免该问题。参见5.11.3节,“二进制日志”。(注释:MySQL 5.1中不需要--innodb-safebinlog,
由于引入了XA事务支持已经作废了)。
· 由于MyISAM表的非事务属性,可以有一个语句只是更新一个表并返回错误代码。例如,多行插入时有
一个行超过键值约束,或者如果长的更新语句更新部分行后被杀掉了。如果发生在主服务器上,除非错误代码
合法并且语句执行产生相同的错误代码,从服务器线程将退出并等待数据库管理员决定如何做。如果该错误代
码验证行为不理想,可以用--slave-skip-errors选项掩盖(忽视)部分或全部错误。
· 如果从BEGIN/COMMIT系列的非事务表更新事务表,如果提交事务前更新非事务表,对二进制日志的更
新可能会不同步。这是因为事务提交后才被写入二进制日志。
· 事务混合更新事务表和非事务表时,二进制日志中语句的顺序是正确的,即使在ROLLBACK时,所有需
要的语句也会写入二进制日志。但是如果在第1个连接的事务完成前,第2个连接更新非事务表,语句记入日志
时会出现顺序错误,因为第2个连接的更新执行完后立即写入日志,而不管第1个连接执行的事务的状态如何 
 * 
 * 
 * 
 * 
如果你的问题是与具体MySQL表达式或函数有关,可以使用mysql客户程序所带的BENCHMARK()函数执行定
时测试。其语法为BENCHMARK(loop_count,expression)。例如:
mysql> SELECT BENCHMARK(1000000,1+1);
+------------------------+
| BENCHMARK(1000000,1+1) |
+------------------------+
| 0 |
+------------------------+
1 row in set (0.32 sec)
上面结果在PentiumII 400MHz系统上获得。它显示MySQL在该系统上在0.32秒内可以执行1,000,000个简单
的+表达式运算。
所有MySQL函数应该被高度优化,但是总有可能有一些例外。BENCHMARK()是一个找出是否查询有问题的优
秀的工具
 * 
 * 
mysql> ANALYZE TABLE tt; 
 * 
 * 

 * 
 * 
 * 
锁定方法
MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行页级锁定,对InnoDB表进行行级锁定。
在许多情况下,可以根据培训猜测应用程序使用哪类锁定类型最好,但一般很难说出某个给出的锁类型就比另
一个好。一切取决于应用程序,应用程序的不同部分可能需要不同的锁类型。
为了确定是否想要使用行级锁定的存储引擎,应看看应用程序做什么并且混合使用什么样的选择和更新语句。
例如,大多数Web应用程序执行许多选择,而很少进行删除,只对关键字的值进行更新,并且只插入少量具体
的表。基本MySQL MyISAM设置已经调节得很好。
在MySQL中对于使用表级锁定的存储引擎,表锁定时不会死锁的。这通过总是在一个查询开始时立即请求所有
必要的锁定并且总是以同样的顺序锁定表来管理。
对WRITE,MySQL使用的表锁定方法原理如下:
如果在表上没有锁,在它上面放一个写锁。
否则,把锁定请求放在写锁定队列中。
对READ,MySQL使用的锁定方法原理如下:
如果在表上没有写锁定,把一个读锁定放在它上面。
否则,把锁请求放在读锁定队列中。
当一个锁定被释放时,锁定可被写锁定队列中的线程得到,然后是读锁定队列中的线程。
这意味着,如果你在一个表上有许多更新,SELECT语句将等待直到没有更多的更新。
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
如果INSERT语句不冲突,可以自由为MyISAM表混合并行的INSERT和SELECT语句而不需要锁定。也就是说,
你可以在其它客户正读取MyISAM表的时候插入行。如果数据文件中间不包含空闲块,不会发生冲突,因为在
这种情况下,记录总是插入在数据文件的尾部。(从表的中部删除或更新的行可能导致空洞)。如果有空洞,
当所有空洞填入新的数据时,并行的插入能够重新自动启用。
如果不能同时插入,为了在一个表中进行多次INSERT和SELECT操作,可以在临时表中插入行并且立即用临时
表中的记录更新真正的表。
这可用下列代码做到:
mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;
InnoDB使用行锁定,BDB使用页锁定。对于这两种存储引擎,都可能存在死锁。这是因为,在SQL语句处理期
间,InnoDB自动获得行锁定和BDB获得页锁定,而不是在事务启动时获得。
行级锁定的优点:
· 当在许多线程中访问不同的行时只存在少量锁定冲突。
· 回滚时只有少量的更改。
· 可以长时间锁定单一的行。
行级锁定的缺点:
· 比页级或表级锁定占用更多的内存。
· 当在表的大部分中使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。
· 如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多。
· 用高级别锁定,通过支持不同的类型锁定,你也可以很容易地调节应用程序,因为其锁成本小于行级锁
定。
在以下情况下,表锁定优先于页级或行级锁定:
· 表的大部分语句用于读取。
· 对严格的关键字进行读取和更新,你可以更新或删除可以用单一的读取的关键字来提取的一行:
· UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
· DELETE FROM tbl_name WHERE unique_key_col=key_value;
· SELECT 结合并行的INSERT语句,并且只有很少的UPDATE或DELETE语句。

· 在整个表上有许多扫描或GROUP BY操作,没有任何写操作。
不同于行级或页级锁定的选项:
· 版本(例如,为并行的插入在MySQL中使用的技术),其中可以一个写操作,同时有许多读取操作。这说
明数据库或表支持数据依赖的不同视图,取决于访问何时开始。其它共同的术语是“时间跟踪”、“写复制”或
者“按需复制”。
· 按需复制在许多情况下优先于页级或行级锁定。然而,在最坏的情况下,它可能比使用常规锁定使用更
多的内存。
· 除了行级锁定外,你可以使用应用程序级锁定,例如在MySQL中使
用GET_LOCK()和RELEASE_LOCK()。这些是建议性锁定,它们只能在运行良好的应用程序中工作。
 * 
 * 
 * 
 * 
 * 
MyISAM键高速缓冲

为了使硬盘I/O最小化,MyISAM存储引擎使用一个被许多数据库管理系统使用的策略。它使用一个缓存机制将
经常访问的表锁在内存中:
Chapter 7. Optimization
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/optimization.html[2010/2/24 5:22:07]
· 对于索引块,维护一个称之为键高速缓冲(或键高速缓冲区)的特殊结构。该结构包含大量块缓存区,其
中放置了最常用的索引块。
· 对于数据块,MySQL不使用特殊缓存。而使用原生的操作系统文件系统的缓存。
本节首先描述了MyISAM键高速缓冲的基本操作。然后讨论了提高键高速缓冲性能并使你更好地控制缓存操作
的最新的更改:
· 多个线程可以并行访问缓存。
· 可以设置多个键高速缓冲,并将表索引指定给具体缓存。
可以使用key_buffer_size系统变量控制键高速缓冲的大小。如果该变量设置为零,不使用键高速缓冲。如
果key_buffer_size值太小不能分配最小数量的块缓存区(8),也不使用键高速缓冲。
如果键高速缓冲不工作,只使用操作系统提供的原生文件系统缓存区访问索引文件。(换句话说,使用与表数
据块相同的策略表来访问索引块)。
索引块是一个连续的访问MyISAM索引文件的单位。通常一个索引块的大小等于索引B-树节点的大小。(在硬盘
上使用B-树数据结构表示索引。树底部的节点为叶子节点。叶子节点上面的节点为非叶子节点)。
键高速缓冲结构中的所有块缓存区大小相同。该大小可以等于、大于或小于表索引块的大小。通常这两个值中
的一个是另一个的几倍。
当必须访问表索引块中的数据时,服务器首先检查是否它可以用于键高速缓冲中的某些块缓存区。如果适用,
服务器访问键高速缓冲中的数据而不是硬盘上的数据。也就是说,从缓存读取或写入缓存,而不是从硬盘读
写。否则,服务器选择一个包含一个不同的表索引块的缓存块缓存区,并用需要的表索引块的拷贝替换那里的
数据。一旦新的索引块位于缓存中,可以访问索引数据。
如果用于替换的块已经被修改了,块被视为“脏了”。在这种情况下,在替换前,其内容被刷新到它来自的表索
引。
通常服务器遵从LRU(最近最少使用)策略:当选择一个块用于替换时,它选择最近最少使用的索引块。为了使
该选择更容易, 键高速缓冲模块维护所有使用的块的专门队列(LRU链)。当访问块时,它被放到队列最后。当
块需要替换时,队列开头的块是最近最少使用的块,并成为第1个候选者。
7.4.6.1. 共享键高速缓冲访问
在以下条件下,线程可以同时访问键高速缓冲缓存区:
· 没有被更新的缓存区可以被多个线程访问。
· 正被更新的缓存区让需要使用它的线程等待直到更新完成。
· 多个线程可以发起请求替换缓存块,只要它们不彼此干扰(也就是说,只要它们需要不同的索引块,并
且使不同的缓存块被替换)。
对键高速缓冲的共享访问允许服务器大大提高吞吐量。
7.4.6.2. 多键高速缓冲
对键高速缓冲的共享访问可以提高性能但不能完全消除线程之间的竟争。它们仍然竞争对键高速缓冲缓存区的
访问进行管理的控制结构。为了进一步降低键高速缓冲访问竟争,MySQL 5.1还提供了多个键高速缓冲,允许
你为不同的键高速缓冲分配不同的表索引。

有多个键高速缓冲时,当为给定的MyISAM表处理查询时,服务器必须知道使用哪个缓存。默认情况,所
有MyISAM表索引被缓存到默认键高速缓冲中。要想为具体键高速缓冲分配表索引,应使用CACHE INDEX语
句(参见13.5.5.1节,“CACHE INDEX语法”)。
例如,下面的语句将表t1、t2和t3的索引分配给名为hot_cache的键高速缓冲:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status | OK |
| test.t2 | assign_to_keycache | status | OK |
| test.t3 | assign_to_keycache | status | OK |
+---------+--------------------+----------+----------+
可以用SET GLOBAL参数设置语句或使用服务器启动选项设置在CACHE INDEX语句中引用的键高速缓冲的大小
来创建键高速缓冲。例如:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
要想删除键高速缓冲,将其大小设置为零:
mysql> SET GLOBAL keycache1.key_buffer_size=0;
请注意不能删除默认键高速缓冲。删除默认键高速缓冲的尝试将被忽略:
mysql> set global key_buffer_size = 0;
mysql> show variables like 'key_buffer_size';
+-----------------+---------+
| Variable_name | Value |
+-----------------+---------+
| key_buffer_size | 8384512 |
+-----------------+---------+
键高速缓冲变量是结构式系统变量,有一个名和组件。对于keycache1.key_buffer_size,keycache1是缓存变
量名,key_buffer_size是缓存组件。关于引用结构式键高速缓冲系统变量所使用的语法的描述,参
见9.4.1节,“结构式系统变量”
默认情况下,表索引被分配给服务器启动时创建的主要(默认)键高速缓冲。当键高速缓冲被删除后,所有分配
给它的索引被重新分配给默认键高速缓冲。
对于一个忙的服务器,我们建议采用使用三个键高速缓冲的策略:
· 占用为所有键高速缓冲分配的空间的20%的“热”键高速缓冲。该缓存用于频繁用于搜索但没有更新的
表。
· 占用为所有键高速缓冲分配的空间的20%的“冷”键高速缓冲。该缓存用于中等大小、大量修改的表,例

如临时表。
· 占用键高速缓冲空间的20%的“温”键高速缓冲。使用它作为默认键高速缓冲,默认情况被所有其它表
使用。
使用3个键高速缓冲有好处的一个原因是对一个键高速缓冲结构的访问不会阻挡对其它的访问。访问分配给一
个缓存的表的查询不会与访问分配给其它缓存的表的查询竞争。由于其它原因也会提高性能:
· 热缓存只用于检索查询,因此其内容决不会被修改。结果是,无论何时需要从硬盘上拉入索引块,选择
用于替换的缓存块的内容不需要先刷新。
· 对于分配给热缓存的索引,如果没有查询需要索引扫描,很有可能对应索引B-树的非叶子节点的索引块
仍然在缓存中。
· 当更新的节点位于缓存中并且不需要先从硬盘读入时,为临时表频繁执行的更新操作会执行得更快。如
果临时表的索引的大小可以与冷键高速缓冲相比较,很可能更新的节点位于缓存中。
CACHE INDEX在一个表和键高速缓冲之间建立一种联系,但每次服务器重启时该联系被丢失。如果你想要每
次服务器重启时该联系生效,一个发办法是使用选项文件:包括配置键高速缓冲的变量设定值,和一个initfile
选项用来命名包含待执行的CACHE INDEX语句的一个文件。例如:
key_buffer_size = 4G
hot_cache.key_buffer_size = 2G
cold_cache.key_buffer_size = 2G
init_file=/path/to/data-directory/mysqld_init.sql
每次服务器启动时执行mysqld_init.sql中的语句。该文件每行应包含一个SQL语句。下面的例子分配几个表,
分别对应hot_cache和cold_cache:
CACHE INDEX a.t1, a.t2, b.t3 IN hot_cache
CACHE INDEX a.t4, b.t5, b.t6 IN cold_cache
7.4.6.3. 中点插入策略
默认情况,键高速缓冲管理系统采用LRU策略选择要收回的键高速缓冲块,但它也支持更复杂的方法,称之
为“中点插入策略”。
当使用中点插入策略时,LRU链被分为两个部分:一条热子链和一条温子链。两部分之间的划分点不固定,但
键高速缓冲管理系统关注温部分不“太短”,总是包含至少key_cache_division_limit比例的键高速缓冲
块。key_cache_division_limit是结构式键高速缓冲变量的一个组件,因此其值是一个可以根据每个缓存进行设
置的参数。
当一个索引块从表中读入键高速缓冲,它被放入温子链的末端。经过一定量的访问后(访问块),它被提升给热
子链。目前,需要用来提升一个块(3)的访问次数与所有索引块的相同。
提升到热子链的块被放到子链的末端。块然后在该子链中循环。如果块在子链的开头停留足够长的时间,它被
降到温链。该时间由键高速缓冲key_cache_age_threshold组件的值确定。
对于包含N个块的键高速缓冲,阈值表示,热子链开头的没有在最后N *key_cache_age_threshold/100次访问
中被访问的块将被移动到温子链开头。该块然后变为第1个挤出的候选者,因为替换的块总是来自温子链的开
头。
中点插入策略允许你将更有价值的块总是在缓存中。如果你想使用简单的LRU策略,
使key_cache_division_limit值保持其默认值100。

若执行的查询要求索引扫描有效推出所有索引块对应有数值的高级B-树节点的缓存,中点插入策略可以帮助提
高性能。要想避免,必须使用中点插入策略,而key_cache_division_limit设置为远小于100。然后在索引扫描
操作过程中,有数值的经常访问的节点被保留在热子链中。
7.4.6.4. 索引预加载
如果键高速缓冲内有足够的块以容纳整个索引的块,或者至少容纳对应其非叶节点的块,则在使用前,预装含
索引块的键高速缓冲很有意义。预装可以以更有效的方式将表索引块放入键高速缓冲缓存区中:通过顺序地从
硬盘读取索引块。
不进行预装,块仍然根据查询需要放入键高速缓冲中。尽管块将仍然在缓存中(因为有足够的缓存区保存它
们),它们以随机方式从硬盘上索取,而不是以顺序方式。
要想将索引预装到缓存中,使用LOAD INDEX INTO CACHE语句。例如,下面的语句可以预装表t1和t2索引的
节点(索引块):
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status | OK |
| test.t2 | preload_keys | status | OK |
+---------+--------------+----------+----------+
IGNORE LEAVES修改器只允许预装索引非叶节点所用的块。这样,上述的语句预装t1中的所有索引块,但只预
装t2中的非叶节点对应的块。
如果已经使用CACHE INDEX语句为一个索引分配了一个键高速缓冲,预装可以将索引块放入该缓存。否则,索
引被装入默认键高速缓冲。
7.4.6.5. 键高速缓冲块大小
可以使用key_cache_block_size变量为具体的键高速缓冲指定块缓存区的大小。这样允许为索引文件调
节I/O操作的性能。
当读缓存区的大小等于原生操作系统I/O缓存区的大小时,可以获得I/O操作的最佳性能。但是将关键字节点的
大小设置为等于I/O缓存区的大小并不总是能保证最佳整体性能。当读取大的叶节点时,服务器读入大量的不
需要的数据,结果防止读入其它叶子的节点。
目前,你不能控制表内索引块的大小。该大小由服务器在创建.MYI索引文件时设置,取决于表定义中索引的关
键字大小。在大多数情况下,它被设置为与I/O缓存区大小相等。
7.4.6.6. 重构键高速缓冲
键高速缓冲可以通过更新其参数值随时重新构建。例如:
mysql> SET GLOBAL cold_cache。key_buffer_size=4*1024*1024;
如果你为key_buffer_size或key_cache_block_size键高速缓冲组件分配的值与组件当前的值不同,服务器将毁
掉缓存的旧结构并根据新值创建一个新的。如果缓存包含任何脏的块,服务器在销毁前将它们保存到硬盘上并
重新创建缓存。如果你设置其它键高速缓冲参数,则不会发生重新构建。

当重新构建键高速缓冲时,服务器首先将任何脏缓存区的内容刷新到硬盘上。之后,缓存内容不再需要。然
而,重新构建并不阻塞需要使用分配给缓存的索引的查询。相反,服务器使用原生文件系统缓存直接访问表索
引。文件系统缓存不如使用键高速缓冲有效,因此尽管查询可以执行,但速度会减慢。缓存被重新构建后,它
又可以缓存分配给它的索引了,并且索引不再使用文件系统缓存。 
 * 
 * 
 * 
MySQL如何计算打开的表
当运行mysqladmin status时,将看见象这样的一些东西:
Uptime: 426 Running threads: 1 Questions: 11082
Reloads: 1 Open tables: 12
如果你仅有6个表,Open tables值为12可能有点令人困惑。
MySQL是多线程的,因此许多客户可以同时在同一个表上进行查询。为了使多个客户线程在同一个表上有不
同状态的问题减到最小,表被每个并发进程独立地打开。这样需要额外的内存但一般会提高性能。对
于MyISAM表,数据文件需要为每个打开表的客户提供一个额外的文件描述符。(索引文件描述符在所有线程之
间共享)。
 * 
 * 
 * 
MySQL如何使用DNS
当新的客户连接mysqld时,mysqld创建一个新的线程来处理请求。该线程先检查是否主机名在主机名缓存
中。如果不在,线程试图解析主机名:

· 如果操作系统支持线程安全gethostbyaddr_r ()和gethostbyname_r()调用,线程使用它们来执行主机名
解析。
· 如果操作系统不支持线程安全调用,线程锁定一个互斥体并调用gethostbyaddr()和gethostbyname()。
在这种情况下,在第1个线程解锁互斥体前,没有其它线程可以解析不在主机名缓存中的主机名。
你可以用--skip-name-resolve选项启动mysqld来禁用DNS主机名查找。然而,在这种情况下,你只可以使
用MySQL中的授权表中的IP号。
如果你有一个很慢的DNS和许多主机,你可以通过用--skip-name-resolve禁用DNS查找或增
加HOST_CACHE_SIZE定义(默认值:128)并重新编译mysqld来提高性能。
你可以用--skip-host-cache选项启动服务器来禁用主机名缓存。要想清除主机名缓存,执行FLUSH HOSTS语句
或执行mysqladmin flush-hosts命令。
如果你想要完全禁止TCP/IP连接,用--skip-networking选项启动mysqld。
 * 
 * 
 * 
 * 
 * 
磁盘事宜
7.6.1. 使用符号链接
· 磁盘搜索是巨大的性能瓶颈。当数据量变得非常大以致于缓存性能变得不可能有效时,该问题变
得更加明显。对于大数据库,其中你或多或少地随机访问数据,你可以确信对读取操作需要至少一次硬
盘搜索,写操作需要多次硬盘搜索。要想使该问题最小化,应使用搜索次数较少的磁盘。
· 通过链接文件到不同的磁盘或对硬盘分段来增加可用磁盘锭数量(因此降低搜索成本):
o 使用符号链接
这说明,对于MyISAM表,你符号链接索引文件和/或数据文件,从它们数据目录内的通常位置到另一个
硬盘(也可以被条纹化)。这将使搜索和读次数达到最好,假定硬盘不再为其它目的使用。参
见7.6.1节,“使用符号链接”。
o 分条
分条意味着你有许多磁盘,将第1个块放到第1个硬盘,第2个块放到第2个磁盘,并且第N块在(N mod
number_of_disks)磁盘上等等。这意味着如果正常数据大小小于分条大小(或完全匹配),能够得到最
佳性能。分条完全取决于操作系统和分条大小,因此用不同的条纹大小对应用程序进行基准测试。参
见7.1.5节,“使用自己的基准”。
分条的不同速度完全依赖于参数。依赖于怎样设置条纹参数和硬盘数量,可以根据不同数量级别得到不
同的标准。你必须进行选择以便优化随机或顺序存取。
· 为了高可靠性你可能想使用RAID 0+1(条纹加镜像),但在这种情况下,需要2*N块磁盘来保
持N个磁盘的数据。如果你肯为它花钱,这可能是最好的选项。然而,你可能还必须投资一部分资金到卷
管理软件中以便有效地管理它。
· 一个较好的选择是根据数据类型的重要性程度改变RAID级别。例如,保存可以在RAID 0硬盘上重
新生成的不太重要的数据,但保存真正重要数据(例如主机信息和日志)到RAID 0+1或RAID N硬盘。
如果你有许多写操作,RAID N可能会存在问题,因为需要时间来更新校验位。
· 在Linux上,通过配置磁盘接口时使用hdparm,你可以获得更多的性能。(在一般负载下达
到100%并不困难。)下面的hdparm选项应该非常适用于MySQL,并且可能适用于许多其它应用程序:
hdparm -m 16 -d 1

请注意,当使用该命令时,性能和可靠性依赖于硬件,因此我们强烈建议,使用hdparm后,完全测试你
的系统。为获取更多详细信息,请查阅hdparm手册帮助页。如果hdparm使用的不好,会导致文件系统
破坏,因此试验之前请做好每个备份!
· 也可以设置数据库使用的文件系统参数:
如果不需要知道文件最后一次访问的时间(这对数据库服务器并没有实际的用途),可以用-o noatime选
项安装文件系统。这将跳过对文件系统中的节点的最后一次访问时间的更新,从而能够避免一些硬盘搜
索。
在许多操作系统中,用-o async选项安装,可以将文件系统设置为异步更新。如果电脑相当稳定,这应该
给予你更高的性能而不需要牺牲太多的可靠性。(该标志是Linux中默认开启。)
 * 
 * 
 * 
客户端脚本和实用工具概述
下面简单列出了MySQL客户端程序和实用工具:
· myisampack
压缩MyISAM表以产生更小的只读表的一个工具。参见8.2节,“myisampack:生成压缩、只读MyISAM表”。
· mysql
交互式输入SQL语句或从文件以批处理模式执行它们的命令行工具。参见8.3节,“mysql:MySQL命令行工具”。
· mysqlaccess
检查访问主机名、用户名和数据库组合的权限的脚本。
· mysqladmin
执行管理操作的客户程序,例如创建或删除数据库,重载授权表,将表刷新到硬盘上,以及重新打开日志文
件。mysqladmin还可以用来检索版本、进程,以及服务器的状态信息。参见8.5节,“mysqladmin:用于管
理MySQL服务器的客户端”。

· mysqlbinlog
从二进制日志读取语句的工具。在二进制日志文件中包含的执行过的语句的日志可用来帮助从崩溃中恢复。参
见8.6节,“mysqlbinlog:用于处理二进制日志文件的实用工具”。
· mysqlcheck
检查、修复、分析以及优化表的表维护客户程序。参见8.7节,“mysqlcheck:表维护和维修程序”。
· mysqldump
将MySQL数据库转储到一个文件(例如SQL语句或tab分隔符文本文件)的客户程序。增强版免费软件首先
由Igor Romanenko提供。参见8.8节,“mysqldump:数据库备份程序”。
· mysqlhotcopy
当服务器在运行时,快速备份MyISAM或ISAM表的工具。参见8.9节,“mysqlhotcopy:数据库备份程序”。
· mysql import
使用LOAD DATA INFILE将文本文件导入相关表的客户程序。参见8.10节,“mysqlimport:数据导入程序”。
· mysqlshow
显示数据库、表、列以及索引相关信息的客户程序。参见8.11节,“mysqlshow:显示数据库、表和列信息”。
· perror
显示系统或MySQL错误代码含义的工具。参见8.13节,“perror:解释错误代码”。
· replace
更改文件中或标准输入中的字符串的实用工具。参见8.14节,“replace:字符串替换实用工具”。
MySQL AB还提供了大量GUI工具用于管理和MySQL服务器的其它工作。相关基本信息参见第4章:MySQL程序
概述。
每个MySQL程序有许多不同的选项。但每个MySQL程序均提供一个---help选项,可以用来全面描述程序不同的
选项。例如,可以试试mysql---help。
使用mysqlclient库同服务器进行通讯的MySQL客户使用下面的环境变量:
MYSQL_UNIX_PORT 默认Unix套接字文件;用于连接localhost
MYSQL_TCP_PORT 默认端口号;用于TCP/IP连接
MYSQL_PWD 默认密码
MYSQL_DEBUG 调试过程中的调试跟踪选项
TMPDIR 创建临时表和文件的目录
使用MYSQL_PWD不安全。参见5.8.6节,“使你的密码安全”。
可以在选项文件中或在命令行中指定选项来替换所有标准程序的默认选项值或指定的环境变量的值
 * 
 * 
 * 
 * 
 * 
 * 
mysql技巧
8.3.4.1. 垂直显示查询结果
一些查询结果如果垂直显示而不用通常的水平表格式显示,则更容易读取。用G而不用分号结束查询可以垂直
显示查询。例如,包括新行的更长的文本值垂直输出时通常更容易读取:
mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
reply: monty@no.spam.com
mail_to: "Thimble Smith" <tim@no.spam.com>
sbj: UTF-8
Chapter 8. Client and Utility Programs
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/client-side-scripts.html[2010/2/24 5:22:14]
txt: >>>>> "Thimble" == Thimble Smith writes:
Thimble> Hi. I think this is a good idea. Is anyone familiar
Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my
Thimble> TODO list and see what happens.
Yes, please do that.
Regards,
Monty
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)
8.3.4.2. 使用--safe-updates选项
对于新手,有一个有用的启动选项--safe-updates(或--i-am-a-dummy,具有相同的效果)。当你已经发出一
个DELETE FROM tbl_name语句但忘记了WHERE子句时很有用。通常情况,这样的语句从表中删除所有行。用-
-safe-updates,可以通过指定可以识别它们的键值只删除某些行。这样可以帮助防止事故。
若使用--safe-updates选项,mysql连接MySQL服务器时发出下面的语句:
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=1000, SQL_MAX_JOIN_SIZE=1000000;
参见13.5.3节,“SET语法”。
SET语句有下面的效果:
· 不允许你执行UPDATE或DELETE语句,除非在WHERE子句中指定一个键值约束或提供一个LIMIT子
句(或二者皆使用)。例如:
· UPDATE tbl_name SET not_key_column=val WHERE key_column=val;
·
· UPDATE tbl_name SET not_key_column=val LIMIT 1;
· 所有大的SELECT结果自动限制到1,000行,除非语句包括一个LIMIT子句。
· 放弃可能需要检查1,000,000多行组合的多表SELECT语句。
要将限制指定为1,000和1,000,000之外的值,可以使用--select_limit和--max_join_size选项覆盖默认值:
shell> mysql --safe-updates --select_limit=500 --max_join_size=10000
8.3.4.3. 禁用mysql自动连接
如果mysql客户程序发送查询时断开与服务器的连接,它立即并自动尝试重新连接服务器并再次发送查询。然
而,即使mysql重新连接成功,你的第1个连接也已经结束,并且以前的会话对象和设定值被丢失:包括临时
表、自动提交模式,以及用户和会话变量。该行为很危险,如下面的例子所示,服务器将在你不知道的情况下
关闭并重启:
mysql> SET @a=1;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO t VALUES(@a);
ERROR 2006: MySQL server has gone away
No connection. Trying to reconnect...

Connection id: 1
Current database: test
Query OK, 1 row affected (1.30 sec)
mysql> SELECT * FROM t;
+------+
| a |
+------+
| NULL |
+------+
1 row in set (0.05 sec)
@a用户变量已经随连接丢失,并且重新连接后它也没有定义。如果有必要在连接断开时终止mysql并提示错
误,你可以用--skip-reconnect选项启动mysql客户程序
 * 
 * 
mysql_zap:杀死符合某一模式的进程
mysql_zap杀死匹配某一模式的进程。象这样调用它:
shell> mysql_zap [-signal] [-?Ift] pattern
如果进程的ps命令的输出行包含该模式,则认为其匹配。默认情况,mysql_zap对每个进程请求确认。响
应y则杀死该进程,或者q退出mysql_zap。对于其它响应,mysql_zap不试图杀死进程。
如果给出-signal选项,它指定发送到每个进程的信号名或信号编号。否则,mysql_zap首先尝试TERM(信
号15)然后用KILL(信号9)。
mysql_zap理解下面的额外选项:
· ---help,-?,-I
显示一条帮助消息并退出。

· -f
强制模式。mysql_zap 视图杀死每个匹配的进程而不需要确认。
· -t
测试模式。显示每个进程的信息但不杀死它。 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 在MySQL中,下表中的字显式被保留。其中大多数字进制被标准SQL用作列名和/或表名(例如,GROUP)。少
数被保留了,因为MySQL需要它们,(目前)使用yacc解析程序。保留字被引起来后可以用作识别符。
ADD ALL ALTER
ANALYZE AND AS
ASC ASENSITIVE BEFORE
BETWEEN BIGINT BINARY
BLOB BOTH BY
CALL CASCADE CASE
CHANGE CHAR CHARACTER
CHECK COLLATE COLUMN
CONDITION CONNECTION CONSTRAINT
CONTINUE CONVERT CREATE
CROSS CURRENT_DATE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR
DATABASE DATABASES DAY_HOUR
DAY_MICROSECOND DAY_MINUTE DAY_SECOND
DEC DECIMAL DECLARE
DEFAULT DELAYED DELETE
DESC DESCRIBE DETERMINISTIC
DISTINCT DISTINCTROW DIV
DOUBLE DROP DUAL
EACH ELSE ELSEIF
ENCLOSED ESCAPED EXISTS
EXIT EXPLAIN FALSE
FETCH FLOAT FLOAT4
FLOAT8 FOR FORCE
FOREIGN FROM FULLTEXT
GOTO GRANT GROUP
HAVING HIGH_PRIORITY HOUR_MICROSECOND
HOUR_MINUTE HOUR_SECOND IF
IGNORE IN INDEX
INFILE INNER INOUT
Chapter 9. Language Structure
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/language-structure.html[2010/2/24 5:22:18]
INSENSITIVE INSERT INT
INT1 INT2 INT3
INT4 INT8 INTEGER
INTERVAL INTO IS
ITERATE JOIN KEY
KEYS KILL LABEL
LEADING LEAVE LEFT
LIKE LIMIT LINEAR
LINES LOAD LOCALTIME
LOCALTIMESTAMP LOCK LONG
LONGBLOB LONGTEXT LOOP
LOW_PRIORITY MATCH MEDIUMBLOB
MEDIUMINT MEDIUMTEXT MIDDLEINT
MINUTE_MICROSECOND MINUTE_SECOND MOD
MODIFIES NATURAL NOT
NO_WRITE_TO_BINLOG NULL NUMERIC
ON OPTIMIZE OPTION
OPTIONALLY OR ORDER
OUT OUTER OUTFILE
PRECISION PRIMARY PROCEDURE
PURGE RAID0 RANGE
READ READS REAL
REFERENCES REGEXP RELEASE
RENAME REPEAT REPLACE
REQUIRE RESTRICT RETURN
REVOKE RIGHT RLIKE
SCHEMA SCHEMAS SECOND_MICROSECOND
SELECT SENSITIVE SEPARATOR
SET SHOW SMALLINT
SPATIAL SPECIFIC SQL
SQLEXCEPTION SQLSTATE SQLWARNING
SQL_BIG_RESULT SQL_CALC_FOUND_ROWS SQL_SMALL_RESULT
SSL STARTING STRAIGHT_JOIN
TABLE TERMINATED THEN
TINYBLOB TINYINT TINYTEXT
TO TRAILING TRIGGER
TRUE UNDO UNION
UNIQUE UNLOCK UNSIGNED
UPDATE USAGE USE
USING UTC_DATE UTC_TIME
UTC_TIMESTAMP VALUES VARBINARY
VARCHAR VARCHARACTER VARYING
Chapter 9. Language Structure
file:///D:/download/refman-5.1-zh.html-chapter/refman-5.1-zh.html-chapter/language-structure.html[2010/2/24 5:22:18]
WHEN WHERE WHILE
WITH WRITE X509
XOR YEAR_MONTH ZEROFILL
MySQL允许部分关键字用做未引起来的识别符,因为许多人以前曾使用过它们。下面列出了一些例子:
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
 * 
 * 
 * 
 * 
  
 * 
 * 
 * 
 * mysql内置函数
 * 时间类型字段
mysql> select YEAR('2013-08-11');
+--------------------+
| YEAR('2013-08-11') |
+--------------------+
|               2013 |
+--------------------+
注意时间戳不行
 * 
 * 
 * mysql> select month('2013-08-11');
+---------------------+
| month('2013-08-11') |
+---------------------+
|                   8 |
+---------------------+
1 row in set (0.00 sec)
 * 
 * 
 * mysql> select day('2013-08-11');
+-------------------+
| day('2013-08-11') |
+-------------------+
|                11 |
+-------------------+
 * 
 * 从最右边取5个长度
 * mysql> select right('2015-05-15',5);
+-----------------------+
| right('2015-05-15',5) |
+-----------------------+
| 05-15                 |
+-----------------------+
 * 
 * 
 * 
 * 从最左边取4个长度
 * mysql> select left('2015-05-15',4);
+----------------------+
| left('2015-05-15',4) |
+----------------------+
| 2015                 |
+----------------------+
 * 
 * 
 
原文地址:https://www.cnblogs.com/zx-admin/p/4550293.html