概述

不知不觉,MySQL8.0已经发布好多个GA小版本了,MySQL8.0版本基本已到稳定期。今天主要介绍从5.7升级到8.0版本的过程及注意事项,有想做版本升级的小伙伴可以参考下。


一、注意事项

mysql从5.7升级到8.0是支持的,但是只支持GA版本的升级,并且要求版本为5.7.9或者更高在升级到8.0之前,建议升级到5.7的最新版本。仅仅支持从5.7版本升级到8.0,不支持5.6版本升级到8.0

升级之前我们需要了解下MySQL5.7和8.0有哪些不同,简单总结出MySQL8.0以下几点新特性:

根据版本变化及官方升级教程,列举出以下几点注意事项:


二、准备工作

1、备份数据(包括当前的数据库和日志文件)

--备份数据 mysqldump -uroot -p ycapp_dflg_prod --single_transaction --flush-logs --master-data=2 >/backup/ycapp.sql --备份视图、函数、存储过程、事件、触发器的定义 ============================================================================ #!/bin/bash # ./output_db_object_definition.sh > /dev/null 2>&1 db_user="root" db_pwd="xxxx" db_host="localhost" db_port=3306 db_name="xxxx" save_file="/home/scripts/${db_name}_object_definition.sql" # view,function,procedure,event,trigger output_type='view,function,procedure,event,trigger' (cat <<out /* ouput object‘s definition for database "$db_name" ouput time: $(date " %Y-%m-%d %H:%M:%S") ouput object type: $output_type */ out )>$save_file echo "">> $save_file echo "">> $save_file # 视图 if [[ $output_type == *"view"* ]] then echo "-- ------------------------------------------------------------" >> $save_file echo "-- views" >> $save_file echo "-- ------------------------------------------------------------" >> $save_file mysql -h$db_host -P$db_port -u$db_user -p$db_pwd --skip-column-names \ -e "select concat('SHOW CREATE VIEW ',table_schema,'.',table_name,';') from information_schema.views where table_schema='$db_name'" |\ sed 's/;/\\G/g' | mysql -h$db_host -P$db_port -u$db_user -p$db_pwd $db_name |\ sed 's/Create View: /kk_begin\n/g' | sed 's/[ ]*character_set_client:/;\nkk_end/g' |\ sed -n '/kk_begin/{:a;N;/kk_end/!ba;s/.*kk_begin\|kk_end.*//g;p}' >> $save_file fi # 函数 if [[ $output_type == *"function"* ]] then echo "-- ------------------------------------------------------------" >> $save_file echo "-- function" >> $save_file echo "-- ------------------------------------------------------------" >> $save_file mysql -h$db_host -P$db_port -u$db_user -p$db_pwd --skip-column-names \ -e "select concat('SHOW CREATE FUNCTION ',routine_schema,'.',routine_name,';') from information_schema.routines where routine_schema='$db_name' and ROUTINE_TYPE='FUNCTION'" |\ sed 's/;/\\G/g' | mysql -h$db_host -P$db_port -u$db_user -p$db_pwd $db_name |\ sed 's/Create Function: /kk_begin\ndelimiter $$\n/g' | sed 's/[ ]*character_set_client:/$$ \ndelimiter ;\nkk_end/g' |\ sed -n '/kk_begin/{:a;N;/kk_end/!ba;s/.*kk_begin\|kk_end.*//g;p}' >> $save_file fi # 存储过程 if [[ $output_type == *"procedure"* ]] then echo "-- ------------------------------------------------------------" >> $save_file echo "-- procedure" >> $save_file echo "-- ------------------------------------------------------------" >> $save_file mysql -h$db_host -P$db_port -u$db_user -p$db_pwd --skip-column-names \ -e "select concat('SHOW CREATE PROCEDURE ',routine_schema,'.',routine_name,';') from information_schema.routines where routine_schema='$db_name' and ROUTINE_TYPE='PROCEDURE'" |\ sed 's/;/\\G/g' | mysql -h$db_host -P$db_port -u$db_user -p$db_pwd $db_name |\ sed 's/Create Procedure: /kk_begin\ndelimiter $$\n/g' | sed 's/[ ]*character_set_client:/$$ \ndelimiter ;\nkk_end/g' |\ sed -n '/kk_begin/{:a;N;/kk_end/!ba;s/.*kk_begin\|kk_end.*//g;p}' >> $save_file fi # 事件 if [[ $output_type == *"event"* ]] then echo "-- ------------------------------------------------------------" >> $save_file echo "-- event" >> $save_file echo "-- ------------------------------------------------------------" >> $save_file mysql -h$db_host -P$db_port -u$db_user -p$db_pwd --skip-column-names \ -e "select concat('SHOW CREATE EVENT ',EVENT_SCHEMA,'.',EVENT_NAME,';') from information_schema.events where EVENT_SCHEMA='$db_name'" |\ sed 's/;/\\G/g' | mysql -h$db_host -P$db_port -u$db_user -p$db_pwd |\ sed 's/Create Event: /kk_begin\ndelimiter $$\n/g' | sed 's/[ ]*character_set_client:/$$ \ndelimiter ;\nkk_end/g' |\ sed -n '/kk_begin/{:a;N;/kk_end/!ba;s/.*kk_begin\|kk_end.*//g;p}' >> $save_file fi # 触发器 if [[ $output_type == *"trigger"* ]] then echo "-- ------------------------------------------------------------" >> $save_file echo "-- trigger" >> $save_file echo "-- ------------------------------------------------------------" >> $save_file mysql -h$db_host -P$db_port -u$db_user -p$db_pwd --skip-column-names \ -e "select concat('SHOW CREATE TRIGGER ',TRIGGER_SCHEMA,'.',TRIGGER_NAME,';') from information_schema.triggers where TRIGGER_SCHEMA='$db_name';" |\ sed 's/;/\\G/g' | mysql -h$db_host -P$db_port -u$db_user -p$db_pwd $db_name|\ sed 's/SQL Original Statement: /kk_begin\ndelimiter $$\n/g' | sed 's/[ ]*character_set_client:/$$ \ndelimiter ;\nkk_end/g' |\ sed -n '/kk_begin/{:a;N;/kk_end/!ba;s/.*kk_begin\|kk_end.*//g;p}' >> $save_file fi # ^M, you need to type CTRL-V and then CTRL-M sed -i "s/\^M//g" $save_file

