MySQL升级的实质是对数据字典的升级,数据字典有:sys、mysql、information_schema、performance_schema 。
常见的MySQL升级方式

说明:数据库服务升级时,不管哪个方式升级,都应该先做好数据备份,方便升级失败的回退。
升级前准备
-
升级是一件风险极高的任务,备份重于一切。
-
了解新版本变更的信息(哪些不再兼容,不再支持哪些功能)
数据库服务升级注意事项
- 仅支持在GA(General Availability)版本之间进行升级
- 支持从数据库5.6到5.7再到8.0,跨版本升级,但是需要先将5.6升级到最新小版本,在进行跨版本升级
- 需要提前考虑好版本回退的方案,最好升级前做好数据备份(特别是向8.0版本升级)
- 确认新版本是否有重大变更
- 注意 SQL mode 的变化,比如:MySQL5.7发生了SQL mode的变化,对不再支持的SQL mode,部分SQL会跑不通,可以清空SQL mode,跑完之后在设置SQL mode。
- 升级成功后,确认业务SQL是否可以跑通,程序层是否都正常
- 在升级完成之后,一定要在测试时使用和线上版本相同的程序,测试是否存在问题。
- 存储引擎的变化,比如:在未来的5.8版本,不再支持myisam 引擎。
- 注意字符集的乱码问题
- 升级过程中多次启动建议加上
--skip-grant-tables和--skip-networking参数,来保证没有任何的应用连接,让升级过程更加安全。
数据库服务官方参考资料:https://dev.mysql.com/doc/refman/8.0/en/upgrade-paths.html
升级过程规划(Inplace)
- 数据库服务数据备份保存(可以采用热备和冷备两种方案,冷备是需要停止业务后备份,热备是无需停止业务备份)
- 数据库服务最新程序安装(最新版本数据库服务安装过程时,无需停止原有数据库旧版服务)
- 数据库服务原有程序关闭(网站显示维护页面)
- 数据库服务最新程序启动(加载原有程序数据实现挂库升级,并采用跳过授权表和跳过网络方式启动)
- 数据库服务升级数据结构(数据库服务升级程序后,还需要升级数据系统结构信息,因此升级时间和数据量无关)
- 数据库服务可以正常重启(数据库服务升级完毕后,确认数据库服务是可以正常完成重启操作)
- 数据库服务功能测试验证(反复核实验证与数据库服务相关的各项功能是否正常)
- 数据库服务升级工作完毕(取消网站维护页面,恢复正常网站线上运营业务)
MySQL升级实战
实战一:演示5.6.48 ->5.7.30 本地升级
1. 准备升级前模拟测试数据
mysql -u root -e "
CREATE DATABASE IF NOT EXISTS my_test_db;
USE my_test_db;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
INSERT INTO users (name, email) VALUES
('Alice', '[email protected]'),
('Bob', '[email protected]'),
('Charlie', '[email protected]');
"
2. 备份数据库
cp -a /data/mysql /data/mysql.bak
mysqldump -u root -p --all-databases > all-data-$(date +%F).sql
3. 安装新版本的数据库
curl -Lo /usr/local/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz -C -
3. 停止低版本数据库
systemctl stop mysql && systemctl stop mysql && ss -tunlp
4. 新版本数据库相关配置
cd /usr/local/
tar xf mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
rm -rf mysql # 删除之前软连接
ln -s mysql-5.7.30-linux-glibc2.12-x86_64 mysql
echo 'export PATH="/usr/local/mysql/bin:$PATH"' > /etc/profile.d/mysql.sh
source /etc/profile.d/mysql.sh
mysql -V
install -d /var/log/mysql/
touch /var/log/mysql/error.log
chown mysql. /var/log/mysql/ -R
编辑旧版本my.cnf文件
cat >/data/mysql/my.cnf<<EOF
[client]
port=3306
socket=/tmp/mysql.sock
[mysql]
default-character-set=utf8
[mysqld_safe]
socket=/tmp/mysql.sock
nice=0
[mysqld]
user=mysql
socket=/tmp/mysql.sock
port=3306
basedir=/usr/local/mysql
datadir=/data/mysql # 找到之前数据
tmpdir=/tmp
lc-messages-dir=/usr/share/mysql
character-set-server=utf8
explicit_defaults_for_timestamp
bind-address=127.0.0.1
log-error=/var/log/mysql/error.log
symbolic-links=0
EOF
5. 启动新版本数据库
cat >/usr/lib/systemd/system/mysql.service <<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/my.cnf
LimitNOFILE=5000
EOF
/usr/local/mysql/bin/mysql_upgrade -S /tmp/mysql.sock --force
systemctl enable mysql && systemctl restart mysql && sleep 3 && ss -tunlp
6. 检查数据是否完整
mysql> show tables;
+----------------------+
| Tables_in_my_test_db |
+----------------------+
| users |
+----------------------+
1 row in set (0.00 sec)
实战一:演示5.7.30 ->5.8.37 本地升级
1. 数据库服务升级版本确认
在早期升级数据服务程序时,很多企业环境升级过程,都需要有前期的模拟测试环节,并且测试环境的版本升级兼容性需要盲猜;
根本无法通过当前环境的数据库服务版本,来核实确认是否可以进行升级的兼容性版本信息,从而有效避免升级后带来的问题;
而在数据库服务8.0之后,提供了一个mysqlshell命令功能,利用命令功能中的特殊函数,可以在升级前对当前环境版本进行验证;
==简而言之:就是数据库服务8.0之后,利用mysqlshell中的函数,可以实现数据库服务升级的预检查功能==
-
下载对应目标版本
MySQL8.xx的mysql shell工具

