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

常见的MySQL升级方式

image-20240408234313132

说明:数据库服务升级时,不管哪个方式升级,都应该先做好数据备份,方便升级失败的回退。

升级前准备

  1. 升级是一件风险极高的任务,备份重于一切。

  2. 了解新版本变更的信息(哪些不再兼容,不再支持哪些功能)

数据库服务升级注意事项

  • 仅支持在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中的函数,可以实现数据库服务升级的预检查功能==

  1. 下载对应目标版本MySQL8.xxmysql shell工具

    image-20240618205517254


    image-20240618205805026

  2. 安装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 -
    
  3. 升级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()" 
    

    image-20240618211828583

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)