作/译者:叶金荣(Email:
),来源:http://imysql.cn,转载请注明作/译者和出处,并且不能用于商业用途,违者必究。
1、概述
通常,从一个发布版本升级到另一个版本时,我们建议按照顺序来升级版本。例如,想要升级 MySQL 3.23 时,先升级到 MySQL 4.0,而不是直接升级到 MySQL 4.1 或 MySQL 5.0。
以下是在升级 MySQL 时需要注意的事项:
- 仔细阅读一下升级的目标版本的新特性和改变的特性,以及2个版本之间的不同特性
- 升级前一定要备份所有的数据
- 如果是在Windows平台上升级MySQL,请阅读附录 "在Windows平台上升级MySQL"
- 有些不同版本间的升级可能会涉及对授权表的修改,请尤其注意这个问题,详情请阅读附录 "升级授权表"
- 如果正在运行着同步,请阅读附录 "升级同步"
- 如果之前运行着MySQL-Max发布版本,想要升级到非MySQL-Max发布版本时,就需要从 mysqld_safe 去掉启动 mysqld-max 服务器的参数
在同一个发布系列版本的MySQL间,可以随意拷贝格式文件和数据文件。如果在MySQL运行过程中改变了字符集,就需要对每个MyISAM表执行 "myisamchk -r -q --set-character-set=charset" 命令修复一下。否则的话,索引的排序可能不正确,因为修改了字符集,就可能会改变索引的顺序。
通常情况下,升级到新版本不需要修改任何数据表。请检查MySQL发布事项中提到的升级需要注意的地方,如果发现不能直接升级的话,就先用 mysqldump 将数据导出来,然后再导回去。
如果担心升级失败,就先把旧版本的MySQL改个名字备份起来,以备所需。
同时,升级完之后可能还需要重新编译跟MySQL相关的程序,因为新版本的头文件和库文件可能有改变了。
如果升级后发生问题了,请先检查是否使用了旧的my.cnf配置文件,可以通过执行命令 "mysqld --print-defaults" 来打印出各种配置信息来确认。
升级的时候最好也升级类似Perl的 DBD::mysql 模块,同样,对PHP和Python而言也是一样。
2、从 MySQL 5.0 升级到 MySQL 5.1
从 5.0 升级到 5.1 的时候,必须要升级授权表。否则,可能某些存储过程无法运行。详情请看附录 "mysql_update MySQL升级时检查数据表"。
以下是从 5.0 升级到 5.1 需要注意的事项:
- 检查所有的变化,尤其注意那些标志为 "不兼容的变化" 的部分。详情请看附录 "
mysql_updateMySQL升级时检查数据表" - 可能某些发布版本会改变授权表的机制
- 查看所有重大的变化,详情请看MySQL手册的 "D.1.1.?Changes in release 5.1.10 (Not yet released)" 章节
以下是升级到MySQL 5.1之后会发生的一些变化:
服务器部分:
-
不兼容的变化:MySQL 5.1 实现了支持无需重启服务器就能在运行时加载或卸载API插件。这个特性需要用到mysql.plugin表,可以运行 "mysql_upgrade" 命令来创建该表
插件安装在系统变量
plugin_dir所指的目录下。这个变量也控制着用户自定义函数(UDFs)所在目录,这相对以前的版本有所改变。在MySQL 5.1中,所有的UDFs库必须都安装到plugin_dir目录下,从旧版本升级的时候,必须把那些库文件都移动到这个目录下 - 不兼容的变化:系统变量
table_cache改名为table_open_cache - 不兼容的变化:在MySQL 5.1.6 中 FULLTEXT 的索引结构发生变化了。当升级到 5.1.6 甚至更高之后,需要对每个包含 FULLTEXT 字段的数据表执行 "REPAIR TABLE" 语句
- 在 MySQL 5.1.6 以前,MySQL把普通的查询日志和慢查询都写到文件中。从5.1.6以后,这些日志可以灵活地选择是是写到日志文件中(跟以前一样)或者写到
mysql数据库的general_log和slow_log表中。如果启用日志记录,这2种方式都可以使用。选项--log-output用来控制这2种日志的记录方式 - 从5.1.6开始,特殊字符集的数据库和表的标识符在创建相应目录和文件时都会用对应的字符集编码了
SQL分:
- 不兼容的变化:在MySQL 5.1.8开始,
TYPE =还仍然是engine_nameENGINE =的同义语法,但有警告。从5.2开始,将完全删除这种语法,并报告错误。engine_name - 不兼容的变化:在MySQL 5.0.10中,触发器的命名空间已经改变了。在以前,触发器的名字必须和每个数据表都不一样。现在,只需要在数据库内唯一就行了。隐含的变化就是,
DROP TRIGGER语法使用模式名而非数据表名(模式名是可选参数,如果忽略了,就使用当前的模式)当从5.0升级到5.0.10及更高时,则必须删除触发器后重新创建它们,否则升级后就无法删除触发器了。建议如下:
- 导出触发器:
SELECT CONCAT('CREATE TRIGGER ', t.TRIGGER_SCHEMA, '.', t.TRIGGER_NAME, ' ', t.ACTION_TIMING, ' ', t.EVENT_MANIPULATION, ' ON ', t.EVENT_OBJECT_SCHEMA, '.', t.EVENT_OBJECT_TABLE, ' FOR EACH ROW ', t.ACTION_STATEMENT, '//' ) INTO OUTFILE '/tmp/triggers.sql' FROM INFORMATION_SCHEMA.TRIGGERS AS t;将触发器导出到文件 "/tmp/triggers.sql" 中去。
- 停止服务器,然后删除数据库目录下的所有 "TRG" 文件:
shell>rm -f */*.TRG
- 启动服务器,倒入触发器:
mysql> delimiter // ; mysql> source /tmp/triggers.sql //
- 导出触发器:
- 不兼容的变化:MySQL 5.1.6引进了触发器权限机制。以前,创建触发器需要有
SUPER权限,现在,这个操作只需要有TRIGGER权限。这改善了权限安全状况 - 一些MySQL 5.1中作为保留关键字在MySQL 5.0中并没有作为保留关键字
- 新引入了 "
INSTALL PLUGIN" 和 "UNINSTALL PLUGIN" 语句用于操作API插件。同样,创建FULLTEXT索引时,可以用 "WITH PARSER" 子句关联解析器插件
3、从 MySQL 4.1 升级到 MySQL 5.0
服务器部分:
- 不兼容的变化:
InnoDB和MyISAM表中空格结尾的TEXT字段索引顺序改变了。因此需要运行 "CHECK TABLE" 语句修复数据表,如果出现错误,就运行 "OPTIMIZE TABLE" 或 "REPAIR TABLE" 语句修复,甚至重新转储(用mysqldump) - 不兼容的变化:从MySQL 5.0.15开始,如何处理
BINARY字段中填充的值已经改变了。填充的值现在是0x00而非空格了,并且在取值的时候不会去除末尾的空格 - 不兼容的变化:从MySQL 5.0.3开始,
DECIMAL的实现方式已经改变了,5.0对DECIMAL的格式限制严格多了 - 不兼容的变化:在MySQL 5.0.3到5.0.5之间版本的
MyISAM和InnoDB表中创建的DECIMAL字段升级到5.0.6之后会发生崩溃 - 不兼容的变化:从5.0.3开始,除非和主函数之间有辅助的符号链接,否则服务器将不再默认地加载用户自定义函数(UDFs),也可以通过
--allow-suspicious-udfs选项来启用 - 不兼容的变化:5.0中禁用了更新日志(update log) ,不过可以用二进制日志(binary log)来代替它
- 不兼容的变化:5.0中不再支持
ISAM类型存储引擎(作者:可以通过重新编译源代码支持,不过非常不建议这么做) - 不兼容的变化:5.0中不再支持
MyISAM的RAID选项,可以用 mysqldump 导出旧表然后重新导回去实现升级 - 在5.0.6中,记录存储过程和触发器的二进制日志发生了一些变化,详见手册的 "17.4 Binary Logging of Stored Routines and Triggers"
SQL部分:
- 不兼容的变化:从5.0.12开始,自然连接和使用
USING的连接,包括外部连接的衍生形式,都按照SQL:2003标准来处理了;这个变化导致减少了自然连接和使用USING的连接产生的结果字段数,并且还将按照更合理的顺序显示这些字段,逗号比较符的优先顺序和JOIN,LEFT JOIN中的一样了 - 不兼容的变化:在以前,等待超时的锁会导致
InnoDB回滚当前全部事务,从5.0.13开始,就只回滚最近的SQL语句了 - 不兼容的变化:触发器的变化,跟前面讲到的一样
- 不兼容的变化:从5.0.15开始,
CHAR()函数返回二进制字符串,而不是按照连接字符集格式的字符串。子句USING可以自定义返回结果的字符集charset_name - 不兼容的变化:在5.0.13以前,
NOW()和SYSDATE()返回的结果一样。但从5.0.13开始,SYSDATE()返回的是语句执行点的时间,这就可能和NOW()返回的结果不一样了,不过可以用--sysdate-is-now选项让SYSDATE()作为NOW()的同名函数 - 不兼容的变化:在5.0.13以前,
GREATEST(和x,NULL)LEAST(如果x,NULL)x不是NULL值,则返回x。从5.0.13开始,只要任何参数是NULL,就返回NULL,跟Oracle一样 - 不兼容的变化:在4.1.13/5.0.8以前,
DATETIME的加0后就转换成YYYYMMDDHHMMSS格式,现在变成YYYYMMDDHHMMSS.000000格式了 - 不兼容的变化:在4.1.12/5.0.6中,语句
LOAD DATA INFILE和SELECT ... INTO OUTFILE 中,当FIELDS TERMINATED BY和FIELDS ENCLOSED BY的值都是空的时候,结果就被改变了。以前,字段都按照它显示的宽度来读写的。现在变成按照足够保存字段值的宽度来读写它。然而,对MySQL 4.0.12/5.0.6来说,那些在它们之前导出来的文件可能无法正确用LOAD DATA INFILE语句导入 - 一些MySQL 5.0中作为保留关键字在MySQL 4.1中并没有作为保留关键字
- 从5.0.3开始,
DECIMAL用更有效的格式来存储 - 5.0.3开始,在计算
DECIMAL值和舍入精确值的时候采用精确数学 - 4.1中,
FLOAT或DOUBLE之间的比较碰巧没问题,但在5.0中可能就不行了 - 从5.0.3开始,
VARCHAR和VARBINARY字段中末尾的空格不再删除 - 从5.0.3开始,
BIT是一个独立的数据类型了,不再是TINYINT(1)的同名词了 - MySQL 5.0.2增加了一些SQL模式以使对排除包含非法或者缺失值得记录有着更严格的控制
- 从5.0.2开始,关键字
SCHEMA和SCHEMAS被认为分别是DATABASE和DATABASES的同名词 - 5.0中用户变量对大小写不敏感,而4.1中则不然
- 增加了一个新的启动选项
innodb_table_locks,它导致LOCK TABLE时也可以请求InnoDB表锁。这个选项默认打开,不过可能在AUTOCOMMIT=1和LOCK TABLES应用中会导致死锁
C API部分:
- 不兼容的变化:由于5.0中
DECIMAL数据类型的实现方式发生了变化,因此如果使用就版本的库文件需要注意这个问题 - 不兼容的变化:
在5.0.3中,ER_WARN_DATA_TRUNCATED警告符号改名为WARN_DATA_TRUNCATED了 MYSQL结构体中的reconnect标志被mysql_real_connect()设为 0。
4、从 MySQL 4.0 升级到 MySQL 4.1
服务器部分:
-
不兼容的变化:以下好几个都是需要重建数据表的,可以使用 mysqldump 导出表后重新导回去
- 如果在4.1.0到4.1.3版本的MySQL中创建了包含
TIMESTAMP字段的InnoDB表。则在升级到4.1.4及更高时需要重建表,因为存储格式发生变化了 - 从4.1.3开始,
InnoDB表采用同一种字符集比较函数来比较那些 非latin1_swedish_ci字符集且不是BINARY的字符串 - 如果在4.1.0到4.1.5版本的MySQl中对 UTF8 字段或者其他多字节字段作了前缀索引,则在升级到4.1.6及更高时必须重建表
- 如果在4.1之前,数据库、表、字段、约束名中使用了重音字符(字节值是128到255的字符),那么不能直接升级到4.1。因为4.1使用 UTF8 来存储元数据名。
- 字符串根据标准SQL来比较:比较之前不删除末尾的空格,以前用末尾空格扩展了比较短的字符串。现在的结果是
'a' > 'a\t',以前则不这样。可以用 mysqlcheck 来检查一下数据表 MyISAM现在使用更好的校验和算法了
- 如果在4.1.0到4.1.3版本的MySQL中创建了包含
- 不兼容的变化:MySQL把字符串类型字段的长度定义理解为字符长度而不是字节长度。
- 重要提示:MySQL 4.1用
UTF8字符集存储数据表名和字段名。如果有用标准 7字节 US-ASCII 范围之外的字符作为表名/字段名的话,需要重建表 - 重要提示:升级到4.1.1或更高后,就很难降级回到4.0或4.1了,因为
InnoDB使用了多个表空间的缘故 - 不兼容的变化:MySQL 4.1.13支持让每个连接设定时区,因此系统变量
timezone改成system_time_zone 所有的数据表和非二进制字符串(CHAR,VARCHAR, 和TEXT)的字段都有字符集,二进制字符串字段包括BINARY,VARBINARY, 和BLOBMySQL4.0中,如果有字段类型为CHAR BINARY或VARCHAR BINARY,则它们会被当作二进制字符串类型- 如果数据表的字段中存储着MySQL 4.1直接就能支持的字符集字符数据时,则可以将这个字段的值转换成由合适的字符集存储
- MySQL 4.1中对数据结构描述文件
.frm的格式稍作改进,新版本能兼容这个新格式,但是旧版本则不能 - windows下的服务器启动时增加
--shared-memory选项即可支持从本地客户端连接时使用共享内存 - 不兼容的变化:从MySQL 4.1.1开始,对用户自定义函数集合接口发生了很大改进
- 不兼容的变化:从4.1.10a开始,除非和主函数之间有辅助的链接,否则服务器将不再默认地加载用户自定义函数(UDFs),也可以通过
--allow-suspicious-udfs选项来启用
客户端部分:
- mysqldump 默认启用
--opt和--quote-names选项
SQL部分:
- 不兼容的变化:字符串根据标准SQL来比较,如上面的"服务器变化"部分中提到的
- 不兼容的变化:
TIMESTAMP返回'YYYY-MM-DD HH:MM:SS'格式的字符串。在MySQL 4.0中,可以增加选项--new来获得MySQL 4.1中这方面的特性 - 不兼容的变化:二进制数据例如
0xFFDF被当成字符串而非数字 - 不兼容的变化:在MySQL 4.1.1前,语句解析器不是那么严格,它在处理字符串转时间转换时会忽略第一个数字前的其他字符。在4.1.1之后,就比较严格了
- 不兼容的变化:在MySQL 4.1.2,
SHOW TABLE STATUS结果的Type字段改名为Engine了 - 当执行多表删除语句时,要删除的表只能使用它的别名,而不能用真实表名
- 返回结果是
DATE,DATETIME, 或TIME类型的函数的结果会被转换成时间型 AUTO_INCREMENT字段不能设定默认(DEFAULT)值了LIMIT不再接受负数参数了SERIALIZE不再是sql_mode变量的有效值了,它的取代值是SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
C API部分:
MySQL 4.1中的密码哈希算法做了改进以提升安全性,不过会导致兼容性问题。使用MySQL 4.0及更早版本的客户端库文件会发生问题。
- 不兼容的变化:
mysql_shutdown()函数增加一个参数:SHUTDOWN-level - 某些函数例如
mysql_real_query()发生错误时返回1而非-1
密码处理部分:
MySQL 4.1中的密码哈希算法做了改进以提升安全性,不过会导致兼容性问题。使用MySQL 4.0及更早版本的客户端库文件会发生问题。解决办法有:
- 升级客户端库文件到4.1(不用升级服务器端库文件)
- 运行 mysql_fix_privilege_tables 脚本来加宽 user 表中的 Password 字段值,以适应新的哈希算法。如果想要允许4.1以下的客户端还能连接到服务器,那么服务器运行时要增加参数 --old-passwords
5、附录
- 备份旧数据
- 停止旧服务器
- 从windows的系统服务中删掉mysql服务,用如下命令:
C:\>
C:\mysql\bin\mysqld --remove - 用可执行安装文件方式安装mysql,或者解压可直接执行的二进制压缩包来安装
- 重新注册mysql服务,用如下命令:
C:\>
C:\mysql\bin\mysqld --install - 重启服务器
- 其他的问题详见上面提到的各种升级中会碰到的情况
升级授权表之前一定要备份好 mysql 数据库,以备升级失败时使用旧的授权表。
在unix或类unix系统中,运行 mysql_fix_privilege_tables 脚本来升级授权表:
shell> mysql_fix_privilege_tables
必须在 mysqld 运行着的时候执行这个脚本,它尝试使用 root 帐号来连接服务器;因此,当 root 需要密码时,用如下方式来指定密码:
shell> mysql_fix_privilege_tables --password=root_password
在 MySQL 4.1之前,则是用如下形式来指定密码:
shell> mysql_fix_privilege_tables root_password
接下来 mysql_fix_privilege_tables 脚本会升级授权表,在这个过程中可能会有一些 Duplicate column name 警告信息,无需理会它们。待它运行完之后,重启一下服务器即可。
在windows平台上,授权表想要升级到4.0.15并不容易。从4.0.15开始,发行版中包含一个sql脚本:mysql_fix_privilege_tables.sql,用 mysql 客户端运行它来升级授权表,运行类似如下命令:
C:\>C:\mysql\bin\mysql -u root -p mysqlmysql>SOURCE C:/mysql/scrīpts/mysql_fix_privilege_tables.sql
把上面提到的目录改成真实的目录。
请查看我翻译的文档"6.6 升级同步"
4、) mysql_update MySQL升级时检查数据表
每次升级的时候都必须运行 mysql_upgrade 脚本。它检查了当前版本的MySQL下的所有数据库表的不兼容性,就会检查这些表;并且发现有问题时,也会修复这些表。mysql_update 同时升级了系统表,因此可以兼容新的权限机制并且使用新增的权限。
由于 mysql_update 会把检查过和修复过的表都标记上当前的MySQL版本号,因而保证了下一次在同一个MySQL版本下运行这个脚本时,都会再次报告哪些表需要修复或检查。
它还会把MySQL的版本号记录在数据文件目录下的一个文件中:mysql_upgrade.info。这个文件用于标识当前发布版本检查表时哪些表可以略过,检查时想要忽略这个文件,只需附加上 --force 选项。
为了能检查和修复数据表,并且升级系统表,mysql_update 执行了一下命令:
mysqlcheck --check-upgrade --all-databases --auto-repair mysql_fix_privilege_tables
mysql_update 目前只支持类unix平台;在windows下,需要手工执行 mysqlcheck 命令,升级授权表请看附录"升级授权表"。
执行 mysql_update 时,MySQL服务器必须运行着,它有以下几个参数:
--help显示帮助信息并且退出
--basedir=path设定MySQL的安装路径
--datadir=path设定MySQL的数据文件路径
--force告诉
mysql_update,在检查时忽略是否存在mysql_upgrade.info文件,强行检查该版本的MySQL数据表,不管是否已经检查过了--user=,user_name-uuser_name连接到MySQL的用户名,默认是
root--verbose冗余模式。发生问题时打印出更多的信息
其他的选项诸如 --password[= 是要传递给 mysqlcheck 和 mysql_fix_privilege_tables 脚本的,并不是必须的。password]
作/译者:叶金荣(Email:
),来源:http://imysql.cn,转载请注明作/译者和出处,并且不能用于商业用途,违者必究。
一. 启动参数优化
修改 my.cnf (或者my.ini),加入/修改以下几行
#设定缓存的连接数,节省连接时的开销 back_log = 64 #禁用文件系统外部锁 external-locking = 0 #禁用BDB,如果你确实不需要的话,innodb也是如此 skip-bdb #索引缓冲,如果是专用的数据库服务器,可以设置高达服务器内存的一半,如果不是专用的, #还是设置得低一点 key_buffer = 512M #缓存数据表数量,如果内存较大,可以设置稍微高一点,否则还是设置低一点 #设置这个参数可以参见系统状态中的 open_tables(表示当前打开的数据表总数) #和 opened_tables(表示所有打开的数据表总数) table_cache = 128 #禁用dns解析,如果你的授权信息中采用dns授权方式了,就不能启用该选项 skip-name-resolve #记录慢查询和没有使用索引的查询,便于帮助分析问题所在 long_query_time = 1 log-slow-queries = /usr/local/mysql/data/slow.log log-queries-not-using-indexes |
其他参数诸如 sort_buffer_size,net_buffer_length,read_buffer_size,read_rnd_buffer_size,myisam_sort_buffer_size, 等请查询MySQL手册,然后做出合适的调整.
thread_cache_size,query_cache_size,max_binlog_cache_size
二. 其他小TIPS
- 针对Innodb表,尽量不执行
SELECT COUNT(*)语句,因为Innodb表没有类似MyISAM那样的内部计数器来记录表记录总量,执行这个操作将会全表扫描,速度很慢. - 尽量使用MyISAM表,除非必须使用其他类型,因为MyISAM类型的总体读写效率是相当高的,缺点是表级锁,而不是行/页级锁.
- 善用
EXPLAIN来帮助你分析查询优化情况 - 如果需要对一个较大的且并发读写较多的数据表做
GROUP BY等统计操作,建议使用摘要表来存储统计信息,定期更新统计表,这可能获得很大的性能改善.- 查询时如果有
ORDER BY分句的话,注意让它的字段顺序和索引字段顺序对应,这样能加快排序速度- 如果有一个多字段索引,则查询时,必须按照索引顺序来使用,否则该索引不会用到.例如:
索引`idx_`(col1, col2, col3),那么查询SELECT .... FROM ... WHERE col1=1 AND col2=2;使用索引,而查询... WHERE col2=2 AND col3=3;或... WHERE col1=1 AND col3=3;则不使用索引.WHERE中的条件如果有恒量类型的(如 `field` = 1),就尽量放在前面,这样能更快的执行过滤.- 2 个表连接时,连接字段的类型最好一致(包括字段长度),这样的话索引速度快多了.
- 大部分情况下,字符类型的字段索引值需要一部分,例如
CREATE INDEX char_idx ON tbl1 ( name(10) );- 尽量使用最合适的数据类型,能使用
ENUM就不使用TINYINT,能使用SMALLINT就不使用MEDIUMINT.这样能节省存储空间,增加数据存储量,提高搜索速度.不要担心这样会对省级产生很大的影响,因为加入从TINYINT类型改变为INT的话,并不会改变原来的数据.- 如果知道某个表总是频繁使用的话,可以把它放到
hot_cache中,用以下方法:SET GLOBAL hot_cache.key_buffer_size=128*1024; CACHE INDEX `xxx` IN hot_cache;
- 把拖沓复杂,速度慢的的查询分解成多个简洁明了的查询,这样尽管查询次数多了,但是总体速度和效率却可能反而更高了,而且也减少了锁表的可能.
- 执行查询时,尽量不使用外部函数,因为这样的话就无法使用可能存在的索引,并且无论如何都会极大地降低效率.如:
... WHERE `create_time` > UNIX_TIMESTAMP(NOW());这样的查询.可以在程序中把当前的时间取得,然后直接执行构造好了的SQL语句.- 在索引字段上使用 LIKE 查询时,左边不要使用 '%' 修饰符,这样就可以利用索引,否则无法使用索引.如
... `name` LIKE 'yejr%';.- 如果有可能,多使用存储过程,这大概能获得 22% 的性能提高.
- 如果并发访问量相对最大连接数小多了的话,最好使用永久连接,这样能节省不少连接时的系统资源损耗.
- 定期的在MyISAM表上执行
OPTIMIZE TABLE,这能整理随便,提高索引效率.- 如果你主要按 col1,col2,...顺序检索记录,请在对表大量更改后执行
ALTER TABLE ... ORDER BY col1, col2, ...语句,这可以获得更好的性能.- 对于频繁更改的MyISAM表,应尽量避免更新所有变长字段(VARCHAR、BLOB和TEXT).
- 对于记录总数超过500万的单表,就应该赶紧考虑分表了.分表策略有多种,比如按ID号段,或者按时间切分,等等.
- 创建数据表时尽量指定字段不能为NULL,并且有默认值.
- 使用
LOAD DATA,而不是使用大批量的INSERT语句来导入数据.- 使数据表名和字段名尽可能的短,例如在
user表中使用字段名name,而不是user_name.- 用
DELAY_KEY_WRITE = 1选项让MyISAM更快地更新索引,因为在表关闭之前它们不刷新到硬盘上.缺点是如果服务器如果突然被杀掉了,重启之后就必须运行myisamchk修复索引才行.- 采用复制机制来分摊读数据的负载,把写数据只放在主服务器上,把读平均分摊到各个从服务器上,能大大提高系统负载.
- 如果需要对一个较大的且并发读写较多的数据表做
由于需要,从4.0直接升级到5.0,查看了一下changelog,发现主要有以下变化:
一、从 4.0 到 4.1 的主要变化
- 如果在4.1.0到4.1.3版本的MySQL中创建了包含 TIMESTAMP 字段的 InnoDB
表。则在升级到4.1.4及更高时需要重建表,因为存储格式发生变化了 - 字符串根据标准SQL来比较:比较之前不删除末尾的空格,以前用末尾空格扩展了比较短的字符串。现在的结果是
'a' > 'a\t',以前则不这样。可以用 mysqlcheck 来检查一下数据表 - TIMESTAMP 返回 'YYYY-MM-DD HH:MM:SS' 格式的字符串。在MySQL
4.0中,可以增加选项 --new 来获得MySQL 4.1中这方面的特性 - 在MySQL
4.1.1前,语句解析器不是那么严格,它在处理字符串转时间转换时会忽略第一个数字前的其他字符。在4.1.1之后,就比较严格了 - 返回结果是 DATE, DATETIME, 或 TIME 类型的函数的结果会被转换成时间型
二、再看从 4.1 到 5.0 的主要变化
- InnoDB 和 MyISAM 表中空格结尾的 TEXT 字段索引顺序改变了。因此需要运行
"CHECK TABLE" 语句修复数据表,如果出现错误,就运行 "OPTIMIZE TABLE" 或 "REPAIR
TABLE" 语句修复,甚至重新转储(用mysqldump) - MySQL 5.0.15开始,如何处理 BINARY 字段中填充的值已经改变了。填充的值现在是
0x00 而非空格了,并且在取值的时候不会去除末尾的空格 - 从MySQL 5.0.3开始,DECIMAL 的实现方式已经改变了,5.0对 DECIMAL
的格式限制严格多了 - 在MySQL 5.0.3到5.0.5之间版本的 MyISAM 和 InnoDB 表中创建的 DECIMAL
字段升级到5.0.6之后会发生崩溃 - 在以前,等待超时的锁会导致 InnoDB
回滚当前全部事务,从5.0.13开始,就只回滚最近的SQL语句了 - 在4.1.13/5.0.8以前,DATETIME 的加0后就转换成 YYYYMMDDHHMMSS 格式,现在变成
YYYYMMDDHHMMSS.000000 格式了 - 从5.0.3开始,DECIMAL 用更有效的格式来存储
- 5.0.3开始,在计算 DECIMAL 值和舍入精确值的时候采用精确数学
- 4.1中,FLOAT 或 DOUBLE 之间的比较碰巧没问题,但在5.0中可能就不行了
- 从5.0.3开始,VARCHAR 和 VARBINARY 字段中末尾的空格不再删除
- 增加了一个新的启动选项 innodb_table_locks,它导致 LOCK TABLE 时也可以请求
InnoDB 表锁。这个选项默认打开,不过可能在 AUTOCOMMIT=1 和 LOCK TABLES
应用中会导致死锁
看来,我只需主要关注 时间(TIMESTAMP, DATETIME< DATE, TIME) 和
数值型(FLOAD, DOUBLE, DECIMAL) 这两种类型的变化;另外,我升级过程中暂时还不需要涉及到字符集问题,因此相对轻松一些。
升级步骤如下:
- 执行
FLUSH TABLES WITH READ LOCK;
直接拷贝 MyISAM 表文件
- 用
mysqldump导出 Innodb 类型的表
整个过程都很顺利,新系统启动之后,发现如下2个问题:
- 新增了关键字
INOUT,因此需要检查表结构中还有其他什么字段使用关键字了 DATE_FORMAT函数要求严谨多了,DATE_FORMAT('2006/11/24 09:14:00', '%Y-%m-%d %T')和
DATE_FORMAT('2006/11/2409:14:00', '%Y-%m-%d %T')的结果完全不一样,在 4.0 中,能兼容这两种格式,而在 5.0 中,只能正确的使用前者了,后者则会有问题。这也应该是上面提到的时间类型发生的变化所致。
到此为止,升级基本结束,大致检查了 DECIMAL 类型也没问题,剩下的就是检查其他的了。
毫不夸张地说,MPM的引入是Apache 2.0最重要的变化。大家知道,Apache是基于模块化的设计,而Apache 2.0更扩展了模块化设计到Web服务器的最基本功能。服务器装载了一种多道处理模块,负责绑定本机网络端口、接受请求,并调度子进程来处理请求。扩展模块化设计有两个重要好处:
◆ Apache可以更简洁、有效地支持多种操作系统;
◆ 服务器可以按站点的特殊需要进行自定制。
在用户级,MPM看起来和其它Apache模块非常类似。主要区别是在任意时刻只能有一种MPM被装载到服务器中。
指定MPM的方法
下面以Red Hat Linux 9为平台,说明在Apache 2.0中如何指定MPM (Apache采用2.0.45)。先解压缩源代码包httpd-2.0.45.tar.gz,生成httpd-2.0.45目录(Apache 1.3源代码包的命名规则是apache_1.3.NN.tar.gz,而2.0版则是httpd-2.0.NN.tar.gz,其中NN是次版本号)。
进入httpd-2.0.45目录,运行以下代码:
$ ./configure --help|grep mpm
显示如下:
--with-mpm=MPM
Choose the process model for Apache to use.
MPM={ beos|worker|prefork|mpmt_os2| perchild|leader|threadpool }
上述操作用来选择要使用的进程模型,即哪种MPM模块。Beos、mpmt_os2分别是BeOS和OS/2上缺省的MPM, perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要CGI的虚拟主机时特别有用,会比1.3版中的SuExec 机制做得更好。leader和threadpool都是基于worker的变体,还处于实验性阶段,某些情况下并不会按照预期设想的那样工作,所以 Apache官方也并不推荐使用。因此,我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM ( 有关其它的MPM详细说明,请参见Apache官方文档:http://httpd.apache.org/do...。
prefork的工作原理及配置
如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM。它所采用的预派生子进程方式也是 Apache 1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。
若使用prefork,在make编译和make install安装后,使用“httpd -l”来确定当前使用的MPM,应该会看到prefork.c(如果看到worker.c说明使用的是worker MPM,依此类推)。再查看缺省生成的httpd.conf配置文件,里面包含如下配置段:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
prefork的工作原理是,控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足 MinSpareServers设置的值为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild” 个请求后将自动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:
◆ 可防止意外的内存泄漏;
◆ 在服务器负载下降的时侯会自动减少子进程数。
因此,可根据服务器的负载来调整这个值。笔者认为10000左右比较合适。
MaxClients是这些指令中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值 150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。如果把这个值设为大于256,那么 Apache将无法起动。事实上,256对于负载稍重的站点也是不够的。在Apache 1.3中,这是个硬限制。如果要加大这个值,必须在“configure”前手工修改的源代码树下的src/include/httpd.h中查找 256,就会发现“#define HARD_SERVER_LIMIT 256”这行。把256改为要增大的值(如4000),然后重新编译Apache即可。在Apache 2.0中新加入了ServerLimit指令,使得无须重编译Apache就可以加大MaxClients。下面是笔者的prefork配置段:
StartServers 10
MinSpareServers 10
MaxSpareServers 15
ServerLimit 2000
MaxClients 1000
MaxRequestsPerChild 10000
上述配置中,ServerLimit的最大值是20000,对于大多数站点已经足够。如果一定要再加大这个数值,对位于源代码树下server/mpm/prefork/prefork.c中以下两行做相应修改即可:
#define DEFAULT_SERVER_LIMIT 256
#define MAX_SERVER_LIMIT 20000
worker的工作原理及配置
相对于prefork,worker是2.0 版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。但是, worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。这种MPM的工作方式将是Apache 2.0的发展趋势。
在configure -with-mpm=worker后,进行make编译、make install安装。在缺省生成的httpd.conf中有以下配置段:
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild 线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用 ThreadLimit指令,它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行:
#define DEFAULT_THREAD_LIMIT 64
#define MAX_THREAD_LIMIT 20000
这两行对应着ThreadsPerChild和ThreadLimit的限制数。最好在configure之前就把64改成所希望的值。注意,不要把这两个值设得太高,超过系统的处理能力,从而因Apache不起动使系统很不稳定。
Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。这两个值位于源码树server/mpm/worker/worker.c中的以下两行:
#define DEFAULT_SERVER_LIMIT 16
#define MAX_SERVER_LIMIT 20000
需要注意的是,如果显式声明了ServerLimit,那么它乘以ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则Apache将会自动调节到一个相应值(可能是个非期望值)。下面是笔者的 worker配置段:
StartServers 3
MaxClients 2000
ServerLimit 25
MinSpareThreads 50
MaxSpareThreads 200
ThreadLimit 200
ThreadsPerChild 100
MaxRequestsPerChild 0
通过上面的叙述,可以了解到Apache 2.0中prefork和worker这两个重要MPM的工作原理,并可根据实际情况来配置Apache相关的核心参数,以获得最大的性能和稳定性。
TMOUT=300
300,表示300秒,也就是表示5分钟。这样,如果系统中登陆的用户在5分钟内都没有动作,那么系统会自动注销这个账户。你可以在个别用户的“.bashrc”文件中添加该值,以便系统对该用户实行特殊的自动注销时间。
改变这项设置后,必须先注销用户,再用该用户登陆才能激活这个功能。