-
安装MySQL shell
curl -Lo /usr/local/mysql-shell-8.0.37-linux-glibc2.17-x86-64bit.tar.gz https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.37-linux-glibc2.17-x86-64bit.tar.gz -C - -
升级MySQL 8.xx高版本预检查
cd /usr/local tar -xf mysql-shell-8.0.37-linux-glibc2.17-x86-64bit.tar.gz cd mysql-shell-8.0.37-linux-glibc2.17-x86-64bit/bin/ # 指定连接的旧版服务的用户名与密码,并根据网络白名单列表和端口建立连接,实现测试 ./mysqlsh root:''@localhost:3306 -e "util.checkForServerUpgrade()"
2. 准备升级前模拟测试数据
mysql -u root -e "
CREATE DATABASE IF NOT EXISTS my_test_db;
USE my_test_db;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
INSERT INTO users (name, email) VALUES
('Alice', '[email protected]'),
('Bob', '[email protected]'),
('Charlie', '[email protected]');
"
3. 备份数据库
cp -a /data/mysql /data/mysql.bak
mysqldump -u root -p --all-databases > all-data-$(date +%F).sql
4. 安装新版本的数据库
curl -Lo /usr/local/mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz -C -
5. 停止低版本数据库
systemctl stop mysql && systemctl stop mysql && ss -tunlp
6. 新版本数据库相关配置
cd /usr/local/
tar xf mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz
rm -rf mysql # 删除之前软连接
ln -s mysql-8.0.37-linux-glibc2.17-x86_64 mysql
echo 'export PATH="/usr/local/mysql/bin:$PATH"' > /etc/profile.d/mysql.sh
source /etc/profile.d/mysql.sh
mysql -V
install -d /var/log/mysql/
touch /var/log/mysql/error.log
chown mysql. /var/log/mysql/ -R
编辑旧版本my.cnf文件
cat >/data/mysql/my.cnf<<EOF
[client]
port=3306
socket=/tmp/mysql.sock
[mysql]
default-character-set=utf8
[mysqld_safe]
socket=/tmp/mysql.sock
nice=0
[mysqld]
user=mysql
socket=/tmp/mysql.sock
port=3306
basedir=/usr/local/mysql
datadir=/data/mysql # 找到之前数据
tmpdir=/tmp
lc-messages-dir=/usr/share/mysql
character-set-server=utf8
explicit_defaults_for_timestamp
bind-address=127.0.0.1
log-error=/var/log/mysql/error.log
symbolic-links=0
EOF
7. 启动新版本数据库
cat >/usr/lib/systemd/system/mysql.service <<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/my.cnf
LimitNOFILE=5000
EOF
systemctl enable mysql && systemctl restart mysql && sleep 3 && ss -tunlp
说明:在数据库版本从5.7升级到8.0时,可以省略mysql_upgrade升级改变数据结构信息操作,因为8.0版本会自动完成此步骤
8. 检查数据是否完整
mysql> show tables;
+----------------------+
| Tables_in_my_test_db |
+----------------------+
| users |
+----------------------+
1 row in set (0.00 sec)