2、升级检查

mysqlcheck -u root -p --all-databases --check-upgrade

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(1)

3、检查分区表(不支持分区的存储引擎)

select table_schema,table_name from information_schema.tables where engine not in ('innodb','ndbcluster') and create_options like '%partitioned';

如果存在记录,必须把对应表修改为innodb引擎或者把表修改为非分区的(alter table table_name engine=INNODB或alter table table_name remove partitioning);

4、在mysql数据库中,必须不存在与mysql8.0数据字典相同名称的表

所有同名的表必须要重命名。

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' );

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(2)

5、必须要不存在外键超过64字符的表

SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN (SELECT LEFT(SUBSTR(ID,INSTR(ID,'/') 1), INSTR(SUBSTR(ID,INSTR(ID,'/') 1),'_ibfk_')-1) FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN WHERE LENGTH(SUBSTR(ID,INSTR(ID,'/') 1))>64);

如果存在,必须修改表。

6、必须要确保不存在拥有ENUM或者SET列元素并且超过255字符或者1020字节长度的表和存储过程

7、mysql5.7中必须不使用8.0不支持的特性。例如NDB引擎,8.0不再支持;部分启动选项不再支持:例如--ignore-db-dir已被移除。

8、如果innodb使用了XA事务,确保所有XA事务提交或者回滚。

9、如果存在加密的innodb表空间,执行语句

alter instance rotate innodb master key;

10、如果mysql5.7启动设置了innodb_fast_shutdown参数为2(冷停止),通过设置参数为1或者0来实现快速或者慢停止

show variables like 'innodb_fast_shutdown'; # 确保数据都刷到硬盘上,更改成0 set global innodb_fast_shutdown=1; --fast shutdown set global innodb_fast_shutdown=0; --slow shutdown

11、停止数据库

mysqladmin -u root -p shutdown

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(3)

12、更改配置文件my.cnf

因5.7版本与8.0版本参数有所不同,为了能顺利升级,我们需要更改部分配置参数。主要注意symbolic-links、sql_mode、binlog_expire_logs_seconds、show_compatibility_56、密码认证插件及字符集设置。下面展示下更改后的配置文件:

[mysqld] port=3306 datadir=/fsl_data/datafile log-error=/fsl_data/log/mysqld.log #mysql8默认禁用symbolic-links #symbolic-links=0 bind-address=0.0.0.0 lower_case_table_names=1 character_set_server=utf8mb4 max_allowed_packet=500M #mysql8取消NO_AUTO_CREATE_USER sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION #InnoDB用于缓存数据、索引、锁、插入缓冲、数据字典等 innodb_buffer_pool_size=4G #InnoDB的log buffer innodb_log_buffer_size = 64M #InnoDB redo log大小 innodb_log_file_size = 256M #InnoDB redo log文件组 innodb_log_files_in_group = 2 innodb_flush_log_at_trx_commit = 1 #连接数 max_connections=600 max_connect_errors=1000 max_user_connections=400 #设置临时表最大值 max_heap_table_size = 100M tmp_table_size = 100M #每个连接都会分配的一些排序、连接等缓冲 sort_buffer_size = 2M join_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 2M #mysql8已经没有query cache #query_cache_size = 0 #如果是以InnoDB引擎为主的DB,专用于MyISAM引擎的 key_buffer_size 可以设置较小,8MB 已足够,如果是以MyISAM引擎为主,可设置较大,但不能超过4G key_buffer_size = 8M #设置慢查询阀值,单位为秒 long_query_time = 60 slow_query_log=1 log_output=table,File #日志输出会写表,也会写日志文件,为了便于程序去统计,所以最好写表 slow_query_log_file=/fsl_data/log/slow.log #快速预热缓冲池 innodb_buffer_pool_dump_at_shutdown=1 innodb_buffer_pool_load_at_startup=1 #打印deadlock日志 innodb_print_all_deadlocks=1 #二进制配置 server-id = 1 log-bin = /fsl_data/log/mysql-bin.log log-bin-index =/fsl_data/log/binlog.index log_bin_trust_function_creators=1 binlog_format = row gtid_mode = ON enforce_gtid_consistency = ON #mysql8中expire_logs_days参数取消,修改成binlog_expire_logs_seconds参数,单位为秒,以下代表15天 binlog_expire_logs_seconds=1296000 #schedule event_scheduler = on #mysql8取消了兼容5.6参数 #show_compatibility_56=on #处理TIMESTAMP with implicit DEFAULT value is deprecated explicit_defaults_for_timestamp=true #mysql8改了默认加密方式为"caching_sha2_password",这里改回来 default_authentication_plugin=mysql_native_password #禁用SSL提高性能 skip_ssl


