MySQL5.7升级到MySQL8全过程指导总结
wptr33 2025-01-20 17:03 27 浏览
概述
不知不觉,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版本升级还是要小心的。真实环境建议先升级从库,验证无误后再逐步对主库进行升级。
相关推荐
- MySQL进阶五之自动读写分离mysql-proxy
-
自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...
- 3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?
-
引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...
- 一文由浅入深带你完全掌握MySQL的锁机制原理与应用
-
本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...
- 验证Mysql中联合索引的最左匹配原则
-
后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...
- MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)
-
目录1.索引基础...
- 你会看 MySQL 的执行计划(EXPLAIN)吗?
-
SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...
- MySQL 从入门到精通(四)之索引结构
-
索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...
- mysql总结——面试中最常问到的知识点
-
mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...
- mysql总结——面试中最常问到的知识点(2)
-
首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...
- MySQL基础全知全解!超详细无废话!轻松上手~
-
本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...
- 深入剖析 MySQL 中的锁机制原理_mysql 锁详解
-
在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...
- Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析
-
引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...
- MySQL基础篇:DQL数据查询操作_mysql 查
-
一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...
- MySql:索引的基本使用_mysql索引的使用和原理
-
一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
如何将AI助手接入微信(打开ai手机助手)
-
redission YYDS spring boot redission 使用
-
SparkSQL——DataFrame的创建与使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)