百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

MySQL5.7升级到MySQL8全过程指导总结

wptr33 2025-01-20 17:03 23 浏览

概述

不知不觉,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以下几点新特性:

  • 默认字符集由latin1变为utf8mb4。
  • MyISAM系统表全部换成InnoDB表。
  • JSON特性增强。
  • 支持不可见索引,支持直方图。
  • sql_mode参数默认值变化。
  • 默认密码策略变更。
  • 新增角色管理。
  • 支持窗口函数,支持Hash join。

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

  • 注意字符集设置。为了避免新旧对象字符集不一致的情况,可以在配置文件将字符集和校验规则设置为旧版本的字符集和比较规则。
  • 密码认证插件变更。为了避免连接问题,可以仍采用5.7的mysql_native_password认证插件。
  • sql_mode支持问题。8.0版本sql_mode不支持NO_AUTO_CREATE_USER,要避免配置的sql_mode中带有NO_AUTO_CREATE_USER。
  • 是否需要手动升级系统表。在MySQL 8.0.16版本之前,需要手动的执行mysql_upgrade来完成该步骤的升级,在MySQL 8.0.16版本及之后是由mysqld来完成该步骤的升级。

二、准备工作

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


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


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


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/


2、执行升级程序

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


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



3、重启数据库并验证

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


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


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版本升级还是要小心的。真实环境建议先升级从库,验证无误后再逐步对主库进行升级。


相关推荐

redis的八种使用场景

前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...

基于Redis的3种分布式ID生成策略

在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...

基于OpenWrt系统路由器的模式切换与网页设计

摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...

这篇文章教你看明白 nginx-ingress 控制器

主机nginx一般nginx做主机反向代理(网关)有以下配置...

如何用redis实现注册中心

一句话总结使用Redis实现注册中心:服务注册...

爱可可老师24小时热门分享(2020.5.10)

No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...

Apportable:拯救程序员,IOS一秒变安卓

摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...

JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透

以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...

3月26日更新 快速施法自动施法可独立设置

2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...

Redis 是如何提供服务的

在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...

lua _G、_VERSION使用

到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...

China&#39;s top diplomat to chair third China-Pacific Island countries foreign ministers&#39; meeting

BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...

移动工作交流工具Lua推出Insights数据分析产品

Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...

Redis 7新武器:用Redis Stack实现向量搜索的极限压测

当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...

Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求

重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...