
1.7 MySQL的升级和降级
升级是常用的操作,可以修补版本出现的漏洞。进行升级操作时,比较稳妥的做法是,先在测试环境进行测试,确保过程顺利,再到生产环境进行操作。
降级并不常用,使用降级通常是由于兼容性或性能问题。
1.7.1 升级MySQL
1. 升级方法
MySQL推荐两种升级方式:就地升级和逻辑升级。就地升级需要关闭旧版本的MySQL,替换当前的二进制文件或包,然后在现有的数据目录上重启MySQL,并运行mysql_upgrade。逻辑升级需要使用备份或导出语句从旧版本的MySQL中导出SQL语句,然后安装新版本,在新版本的基础上执行导出的SQL语句。
提示
使用旧版本导出的SQL语句在新版本中可能会报错,所以请预先使用checkForServerUpgrade脚本进行检查,使逻辑升级能够顺利进行。
2. 升级路线
MySQL支持从5.7版本升级到8.0,仅限于正式发行版,即GA版。
MySQL支持逐级升级,不可跳级。例如,要想升级到MySQL 8,必须先升级到5.7版本,5.6版本无法直接升级到8版本。
一旦发行系列到达稳定版状态,正式发行版之间可以直接进行升级。例如,MySQL 8.0.x可升级至8.0.y,也可升级至8.0.z。
MySQL 8.0.11是MySQL 8.0发行系列的第一个正式发行版本。
3. 升级前的准备
首先需要备份当前数据库和日志文件。备份内容应包含mysql系统数据库,涵盖MySQL数据字典表和系统表。
MySQL 8包含一个全局数据字典。在之前的MySQL版本中,字典数据存储在元数据文件和非事务的系统表中。将MySQL 5.7升级到8时,需将数据目录从基于文件的结构升级到基于数据字典的结构。
升级前需检查版本之间的兼容问题,重点检查新特性、过时或废弃特性以及一些影响应用的改变,在升级前后及时处理以确保应用正常运行。
4. 验证MySQL 5.7升级到8前的先决条件
(1)确保没有使用过时的数据类型、函数和单独的frm文件的数据库表、非本地分区的InnoDB引擎表以及没有定义的触发器。检查命令如下:
mysqlcheck -u root -p --all-databases --check-upgrade
(2)确保已分区的数据库表使用的存储引擎都支持本地分区。检查命令如下:
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE NOT IN ('innodb', 'ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned%';
上述语句中查询出的数据库表可通过两种方式进行修正,将存储引擎改为InnoDB或移除表的分区。命令如下:
#设置表的存储引擎为InnoDB ALTER TABLE table_name ENGINE = INNODB; #移除表分区 ALTER TABLE tablename REMOVE PARTITIONING;
(3)确保MySQL 5.7版本中mysql系统数据库中的表名与MySQL 8数据字典的表名不重复。检查命令如下:
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE LOWER(TABLE_SCHEMA) = 'mysql' and LOWER(TABLE_NAME) IN ( 'catalogs', 'character_sets', 'collations', 'column_statistics', 'column_type_elements', 'columns', 'dd_properties', 'events', 'foreign_key_column_usage', 'foreign_keys', 'index_column_usage', 'index_partitions', 'index_stats', 'indexes', 'parameter_type_elements', 'parameters', 'resource_groups', 'routines', 'schemata', 'st_spatial_reference_systems', 'table_partition_values', 'table_partitions', 'table_stats', 'tables', 'tablespace_files', 'tablespaces', 'triggers', 'view_routine_usage', 'view_table_usage' );
(4)确保外键限制名称均不超过64个字符。检查命令如下:

(5)确保数据库表或程序使用单独的枚举或设置列元素的长度不超过255个字符或1020个字节。
(6)确保本地的MySQL 5.7版本中未使用在MySQL 8中已不再提供支持的特性。
5. 就地升级
(1)参考第三条中升级前的准备,做好准备工作。
(2)关闭MySQL 5.7服务。
(3)替换二进制文件或安装包。
(4)启动MySQL 8服务,使用现有的数据目录,参考命令如下:
mysqld_safe --user=mysql --datadir=/path/to/existing-datadir
(5)MySQL 8.0服务启动成功之后,运行如下命令:
mysql_upgrade -u root -p
这个命令可以检查当前数据库中所有不兼容的表。
(6)关闭并重启服务,确保所有更改已生效。参考命令如下:
mysqladmin -u root -p shutdown mysqldsafe --user=mysql --datadir=/path/to/existing-datadir
6. 升级问题
(1)在MySQL 5.7中,frm表文件和InnoDB数据字典模式不匹配会导致升级失败。
(2)如果出现mysqld服务无法启动的情况,检查是否存在旧的配置文件。
(3)如果升级后客户端程序编译报错,检查一下是否使用了旧的头文件或库文件。
(4)如果升级后自定义函数名称与新版本的函数名称重复,那么自定义函数将无法被使用,需要使用DROP FUNCTION命令移除函数后再使用CREATE FUNCTION命令重新创建不重名的函数。
1.7.2 降级MySQL
目前,无法从MySQL 8降级到MySQL 5.7。唯一可选的方案是,在MySQL 5.7升级到8之前存储备份数据。所以,升级前务必对数据进行备份。
1.7.3 重建或修复表或索引
由于MySQL处理数据类型和字符集方式的改变,以及使用CHECK TABLE、mysqlcheck和mysql_upgrade命令时提示必须要修复和升级表,这就需要重建或修复表或索引。
1. 转储或重载表方法
如果因为不同版本的MySQL在二进制(就地)升级或降级后无法处理数据库表而重建,就必须使用dump-and-reload方法。升级或降级之前,先转储数据库表,然后在升级或降级完成之后重载这些表。
如果只使用dump-and-reload方法重建索引,可在升级或降级之后再进行转储。
CHECK TABLE操作提示需要升级表而进行InnoDB表重建,需要使用mysqldump命令建立转储文件,并使用mysql命令重载该文件,可参考如下命令:
mysqldump dbname tablename > dump.sql mysql dbname < dump.sql
如果要重建数据库中的所有表,参考命令如下:
mysqldump db_name > dump.sql mysql db_name < dump.sql
如果要重建所有数据库中的所有表,参考命令如下:
mysqldump --all-databases > dump.sql mysql < dump.sql
2. 更改表方法
使用ALTER TABLE语句将表设定为其已拥有的存储引擎。例如,某个表的存储引擎为InnoDB,可使用如下命令:
ALTER TABLE tablename ENGINE = InnoDB;
如果更改前不确定表的存储引擎,就应先使用SHOW CREATE TABLE语句查看。
3. 修复表方法
REPAIR TABLE方法只适用于MyISAM、ARCHIVE和CSV表。
如果表检查操作提示存在腐败或需要升级,此时可使用REPAIR TABLE语句,例如:
REPAIR TABLE tablename;
mysqlcheck --repair为修复表提供更方便的方法,可以添加--databases或--all-databases选项分别修复特定数据库或所有数据库中的所有表,参考命令如下:
mysqlcheck --repair --databases db_name ... mysqlcheck --repair --all-databases
1.7.4 将MySQL数据库复制到另一台机器
如果需要在不同机器之间传递数据库,要使用mysqldump生成包含SQL语句的文件,然后将该文件传输到目标机器上,并使用MySQL客户端导入该文件。
复制数据库到另一台机器最便捷的方法是在源数据库机器上运行如下命令:
mysqladmin -h 'other_hostname' create db_name mysqldump db_name | mysql -h 'other_hostname' db_name
其中,other_hostname代表目标数据库的IP地址或域名。
如果在目标机器上获取远程的数据库并复制过来,可使用如下命令:
mysqladmin create db_name mysqldump -h 'other_hostname' --compress db_name | mysql db_name
也可以通过命令将源数据库存储到压缩文件中,然后将压缩文件传输到目标机器上,在目标机器上运行命令将数据解压到数据库中,参考命令如下:
mysqldump --quick dbname | gzip > dbname.gz mysqladmin create db_name gunzip < db_name.gz | mysql db_name
另外,也可以通过mysqldump和mysqlimport命令来传输数据库。这种方式适合大数据量传输。首先在源数据库机器上创建文件目录,用以存放数据库文件,然后将这些文件传输到目标机器上,并在目标机器上装载这些文件,命令如下:
#源数据库机器执行命令 mkdir DUMPDIR mysqldump --tab=DUMPDIR db_name #目标机器执行命令 mysqladmin create db_name # create database cat DUMPDIR/*.sql | mysql db_name # create tables in database mysqlimport db_name DUMPDIR/*.txt # load data into tables
提示
不要忘记复制MySQL系统数据库,并且在复制完成后执行mysqladmin flush-privileges命令,以便服务器重新装载授权信息。