爱可生 MySQL DBA 团队成员, Oracle 10g OCM,MySQL 5.7 OCP, 擅长数据库性能问题诊断, 事务与锁问题的分析等, 负责处理客户 MySQL 及我司自研 DMP 平台日常运维中的问题, 对开源数据库相关技术非常感兴趣.
本文关键字: 升级, Windows, 账号管理
背景
最近有去某客户那里支持 MySQL 实例升级, 他们的实例版本比较多, 有 5.5,5.6,5.7, 外加各种小版本, 平台也很多, 有 Linux,Windows. 对于 Unix/Linux 平台的 MySQL 版本升级, 大家可能再熟悉不过了, 但对于 Windows 平台的, 可能接触地较少. 由于项目上有需求, 自己也在 Windows 环境上测试了一把, 有了些心得, 想跟大家分享一些经验, 于是有了本文. 这里主要是针对比较常见的 5.6 到 5.7 的升级.
限制
MySQL 官方提供了 2 种介质的升级方式: 一种是 MySQL Installer 的方式(需要下载 MSI 可执行程序, 进行图形化安装), 另一种则是 noinstall zip 包的方式(就是我们熟悉的绿色软件, 解压即用的那种, 当然 MySQL 作为数据库软件, 也没傻瓜到那种程度, 还是需要一些额外操作的), 推荐使用第 2 种方式, 系统侵入性小, 方便快捷.
连续大版本的升级 (5.6 to 5.7) 不能用 MySQL Installer, 这种场景只支持 zip 方式.
社区版和企业版之间, 也不能用 MySQL Installer 升级, 需要用 zip 方式.
除了介质, 升级的方法也有 2 种: 一种是 IN-PLACE 方式(适用于数据量较大, 小版本或连续版本的升级), 另一种是逻辑方式(适用于数据量小, 跨越大版本的升级).
对于大数据库, 即便是采用 IN-PLACE 方式升级, 也可能会花费较长时间, 因为执行 mysql_upgrade 时, 默认也会对业务表进行数据转换和修复(这个问题在客户那儿也遇到了, 300G 左右的库, 有大量 MyISAM 表, 最大的单表有 40G. 修复过程其实是通过创建临时表进行重建, 而他们的磁盘性能又不好, 跑了很久都没有结束, 后来通过 -s 参数跳过对业务表的修复).
如果是 Milestone 版和 GA 版之间的升级, 也只能通过逻辑方式进行.
环境准备
虽然是在讲升级, 这里也稍微提一下 Windows 上安装实例的方法. 首先, 准备一台 Windows 主机 (我这里用的是 Windows 10), 去官网下载好 5.6.x,5.7.x for Windows 的 zip 包, 我选择了社区版的 5.6.30 和 5.7.30(最新 GA) 的包.
解压完的 zip 包 是这样的, 有点像 Linux 上的二进制包:
安装 5.6 环境
安装很简单, 最小化配置只需要把 my-default 参数中示例的几个参数前的注释符号去掉, 并配置上相应的值, 就可以启动了, 当然, 如果是生产环境, 肯定会自定义一堆参数, 此处略过.
改完后如下, 然后就可以用这个参数文件去初始化实例了:
初始化实例后, 再启动实例, 接着创建并配置 Windows 服务, 以后就可以通过启停服务对 MySQL 实例进行管理. 升级 5.6 至 5.7 这里不讨论详细的升级步骤, 与安装实例其实差不多, 主要说一下升级时要注意的点(本次测试采用 IN-PLACE 方式).
首次安装完 5.7(zip 方式)后, 出于安全性考虑, 需要设置 skip-grant-tables 进入实例, 修改 root 密码, 删除空账号(先执行 flush privileges;).
服务的创建, 删除都要用管理员身份运行 cmd 后再执行执行, 示例: mysqld install mysql5630 / mysqld remove mysql5630.
如果启动实例是用 mysqld --console 执行的, 会在屏幕输出实例启动的一些 error 日志, 一旦退出这个窗口, 实例就会终止(因此, 建议仅在首次测试实例能否正常启动时使用).
5.7 的 zip 包解压后没有 data 目录和 my.INI 配置文件, 可以将 5.6 中的 data 目录和 my.INI 拷贝过来(拷 data 前要停实例), 如果本来就已经指定在 basedir 之外的地方, 也可以直接用, 然后修改 5.7 配置文件的 datadir 与原来 5.6 的位置一致.
如果 5.6 是 zip 安装, 5.7 也是 zip 安装, 并且 5.7 解压到 5.6 的目录之外, 建议修改环境变量后先执行 MySQL -V, 检查其是否被正确地配置了(官方推荐解压到同一个目录中, 这样可以不用修改环境变量).
尽量不要使用旧版的 my.cnf, 并且用 mysqld --print-defaults 检查默认参数.
升级到 5.7 后, 当执行 mysqld install mysql5730 时(添加 5.7 实例的服务), 如果报找不到 dll 动态库链接文件 MSVCR120.dll,MSVCP120.dll, 则需要下载并安装相应版本的的 Visual C++ 程序).
参考链接:
各个 dll 文件对应的 Visual C++ 版本:
安装完以后, 可以查看 dll 动态库链接文件与对应 Visual C++ 版本之间的关系:
我的环境中要正常运行 5.7.30 实例, 需要安装 Visual C++ 2012,Visual C++ 2013, 之后就可以正常创建服务.
升级排错案例
安装完 5.7.30 实例后, 创建并启动 Windows 服务:
通过 SC 启动服务后却立即停止了:
用 NET 命令也无法启动, error 日志也没有输出:
尝试删除服务再重新添加:
此时服务还没有被创建:
通过 SC 再次启动后, 服务有了, 但仍然是已停止状态:
再次删除服务后直接启动 mysqld, 在登录客户端后发现了端倪, 原来是用 5.6.30 的 mysqld 命令启动了:
立即检查 my.INI 参数, 发现参数中果然是用了 5.6.30 的路径:
停止进程, 修改参数并重新启动 5.7.30 进程和服务:
msyql5730 服务恢复正常, 不会再自动停止了:
服务端 (mysqld) 和客户端 (MySQL) 进程也运行正常:
检查数据库(注意, 此时仍然是没有 sys 库的, 因为是把 5.6 的 data 目录直接拿来启动实例的):
执行 mysql_upgrade, 重建系统库:
至此, 完成 5.6.30 to 5.7.30 的升级(是不是 so easy?).
要注意, 执行完 mysql_upgrade 后需要重启实例, 否则会报以下错误:
重启实例后, 可以正常使用了:
一个有趣的登陆测试
配置了 3 个 root 账号, 来源分别为 ::1,127.0.0.1',localhost.
在账号密码都不输入的情况下, Windows 默认会用 ODBC@localhost 这个用户连接.
在加上 -uroot 后, 会优先使用 root@'::1' 这个账号来连接, 用户仍然使用的是 root@localhost.
把 root@'::1' 账号删除后, 会使用 root@localhost 的账号连接.
把 root@localhost 账号也删除后, 默认不会使用 root@127.0.0.1 的账号连接, 除非指定了 -h127.0.0.1.
在 Windows 中, 无论是 ::1,localhost 还是 127.0.0.1, 哪怕是使用 -S 进行连接, 也都是 TCP/IP 连接.
- MySQL> select user,host from MySQL.user;
- +---------------+-------------+
- | user | host |
- +---------------+-------------+
- | root | 10.186.64.% |
- | root | 127.0.0.1 |
- | root | ::1 |
- | MySQL.session | localhost |
- | MySQL.sys | localhost |
- | root | localhost |
- +---------------+-------------+
- 6 rows in set (0.00 sec)
- MySQL> exit
- Bye
- C:\Users\Administrator>MySQL
- ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: NO)
- C:\Users\Administrator>MySQL -uroot
- ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
- C:\Users\Administrator>MySQL -uroot -p
- Enter password: ********
- Welcome to the MySQL monitor. Commands end with ; or \g.
- Your MySQL connection id is 7
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
- Oracle is a registered trademark of Oracle Corporation and/or its
- affiliates. Other names may be trademarks of their respective
- owners.
- Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
- MySQL> select current_user(),user();
- +----------------+----------------+
- | current_user() | user() |
- +----------------+----------------+
- | root@::1 | root@localhost |
- +----------------+----------------+
- 1 row in set (0.00 sec)
- MySQL> drop user root@'::1';
- Query OK, 0 rows affected (0.06 sec)
- MySQL> exit
- Bye
- C:\Users\Administrator>MySQL -uroot -p
- Enter password: ********
- Welcome to the MySQL monitor. Commands end with ; or \g.
- Your MySQL connection id is 8
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
- Oracle is a registered trademark of Oracle Corporation and/or its
- affiliates. Other names may be trademarks of their respective
- owners.
- Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
- MySQL> select current_user(),user();
- +----------------+----------------+
- | current_user() | user() |
- +----------------+----------------+
- | root@localhost | root@localhost |
- +----------------+----------------+
- 1 row in set (0.02 sec)
- MySQL> drop user root@localhost;
- Query OK, 0 rows affected (0.03 sec)
- MySQL> exit
- Bye
- C:\Users\Administrator>MySQL -uroot -p
- Enter password: ********
- ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
- C:\Users\Administrator>MySQL -uroot -p -h127.0.0.1
- Enter password: ********
- Welcome to the MySQL monitor. Commands end with ; or \g.
- Your MySQL connection id is 10
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
- Oracle is a registered trademark of Oracle Corporation and/or its
- affiliates. Other names may be trademarks of their respective
- owners.
- Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
- MySQL> select current_user(),user();
- +----------------+----------------+
- | current_user() | user() |
- +----------------+----------------+
- | root@127.0.0.1 | root@localhost |
- +----------------+----------------+
- 1 row in set (0.00 sec)
- MySQL> \s
- --------------
- MySQL Ver 14.14 Distrib 5.7.30, for Win64 (x86_64)
- Connection id: 10
- Current database:
- Current user: root@localhost
- SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
- Using delimiter: ;
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Protocol version: 10
- Connection: 127.0.0.1 via TCP/IP
- Server characterset: latin1
- Db characterset: latin1
- Client characterset: gbk
- Conn. characterset: gbk
- TCP port: 3306
- Uptime: 6 hours 41 min 40 sec
- Threads: 1 Questions: 26 Slow queries: 0 Opens: 123 Flush tables: 1 Open tables: 116 Queries per second avg: 0.001
- --------------
- MySQL> show variables like 'socket';
- +-----------------------------------------+-------+
- | Variable_name | Value |
- +-----------------------------------------+-------+
- | socket | MySQL |
- +-----------------------------------------+-------+
- 3 rows in set, 1 warning (0.01 sec)
- MySQL> exit
- Bye
- C:\Users\Administrator>MySQL -uroot -p -S MySQL
- Enter password: ********
- Welcome to the MySQL monitor. Commands end with ; or \g.
- Your MySQL connection id is 16
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
- Oracle is a registered trademark of Oracle Corporation and/or its
- affiliates. Other names may be trademarks of their respective
- owners.
- Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
- MySQL> \s
- --------------
- MySQL Ver 14.14 Distrib 5.7.30, for Win64 (x86_64)
- Connection id: 16
- Current database:
- Current user: root@localhost
- SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
- Using delimiter: ;
- Server version: 5.7.30-log MySQL Community Server (GPL)
- Protocol version: 10
- Connection: localhost via TCP/IP
- Server characterset: latin1
- Db characterset: latin1
- Client characterset: gbk
- Conn. characterset: gbk
- TCP port: 3306
- Uptime: 7 hours 6 min 23 sec
- Threads: 1 Questions: 63 Slow queries: 0 Opens: 137 Flush tables: 1 Open tables: 130 Queries per second avg: 0.002
- --------------
升级步骤汇总
最后, 再把升级的各个步骤罗列一遍:
1. 下载 5.7.30 的 zip 包并解压到新的目录.
2. 安装 Visual C++ 2012/2013(或更多版本).
3. 停应用, 停止 5.6 实例(可以通过停服务来操作, 停止服务前建议记录一下 GTID 或 binlog file 和 position 位置), 删除服务.
4. 备份一份 5.6 实例的 datadir, 包括 binlog(整个目录 copy 到别的目录存放).
5. 拷贝 5.6 实例的 datadir 和 my.INI 到 5.7 实例 basedir 目录, 调整并优化参数值(注意要确保路径一致, 确认已开启 5.7 新特性相关参数, 如增强半同步, MTS 等).
6. 修改系统环境变量, 把可执行路径指向 5.7 实例的 basedir/bin.
7. 启动 5.7 实例, 创建服务并启动.
8. 验证服务端, 客户端版本是否正确.
9. 确认无误后, 执行 mysql_upgrade 升级数据字典(会升级系统库: MySQL,ps,sys, 没有会重建).
10. 重启实例.
11. 再次校验 5.7 的参数, 尽量保持与 5.6 的兼容, 尤其要注意 sql_mode 的默认值对业务的影响.
12. 清理 5.6 实例的 basedir 和 datadir 目录(可选).
13. 如果是主从环境, 还要考虑 slave_net_timeout 参数默认值改变带来的影响(主库 error 日志中出现 "ER_RPL_ZOMBIE_ENCOUNTERED" 的报错). 在 5.7.7 以前, 该参数默认是 3600s, 之后改为了 60s, 需要重新执行 change master to 语句, 并且显式指定 master_heartbeat_period=xx, 因为从 5.7.4 开始, 只有执行 reset slave 才能将其重置为默认值(slave_net_timeout 值的一半). 另外提一句, 也是从 5.7.4 开始, 执行 change master to 语句时, 可以不用先停止复制线程了.
参考链接:
总结
本文主要阐述了如何优雅地通过 ZIP&IN-PLACE 方式在 Windows 服务器上将 MySQL 5.6 实例升级到 5.7. 对 MySQL 官方提供的一些升级方式和相关限制做了说明. 通过一个实际的升级案例来展示如何在升级过程中排查错误. 演示了一个关于账号登陆的小测试, 要注意区分账号的来源部分, current_user(),user() 之间的差别, 前者是 MySQL.user 表中创建的账号, 后者是当前操作系统的登录用户. 最后对整个升级步骤做了总结, 罗列了一些升级时的注意点.
参考链接:
来源: https://segmentfault.com/a/1190000023238250