三、MySQL8升级过程

下面以Linux系统为例,展示下具体升级过程。我的系统是CentOS7.7,原版本是MySQL5.7.27,以In-Place方式直接升级到MySQL8.0.19。

1、下载解压安装包

官网下载对应版本的tar包,可通过wget下载或者本地下载后上传。

下载地址:https://downloads.mysql.com/archives/community/

>选择mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz

执行以下步骤解压tar包:

mkdir -p /usr/local/mysql8 tar -xvf mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz -C /usr/local/mysql8 mv /usr/local/mysql8/mysql-8.0.19-linux-glibc2.12-x86_64/* /usr/local/mysql8 chown -R mysql.mysql /usr/local/mysql8/

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(4)

2、执行升级程序

在mysql8.0.16版本后只需要使用新版本软件包启动MySQL Server,此时Server会自动检查并执行第一步升级操作,升级数据字典表。在第一步升级完成之后,Server分析系统表和用户表是否需要升级,如果指定了升级选项 upgrade 为AUTO或者FORCE,Server将会执行第二步升级操作,对系统表和用户表进行升级,如果第二步不需要升级,Server将会跳过第二步。

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(5)

对于所有数据库对象,包括数据库、表空间、系统和用户表、视图,以及存储程序(存储过程和函数、触发器、事件调度程序事件)。服务器同时删除以前用于元数据存储的文件。例如升级后数据表不再有.frm文件。

如果升级完成,server将会创建一个backup_metadata_57的目录,目录中将会备份db.opt及以.frm,.par,.TRG,.TRN,.isl。

# 用mysql8.0.19客户端直接启动(/fsl_data/datafile/为需要升级的数据文件目录) /usr/local/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --datadir=/fsl_data/datafile/ --user=mysql &

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(6)

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(7)

3、重启数据库并验证

#停止数据库,再启动数据库查看升级结果: /usr/local/mysql8/bin/mysqladmin -u root -p shutdown /usr/local/mysql8/bin/mysqld_safe --user=mysql --datadir=/fsl_data/datafile/

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(8)

4、卸载旧mysql数据库

停止数据库服务后操作如下:

# 查看MySQL服务 rpm -qa|grep mysql # 卸载 mysql rpm -qa|grep mysql|xargs -i rpm -e --nodeps {} # 还原配置文件 cp /etc/my.cnf.rpmsave /etc/my.cnf

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(9)

5、设置MySQL8 自启动服务脚本因basedir变成了/usr/local/mysql8,故相关环境变量推荐修改下。可按照以下步骤来操作验证:

vim /usr/lib/systemd/system/mysqld.service ==================================================================== [Unit] Description=MySQL Community Server After=network.target After=syslog.target [Install] WantedBy=multi-user.target Alias=mysql.service [Service] # 启动服务 User=mysql Group=mysql # Start main service ExecStart=/usr/local/mysql8/bin/mysqld --defaults-file=/etc/my.cnf # Sets open_files_limit LimitNOFILE = 50000 ==================================================================== # chmod u x /usr/lib/systemd/system/mysqld.service # systemctl daemon-reload # systemctl start mysqld # systemctl enable mysqld

6、设置环境变量

echo "PATH=$PATH:/usr/local/mysql8/bin" >> /etc/profile source /etc/profile which mysql


至此,我们的数据库由5.7成功升级至8.0!对比MySQL安装过程及升级过程,发现二者很相似,其实升级过程并不复杂,复杂的是升级后的验证及兼容测试,特别是对于复杂的业务库,MySQL版本升级还是要小心的。真实环境建议先升级从库,验证无误后再逐步对主库进行升级。

mysql5.7安装配置教程(MySQL5.7升级到MySQL8全过程指导总结)(10)

,