相关推荐recommended
MySQL大小版本升级步骤
作者:mmseoamin日期:2023-12-20

MySQL8.0的一些变化

在升级到8.0之前需要充分考虑版本变化带来的使用兼容性的问题,其中不兼容的部分需要特别关注,建议升级大版本前做充分的测试。下面简单介绍下MySQL8.0的部分变化。

  • 数据字典

    不同于之前的版本将字典数据存储在元数据文件和非事务系统表中,MySQL8.0将包含数据库对象的全局数据字典存储在事务表中。在使用上如果设置了innodb_read_only 参数会导致所有表的创建、删除、analyze、修改表引擎操作无法执行。CREATE TABLE dst_tbl LIKE src_tbl 要求src_tbl必须是base table。mysqldump和mysqlpump不会导出information_schema,不会导出MySQL Schema中数据字典表,需导出存储过程和事件需指定–routines和–events选项,并且用户需要全局select权限。

    • Authentication Plugin

      MySQL8.0将默认身份验证插件从mysql_native_password变更为caching_sha2_password,客户端需要验证现有版本是否支持。

      • Configuration Changes
      • MySQL8.0开始只有InnoDB和NDB引擎支持分区表,升级前需确保不存在非InnoDB引擎的分区表。
      • 部分error code被启用,详见https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals
      • 默认字符集从latin1变更为utf8mb4,默认排序规则为utf8mb4_0900_ai_ci。注意这可能会导致新旧数据库对象的字符集不一致,造成隐式类型转换的问题。
      • 8.0.11版本开始,如使用与初始化配置不同的lower_case_table_names值启动数据库时会报错。
        [ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('0') and data dictionary ('1').
        [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
        [ERROR] [MY-010119] [Server] Aborting
        
        • Server Changes
        • 8.0.11开始部分账户管理功能被删除,如Grant命令修改用户非权限特性,NO_AUTO_CREATE_USER模式,PASSWORD() 函数和 old_passwords 系统变量。
        • 8.0.11开始删除了部分兼容 SQL 模式:DB2、MAXDB、MSSQL、MYSQL323、MYSQL40、ORACLE、POSTGRESQL、NO_FIELD_OPTIONS、NO_KEY_OPTIONS、NO_TABLE_OPTIONS。
        • 从 MySQL 8.0.3 开始,空间数据类型允许 SRID 属性,以明确指示存储在列中的值的空间参考系统 (SRS)。并删除了部分非ST_前缀的空间函数。详见https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals在线切换binlog format增加了更多限制。
        • InnoDB Changes
          • information_Schema中,innodb_sys_% 改名为 innodb_%
          • zlib库版本从1.2.3升级到1.2.11。
          • 只读变量innodb_directories应该包含file-per-table和绝对路径创建的通用表空间文件的路径。
          • undo日志从系统表空间移出。默认会在innodb_undo_directory指定位置(未指定则在data dir)创建两个undo表空间。从5.7升级到8.0时innodb-fast-shutdown需设置成0。
          • 8.0.17开始在创建表空间时,路径不允许含 circular directory reference(/…/);升级前可以查询INFORMATION_SCHEMA.INNODB_DATAFILES表检查表空间路径。
            mysql> CREATE TABLESPACE ts11 ADD DATAFILE '/data/mysql/log/test/../ts11.ibd';
            ERROR 3121 (HY000): The ADD DATAFILE filepath cannot contain circular directory references.
            mysql> CREATE TABLESPACE ts11 ADD DATAFILE '/data/mysql/log/ts11.ibd';
            Query OK, 0 rows affected (10.02 sec)
            
            • SQL change
              • group by 不再支持DESC和ASC,GROUP BY {col_name | expr | position}, … [WITH ROLLUP]]
              • 保留字变更。https://dev.mysql.com/doc/refman/8.0/en/keywords.html
              • 升级后建议测试optimizer hints,在8.0中部分hint可能不再适用。

                部分默认配置的变化。

                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来完成该步骤的升级。

                    升级建议

                    • 支持从MySQL5.7升级到8.0,注意仅支持GA版本之间的升级。
                    • 不支持跨大版本的升级,如从5.6升级到8.0是不支持的。
                    • 建议升级大版本前先升级到当前版本的最近小版本,如5.7先升级到5.7.35后再升级到8.0。
                    • 在大版本内部GA的小版本可以直接升级,如从8.0.9直接升级到8.0.26。

                      MySQL 8.0 中的更改:了解升级前应注意的更改。某些更改可能需要执行操作。

                      MySQL 8.0 中的新增功能:了解已弃用和已删除的功能。如果您使用其中任何一个功能,升级可能需要更改这些功能。

                      MySQL 8.0 中添加、弃用或删除的服务器和状态变量和选项”。如果使用已弃用或删除的变量,则升级可能需要更改配置。

                      建议先升级到最新版本,然后再升级到下一个版本。例如,在升级到 MySQL 8.0 之前升级到最新的 MySQL 5.7 版本。不支持跳过版本的升级。例如,不支持直接从 MySQL 5.6 升级到 8.0。

                      升级方式

                      升级方式有2种,in-place升级和logical升级

                      in-place升级

                      关闭现有版本MySQL,将二进制或包替换成新版本并在现有数据目录上启动MySQL并执行升级任务的方式,称为in-place升级。升级过程分为以下几步:

                      1. 完成升级前检查,并处理不合规问题。
                      2. 如果使用了XA事务,升级前通过命令xa recover未提交XA事务,并使用xa commit或xa rollback命令提交或回滚。
                      3. 如当前版本低于5.7.11且使用了加密表空间,升级前轮换keyring的master keyALTER INSTANCE ROTATE INNODB MASTER KEY。
                      4. 将innodb_fast_shutdown改为0或1。
                      5. 关闭现版本MySQL。
                      6. 升级MySQL二进制文件或软件包。
                      7. 在现有数据目录上启动新版本MySQL。如果有加密的 InnoDB 表空间,请使用 --early-plugin-load选项加载keyring插件。如升级失败请删除redolog,启动5.7版本并修复错误,设置innodb_fast_shutdown为0后关闭MySQL。再使用8.0版本MySQL启动。
                      8. 如目标版本小于8.0.16,MySQL启动后还需执行mysql_upgrade后重启MySQL。MySQL 8.0.16 开始,MySQL 不推荐使用mysql_upgrade。取而代之的是server upgrade的升级方式,好处有:1. 升级速度更快 2. 升级更简单 3. 安全性更好 4. 减少升级步骤,方便自动化 5. 不需要重启 MySQL 6. 即插即用

                      logical升级

                      逻辑升级是指使用逻辑备份从旧版本MySQL中导出数据,安装新版本MySQL并导入数据的升级方式。由于可能存在的不兼容问题会导致导入失败,导出前需要做升级前检查,导入前可能还需要对备份文件进行修改。

                      升级步骤如下:

                      1. 对旧版本数据做全量导出。
                      mysqldump -u root -p --add-drop-table --routines --events --all-databases --force > data-for-upgrade.sql
                      
                      1. 关闭当前版本数据库。
                      2. 安装8.0版本数据库并初始化(从error log中获取’root’@'localhost’用户初始密码)。
                      3. 在新的数据目录中启动MySQL8.0,并重置初始密码。
                      4. 将备份文件导入mysql -u root -p --force < data-for-upgrade.sql。如导出文件包含系统表,则不建议导入时开启GTID(gtid_mode=ON)。
                      5. 执行剩余的升级操作。目标版本大于8.0.16时需重启服务器,启动时使用–upgrade=FORCE参数。8.0.16之前的版本先执行mysql_upgrade再重启MySQL。
                      #8.0.16以后的版本
                      mysqladmin -u root -p shutdown
                      mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir --upgrade=FORCE &
                      #8.0.16之前的版本
                      mysql_upgrade -u root -p
                      mysqladmin -u root -p shutdown
                      mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir &
                      #确认升级成功后,mysql schema中两张不再使用的表可以自行清理
                      DROP TABLE mysql.event;
                      DROP TABLE mysql.proc;
                      

                      升级过程包含哪些操作

                      升级MySQL时需要对现版本MySQL中的数据字典和元数据等进行更新。在MySQL Schema中需更新数据字典表和系统表,在其他Schema中需要更新一些内置的MySQL持有的表,如performance_Schema、information_schema和sys schema等。

                      升级过程大致分为两个部分,升级数据字典和升级服务。

                      • 升级数据字典包括升级MySQL Schema中的数据字典表,以及performance schema,information_schema。升级数据字典表时,如当前版本低于期望版本,则服务器将创建新版本的数据字典表并将持久化的元数据拷贝到新表,在新旧表做原子性替换后重新初始化数据字典。服务器启动后会按需执行,可以使用 --upgrade=NONE(8.0.16以后)或–no-dd-upgrade (8.0.16之前)参数启动MySQL,阻止数据字典表的升级。
                      • 升级服务即其余升级任务,包括MySQL Schema中的非数据字典表,sys schema和用户schema。

                        在8.0.16之前需使用mysql_upgrade执行除数据字典表外的其余升级步骤,在8.0.16以后该步骤由MySQL服务在启动后执行。MySQL服务会根据升级到的版本以及in-place或logical升级的指示确定是否执行所有的升级步骤。

                        8.0.16开始启动参数–upgrade= 控制MySQL服务在启动时执行自动升级的动作。

                        --upgrade=AUTO MySQL升级所有过时的内容
                        --upgrade=NONE MySQL跳过升级步骤,可能会导致报错
                        --upgrade=MINIMAL MySQL在必要时升级数据字典表,information_schema和information_schema。这可能会导致部分功能不能正常使用,例如MGR。
                        --upgrade=FORCE MySQL会升级所有的内容,这会检查所有schema的所有对象,导致MySQL需要更长的时间启动。此模式下MySQL会重新创建系统表 if they are missing。
                        

                        8.0.16前和8.0.16后升级对比

                        MySQL 8.0.16 开始,MySQL 不推荐使用mysql_upgrade。取而代之的是server upgrade的升级方式。

                        变更升级方式原因

                        1. 升级速度更快 2. 升级更简单 3. 安全性更好 4. 减少升级步骤,方便自动化 5. 不需要重启 MySQL 6. 即插即用

                        新旧方式升级流程对比

                        在 MySQL 8.0.16 之前

                        MySQL大小版本升级步骤,image.png,第1张

                        1. 关闭 MySQL,替换新的二进制 MySQL
                        2. 启动 MySQL,让服务器升级 DD(数据字典)表
                        3. 运行 mysql_upgrade,更新系统表和用户表
                        4. 加载新的帮助表
                        5. 重启 MySQL

                        从 MySQL 8.0.16 开始

                        MySQL大小版本升级步骤,外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传,第2张

                        1. 关闭 MySQL,替换新的二进制 MySQL
                        2. 启动 MySQL,升级 DD(数据字典)表和系统表、用户表和帮助表

                          升级的时间和操作都会大幅度缩短,操作步骤也减少了很多,更方便了用户。

                        关于 MySQL 8.0.16 的新的升级方式

                        在 mysqld 额外添加了一个新的选项 --upgrade。可选值为 NONE,AUTO,MINIMAL,FORCE。

                        --使用方法
                        /usr/local/mysql/bin/mysqld --upgrade=NONE
                        参数解释:
                        NONE:不尝试进行升级
                        AUTO:默认选项,MySQL 进行数据字典升级和服务升级
                        MINIMAL:仅升级数据字典
                        FORCE:强制升级,类似旧的 mysql_upgrade –force
                        

                        MySQL 8.0.16 新的升级方式,总体来说分为2个步骤。

                        1. 升级数据字典(DD)
                        2. 服务器升级:升级 MySQL 系统表、升级用户表、升级 sys 表、升级帮助更新表

                          可能出现的问题:

                        3. 升级数据字典:原子性操作。如果操作失败,则根据目录可以回滚回来。

                          2.升级系统表、用户表:可以从备份还原中恢复。

                        构建测试数据

                        --创建数据库并批量插入数据
                        CREATE DATABASE IF NOT EXISTS pijiake;
                        CREATE TABLE IF NOT EXISTS `pijiake`.`test_user`(
                           `id` INT UNSIGNED AUTO_INCREMENT,
                           `name` VARCHAR(255) NOT NULL,
                           `age` INT(11) NOT NULL,
                           `sex` VARCHAR(16),
                           PRIMARY KEY ( `id` )
                        )ENGINE=InnoDB DEFAULT CHARSET=utf8;
                        INSERT INTO  `pijiake`.`test_user`
                        (name, age, sex)
                        VALUES 
                        ('张三', 18, '男'),
                        ('赵四', 17, '女'),
                        ('刘五', 16, '男'),
                        ('周七', 19, '女');
                        select * from `pijiake`.`test_user`;
                        CREATE DATABASE IF NOT EXISTS xiaomiaoao;
                        CREATE TABLE IF NOT EXISTS `xiaomiaoao`.`test_user`(
                           `id` INT UNSIGNED AUTO_INCREMENT,
                           `name` VARCHAR(255) NOT NULL,
                           `age` INT(11) NOT NULL,
                           `sex` VARCHAR(16),
                           PRIMARY KEY ( `id` )
                        )ENGINE=InnoDB DEFAULT CHARSET=utf8;
                        INSERT INTO `xiaomiaoao`.`test_user` 
                        (name, age, sex)
                        VALUES 
                        ('张三', 18, '男'),
                        ('赵四', 17, '女'),
                        ('刘五', 16, '男'),
                        ('周七', 19, '女');
                        select * from `xiaomiaoao`.`test_user`;
                        

                        升级前的检查

                        在执行升级操作前需要做一些检查工作,确认准备工作是否就绪,避免升级过程中出现异常。

                        • 可以使用MySQL Shell使用util.checkForServerUpgrade进行检查,返回内容包括不符合迁移要求的问题,error的问题需要迁移前修改。

                          下面的例子中就存在一个不兼容的问题,ymh.t1表是一个MyISAM引擎的分区表,需将该表引擎调整为innodb后方可升级。

                           MySQL  JS > util.checkForServerUpgrade('root@127.0.0.1:3307', {"password":"XXXX", "targetVersion":"8.0.26", "configPath":"/etc/my3307.cnf"})
                          The MySQL server at 127.0.0.1:3307, version 5.7.23-log - MySQL Community Server
                          (GPL), will now be checked for compatibility issues for upgrade to MySQL
                          8.0.26...
                          1) Usage of old temporal type
                            No issues found
                          2) Usage of db objects with names conflicting with new reserved keywords
                            No issues found
                          3) Usage of utf8mb3 charset
                            No issues found
                          4) Table names in the mysql schema conflicting with new tables in 8.0
                            No issues found
                          5) Partitioned tables using engines with non native partitioning
                            Error: In MySQL 8.0 storage engine is responsible for providing its own
                              partitioning handler, and the MySQL server no longer provides generic
                              partitioning support. InnoDB and NDB are the only storage engines that
                              provide a native partitioning handler that is supported in MySQL 8.0. A
                              partitioned table using any other storage engine must be altered—either to
                              convert it to InnoDB or NDB, or to remove its partitioning—before upgrading
                              the server, else it cannot be used afterwards.
                            More information:
                              https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-configuration-changes
                            ymh.t1 - MyISAM engine does not support native partitioning
                          6) Foreign key constraint names longer than 64 characters
                            No issues found
                          7) Usage of obsolete MAXDB sql_mode flag
                            No issues found
                          8) Usage of obsolete sql_mode flags
                            No issues found
                          9) ENUM/SET column definitions containing elements longer than 255 characters
                            No issues found
                          10) Usage of partitioned tables in shared tablespaces
                            No issues found
                          11) Circular directory references in tablespace data file paths
                            No issues found
                          12) Usage of removed functions
                            No issues found
                          13) Usage of removed GROUP BY ASC/DESC syntax
                            No issues found
                          14) Removed system variables for error logging to the system log configuration
                            No issues found
                          15) Removed system variables
                            No issues found
                          16) System variables with new default values
                            Warning: Following system variables that are not defined in your
                              configuration file will have new default values. Please review if you rely on
                              their current values and if so define them before performing upgrade.
                            More information:
                              https://mysqlserverteam.com/new-defaults-in-mysql-8-0/
                            back_log - default value will change
                            collation_server - default value will change from latin1_swedish_ci to
                              utf8mb4_0900_ai_ci
                            event_scheduler - default value will change from OFF to ON
                            explicit_defaults_for_timestamp - default value will change from OFF to ON
                            innodb_autoinc_lock_mode - default value will change from 1 (consecutive) to
                              2 (interleaved)
                            innodb_max_dirty_pages_pct_lwm - default value will change from_0 (%) to 10
                              (%)
                            innodb_undo_log_truncate - default value will change from OFF to ON
                            innodb_undo_tablespaces - default value will change from 0 to 2
                            log_error_verbosity - default value will change from 3 (Notes) to 2 (Warning)
                            max_error_count - default value will change from 64 to 1024
                            optimizer_trace_max_mem_size - default value will change from 16KB to 1MB
                            performance_schema_consumer_events_transactions_current - default value will
                              change from OFF to ON
                            performance_schema_consumer_events_transactions_history - default value will
                              change from OFF to ON
                            transaction_write_set_extraction - default value will change from OFF to
                              XXHASH64
                          17) Zero Date, Datetime, and Timestamp values
                            Warning: By default zero date/datetime/timestamp values are no longer allowed
                              in MySQL, as of 5.7.8 NO_ZERO_IN_DATE and NO_ZERO_DATE are included in
                              SQL_MODE by default. These modes should be used with strict mode as they will
                              be merged with strict mode in a future release. If you do not include these
                              modes in your SQL_MODE setting, you are able to insert
                              date/datetime/timestamp values that contain zeros. It is strongly advised to
                              replace zero values with valid ones, as they may not work correctly in the
                              future.
                            More information:
                              https://lefred.be/content/mysql-8-0-and-wrong-dates/
                            global.sql_mode - does not contain either NO_ZERO_DATE or NO_ZERO_IN_DATE
                              which allows insertion of zero dates
                            session.sql_mode -  of 1 session(s) does not contain either NO_ZERO_DATE or
                              NO_ZERO_IN_DATE which allows insertion of zero dates
                          18) Schema inconsistencies resulting from file removal or corruption
                            No issues found
                          19) Tables recognized by InnoDB that belong to a different engine
                            No issues found
                          20) Issues reported by 'check table x for upgrade' command
                            No issues found
                          21) New default authentication plugin considerations
                            Warning: The new default authentication plugin 'caching_sha2_password' offers
                              more secure password hashing than previously used 'mysql_native_password'
                              (and consequent improved client connection authentication). However, it also
                              has compatibility implications that may affect existing MySQL installations. 
                              If your MySQL installation must serve pre-8.0 clients and you encounter
                              compatibility issues after upgrading, the simplest way to address those
                              issues is to reconfigure the server to revert to the previous default
                              authentication plugin (mysql_native_password). For example, use these lines
                              in the server option file:
                              
                              [mysqld]
                              default_authentication_plugin=mysql_native_password
                              
                              However, the setting should be viewed as temporary, not as a long term or
                              permanent solution, because it causes new accounts created with the setting
                              in effect to forego the improved authentication security.
                              If you are using replication please take time to understand how the
                              authentication plugin changes may impact you.
                            More information:
                              https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-compatibility-issues
                              https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-replication
                          Errors:   1
                          Warnings: 17
                          Notices:  0
                          1 errors were found. Please correct these issues before upgrading to avoid compatibility issues.
                          #修改t1表引擎为InnoDB
                          mysql> alter table t1 engine=innodb;
                          Query OK, 0 rows affected (0.02 sec)
                          Records: 0  Duplicates: 0  Warnings: 0
                          

                          MySQL Shell的util.checkForServerUpgrade工具主要做了以下检查,当然我们也可以手动进行相关的检查。

                          • 不应存在以下问题
                            • 使用过时的数据类型和函数的表。如5.6.4之前的不支持小数点的时间格式。需在执行In-place升级前执行repair table修复。
                            • 没有孤立的.frm文件。
                            • 触发器不能缺失或空的definer或无效的creation context。

                              可执行以下命令检查上述问题:

                              mysqlcheck -u root -p --all-databases --check-upgrade
                              

                              不应存在非InnoDB或NDB引擎的分区表,如存在需变更引擎或转换成非分区表。可通过以下SQL检查:

                              SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE NOT IN ('innodb', 'ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned%';
                              
                              • 检查是否使用了8.0新增的保留字。
                              • MySQL Schema中不应存在8.0数据字典表同名的表,可用以下SQL检查:
                                SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE LOWER(TABLE_SCHEMA) = 'mysql' and LOWER(TABLE_NAME) IN ( 'catalogs', 'character_sets', 'check_constraints', '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' );
                                

                                不得有外键约束名称长度超过 64 个字符的表,如存在则删除后重建。可用以下SQL检查:

                                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);
                                
                                • sql_mode系统参数不能含前面提到弃用模式。
                                • 视图中不能有显式定义超过64个字符的列名。可查看INFORMATION_SCHEMA.VIEWS检查。
                                • 表和存储过程中单个枚举和SET列元素不能超过255个字符或1020个字节。
                                • 升级到8.0.13版本前,包括系统表空间和通用表空间在内的共享表空间中不能存在表分区。
                                  #5.7版本以下SQL检查
                                  SELECT DISTINCT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES   WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single';
                                  #8.0早期版本以下SQL检查
                                  SELECT DISTINCT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_TABLES   WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single'; 
                                  #如存在,可使用reorganize partition命令将共享表空间中的分区迁移到 file-per-table表空间
                                   ALTER TABLE $table_name REORGANIZE PARTITION $partition_name   INTO (partition_definition TABLESPACE=innodb_file_per_table);
                                  
                                  • 查询和存储过程中不能在group by子句中使用ASC或者DESC。
                                  • 不能使用8.0中不支持的功能和配置参数。https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.htmlhttps://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals
                                  • 从 MySQL 8.0.19 开始,如果lower_case_table_names=1,升级过程会检查表和模式名称以确保所有字符都是小写。如果发现表或架构名称包含大写字符,升级过程将失败并显示错误。
                                    mysql> SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != LOWER(TABLE_NAME) AND TABLE_TYPE = 'BASE TABLE';
                                    mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME != LOWER(SCHEMA_NAME);
                                    

                                    如果出现上述问题导致的升级失败,MySQL会将变更还原,这时删除redo log并重启5.7版本实例即可。注意关闭前一定设置innodb_fast_shutdown=0。

                                    版本升级案例

                                    小版本升级步骤

                                    升级需求:将8.0.26升级到8.0.33

                                    停止应用

                                    确保业务已停止,保证数据一致性

                                    --查询数据库中哪些线程正在执行
                                    show processlist;
                                    

                                    查看当前的MySQL版本

                                    select version()
                                    或
                                    mysql -V
                                    或
                                    show variables like '%version%'
                                    

                                    备份数据库

                                    逻辑备份
                                    --多个数据库备份成1个文件
                                    mysqldump -uroot -p  --databases  xiaomiaoao pijiake  > /root/all-databases2213.sql
                                    --备份test数据库
                                    mysqldump -uroot -p test > /data/mysqldb/tmp/test_exp_$(date +%F).sql 
                                    
                                    目录备份

                                    如果升级失败能更快的回退

                                    --停止数据库
                                    systemctl stop mysqld
                                    --安装目录备份
                                    cp -r /data/mysqldb/mysql /data/mysqldb/mysql_bak_`date +%F`
                                    --数据目录备份
                                    cp -r /data/mysqldb/data /data/mysqldb/data_bak_`date +%F`
                                    --配置文件备份
                                    cp /etc/my.cnf /etc/my5_bak_`date +%F`.cnf
                                    

                                    关闭正在运行的MySQL服务

                                    再次查看运行情况,确认关闭情况 Active: inactive (dead)

                                    systemctl status mysqld
                                    systemctl stop mysqld
                                    systemctl status mysqld
                                    

                                    安装新版本软件

                                    #1.安装介质上传至/opt/下
                                    #2.解压安装包
                                    tar -xvf mysql-8.0.33-el7-x86_64.tar.gz  -C /data/
                                    #4.文件夹重命名为mysql8 
                                    mv /data/mysql*  /data/mysql8033
                                    #5.更改文件夹所属
                                    chown -R mysql.mysql /data/mysql8033
                                    

                                    更改配置文件

                                    --备份原配置文件
                                    cp /etc/my.cnf /etc/my.cnf.bak_`date +%F`
                                    --更改配置文件
                                    安装目录
                                    

                                    启动数据库

                                    cd /data/mysql8033/support-files
                                    ls -l /etc/init.d/mysqld #如果该文件存在跳过第3条命令
                                    cp mysql.server /etc/init.d/mysqld  
                                    vi /etc/init.d/mysqld  #确认或更改basedir或datadir参数
                                    service mysqld start 或mysql.service start
                                    service mysqld status
                                    

                                    问题

                                    启动失败
                                    --问题描述
                                    [root@top132:/data/mysql813/mysql8/support-files]$ service mysqld start
                                    Starting MySQL........................................................................................................ ERROR! The server quit without updating PID file (/data/mysql813/data8/top132.pid).
                                    解决办法:
                                    /etc/my.cnf中的pid路径需指向basedir
                                    

                                    大版本升级步骤案例1-1:in-place升级方式

                                    升级需求:将5.7.42升级到8.0.13,以In-Place方式直接升级到MySQL8.0.13。

                                    原版本5.7.42Centos7.6 x86_64
                                    新版本8.0.13Centos7.6 x86_64

                                    关闭现有版本MySQL,将二进制或包替换成新版本并在现有数据目录上启动MySQL并执行升级任务的方式,称为in-place升级。升级过程分为以下几步:

                                    1. 完成升级前检查,并处理不合规问题。
                                    2. 如果使用了XA事务,升级前通过命令xa recover未提交XA事务,并使用xa commit或xa rollback命令提交或回滚。
                                    3. 如当前版本低于5.7.11且使用了加密表空间,升级前轮换keyring的master keyALTER INSTANCE ROTATE INNODB MASTER KEY。
                                    4. 将innodb_fast_shutdown改为0或1。
                                    5. 关闭现版本MySQL。
                                    6. 升级MySQL二进制文件或软件包。
                                    7. 在现有数据目录上启动新版本MySQL。如果有加密的 InnoDB 表空间,请使用 --early-plugin-load选项加载keyring插件。如升级失败请删除redolog,启动5.7版本并修复错误,设置innodb_fast_shutdown为0后关闭MySQL。再使用8.0版本MySQL启动。
                                    8. 如目标版本小于8.0.16,MySQL启动后还需执行mysql_upgrade后重启MySQL。

                                    一.升级前准备

                                    1.停止业务

                                    确保业务已停止,保证数据一致性

                                    --查询数据库中哪些线程正在执行
                                    show processlist;
                                    
                                    2.查看源数据库信息
                                    #查版本
                                    mysql -V 
                                    或
                                    mysql> select version();
                                    +------------+
                                    | version()  |
                                    +------------+
                                    | 5.7.42-log |
                                    +------------+
                                    1 row in set (0.00 sec)
                                    

                                    场景1:查询所有数据库的总大小

                                    --查询所有数据库的总大小
                                    use information_schema;
                                    select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES;
                                    --统计一下所有库数据量
                                    SELECT
                                    SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb
                                    FROM information_schema.TABLES; 
                                    --统计每个库大小
                                    SELECT
                                    table_schema,SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb
                                    FROM information_schema.TABLES group by table_schema;  
                                    

                                    场景2:查看指定数据库的大小

                                    use information_schema;
                                    select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES where table_schema='pijiake';
                                    

                                    场景3:记录数

                                    --查看所有数据库各容量大小
                                    select
                                    table_schema as '数据库',
                                    sum(table_rows) as '记录数',
                                    sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)',
                                    sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)'
                                    from information_schema.tables
                                    group by table_schema
                                    order by sum(data_length) desc, sum(index_length) desc;
                                    --查看所有数据库各表容量大小
                                    select
                                    table_schema as '数据库',
                                    table_name as '表名',
                                    table_rows as '记录数',
                                    truncate(data_length/1024/1024, 2) as '数据容量(MB)',
                                    truncate(index_length/1024/1024, 2) as '索引容量(MB)'
                                    from information_schema.tables
                                    order by data_length desc, index_length desc;
                                    --查看指定数据库容量大小(例:查看mysql库容量大小)
                                    select
                                    table_schema as '数据库',
                                    sum(table_rows) as '记录数',
                                    sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)',
                                    sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)'
                                    from information_schema.tables
                                    where table_schema='test'; 
                                    --查看指定数据库各表容量大小(例:查看mysql库各表容量大小)
                                    select
                                    table_schema as '数据库',
                                    table_name as '表名',
                                    table_rows as '记录数',
                                    truncate(data_length/1024/1024, 2) as '数据容量(MB)',
                                    truncate(index_length/1024/1024, 2) as '索引容量(MB)'
                                    from information_schema.tables
                                    where table_schema='test'
                                    order by data_length desc, index_length desc;
                                    
                                    3.备份数据库
                                    3.1.逻辑备份
                                    --多个数据库备份成1个文件
                                    mysqldump -uroot -p  --databases  xiaomiaoao pijiake  > /root/all-databases2213.sql
                                    --备份test数据库
                                    mysqldump -uroot -p test > /data/mysqldb/tmp/test_exp_$(date +%F).sql 
                                    
                                    3.2.目录备份

                                    如果升级失败能更快的回退

                                    --停止数据库
                                    systemctl stop mysqld
                                    --安装目录备份
                                    cp -r /data/mysqldb/mysql /data/mysqldb/mysql_bak_`date +%F`
                                    --数据目录备份
                                    cp -r /data/mysqldb/data /data/mysqldb/data_bak_`date +%F`
                                    --配置文件备份
                                    cp /etc/my.cnf /etc/my5_bak_`date +%F`.cnf
                                    
                                    4.下载并安装新版本MySQL软件
                                    #1.安装介质上传至/opt/下
                                    #2.创建目录
                                    mkdir -p /data/mysqldb813
                                    #3.解压安装包
                                    tar -xvf mysql-8.0.13-el7-x86_64.tar.gz  -C /data/mysqldb813
                                    #4.文件夹重命名为mysql8 
                                    mv /data/mysqldb813/mysql*  /data/mysqldb813/mysql813
                                    #5.更改文件夹所属
                                    chown -R mysql.mysql /data/mysqldb813
                                    
                                    5.更改配置文件

                                    因5.7版本与8.0版本参数有所不同,为了能顺利升级,需要更改部分配置参数。主要注意sql_mode、basedir、密码认证插件及字符集设置,其他参数最好还是按照原5.7的来,不需要做调整。

                                    更改/etc/my.conf配置,末尾添加关键配置

                                    #add for 8.0
                                    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                                    character-set-server = utf8
                                    collation-server = utf8_general_ci
                                    basedir = /data/mysqldb813/mysql813
                                    skip_ssl
                                    default_authentication_plugin=mysql_native_password
                                    

                                    https://blog.csdn.net/weixin_42689212/article/details/121293222

                                    二.开始升级

                                    1.关闭数据库
                                    --1.进入原5.7 mysql命令行 正确关闭数据库
                                    法1:
                                    mysqladmin -uroot -p shutdown
                                    [root@mysql]# mysql -uroot -p
                                    Enter password: 
                                    #使用mysql shell 命令util.checkForServerUpgrade('root@127.0.0.1:3307', {"password":"XXXXX", "targetVersion":"8.0.26", "configPath":"/etc/my3307.cnf"}) 检查升级到目标版本8.0.26,确认没有error级别的问题
                                    Errors:   0
                                    Warnings: 17
                                    Notices:  0
                                    #检查没有未提交的xa事务
                                    mysql> xa recover;
                                    Empty set (0.00 sec)
                                    # 确保数据都刷到硬盘上,更改成0
                                    mysql> show variables like 'innodb_fast_shutdown';
                                    +----------------------+-------+
                                    | Variable_name        | Value |
                                    +----------------------+-------+
                                    | innodb_fast_shutdown | 1     |
                                    +----------------------+-------+
                                    1 row in set (0.00 sec)
                                    mysql> set global innodb_fast_shutdown=0;
                                    Query OK, 0 rows affected (0.00 sec)
                                    mysql> show variables like 'innodb_fast_shutdown';
                                    +----------------------+-------+
                                    | Variable_name        | Value |
                                    +----------------------+-------+
                                    | innodb_fast_shutdown | 0     |
                                    +----------------------+-------+
                                    mysql> shutdown;
                                    Query OK, 0 rows affected (0.00 sec)
                                    mysql> exit
                                    #查看进程和端口后,已无输出记录,确保已停止
                                    [root@localhost mysqldb8]# ps -ef | grep mysql
                                    root       6330   6202  0 07:35 pts/0    00:00:00 mysql -uroot -p -P2213 test
                                    root       6466   6202  0 09:18 pts/0    00:00:00 mysql -uroot -p
                                    root       6522   6293  0 09:58 pts/1    00:00:00 mysql -uroot -p
                                    root       6603   6551  0 10:14 pts/3    00:00:00 grep --color=auto mysql
                                    [root@localhost mysqldb8]# ss -ntl | grep 2213
                                    
                                    2.用mysql8.0.13客户端直接启动数据库

                                    因目标版本8.0.13,直接在现有数据目录上启动新版本MySQL。由MySQL服务执行升级任务,可指定–upgrade=FORCE参数

                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --upgrade=FORCE &
                                    [1] 6611
                                    [root@localhost mysqldb8]# 2023-10-15T02:20:11.533316Z mysqld_safe Logging to '/data/mysqldb/log/mysqld_error.log'.
                                    2023-10-15T02:20:11.557198Z mysqld_safe Starting mysqld daemon with databases from /data/mysqldb/data
                                    2023-10-15T02:20:12.121520Z mysqld_safe mysqld from pid file /data/mysqldb/data/mysqld.pid ended
                                    会一直卡住不用担心
                                    
                                    3.运行 mysql_upgrade,更新系统表和用户表
                                    cd /data/mysqldb813/mysql813/bin
                                    ./mysql_upgrade -uroot -p
                                    select version();
                                    --输出+-----------+
                                    | version() |
                                    +-----------+
                                    | 8.0.13    |
                                    +-----------+
                                    说明数据库平滑升级成功了
                                    
                                    4.更改环境变量

                                    因basedir由/data/mysqldb/mysql变成了/data/mysqldb8/mysql8,故相关环境变量修改如下

                                    将mysql5.7的环境变量参数更改为mysql8.0的

                                    #更改环境变量
                                    [root@localhost ~]# vi .bash_profile
                                    ...
                                    MYSQL_DATA=/data/mysqldb/data
                                    #mysql5.7弃用
                                    #export PATH=$PATH:/data/mysqldb/mysql/bin
                                    #export MYSQL_HOME=/data/mysqldb/mysql
                                    #add for mysql8.0
                                    export MYSQL_HOME=/data/mysqldb813/mysql813
                                    export PATH=$PATH:/data/mysqldb813/mysql813/bin
                                    #生效环境变量
                                    [root@localhost ~]# source .bash_profile
                                    #查看版本
                                    [root@localhost ~]# mysql -V
                                    mysql  Ver 8.0.13 for el7 on x86_64 (MySQL Community Server - GPL)
                                    或
                                    [root@localhost ~]# mysql -uroot -p
                                    root@localhost :(none) 10:40:24>select version();
                                    +-----------+
                                    | version() |
                                    +-----------+
                                    | 8.0.13    |
                                    +-----------+
                                    1 row in set (0.00 sec)
                                    root@localhost :(none) 10:40:30>exit
                                    
                                    5.配置系统服务
                                    --停止mysql5系统服务
                                    systemctl stop mysqld
                                    systemctl disable mysqld
                                    --配置mysql8系统服务
                                    cp /usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/mysqld8.service
                                    [root@localhost ~]# cat /usr/lib/systemd/system/mysqld8.service
                                    [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=/data/mysqldb813/mysql813/bin/mysqld --defaults-file=/data/mysqldb/my.cnf
                                    LimitNOFILE=65536  
                                    LimitNPROC=65536
                                    systemctl start mysqld8
                                    systemctl enable mysqld8
                                    systemctl status mysqld8
                                    

                                    三.总结

                                    至此,数据库由5.7成功升级至8.0!对比MySQL安装过程及升级过程,发现二者很相似,其实升级过程并不复杂,复杂的是升级后的验证及兼容测试,特别是对于复杂的业务库,MySQL版本升级还是要小心的。真实环境建议先升级从库,验证无误后再逐步对主库进行升级。

                                    问题1:登录数据库失败
                                    --问题描述
                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysql -uroot -p
                                    Enter password: 
                                    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysqldb/data/mysql.sock' (2)
                                    --问题处理
                                    找到 mysql.sock
                                    find / -name mysql.sock
                                    --更改/etc/my.cnf
                                    更改为上一步找到的mysql.sock文件目录
                                    
                                    问题2:sql_mode错误
                                    --问题描述
                                    2023-10-15T10:20:12.102785+08:00 0 [ERROR] [MY-000077] [Server] /data/mysqldb8/mysql8/bin/mysqld: Error while setting value 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER' to 'sql_mode'.
                                    --查看报错日志
                                    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER
                                    --问题原因
                                    8.0以上已经取消了NO_AUTO_CREATE_USER这个关键字,在my.cnf中的sql_mode中删掉这个关键字重启即可
                                    是每次升级后sql_mode的值。逗号后面都会自动加上空格导致无法启动,要手动删掉空格
                                    --问题处理
                                    去掉sql_mode中的NO_AUTO_CREATE_USER
                                    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                                    再次启动
                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
                                    或
                                    systemctl restart mysqld8
                                    systemctl status mysqld8
                                    

                                    大版本升级步骤案例1-2:logical升级方式

                                    升级需求:将5.7.42升级到8.0.13,升级方式

                                    原版本5.7.42Centos7.6 x86_64
                                    新版本8.0.13Centos7.6 x86_64

                                    逻辑升级是指使用逻辑备份从旧版本MySQL中导出数据,安装新版本MySQL并导入数据的升级方式。由于可能存在的不兼容问题会导致导入失败,导出前需要做升级前检查,导入前可能还需要对备份文件进行修改。

                                    升级主要步骤:

                                    1. 对旧版本数据做全量导出。mysqldump -u root -p --add-drop-table --routines --events --all-databases --force > data-for-upgrade.sql
                                    2. 关闭当前版本数据库。
                                    3. 安装8.0版本数据库并初始化(从error log中获取’root’@'localhost’用户初始密码)。
                                    4. 在新的数据目录中启动MySQL8.0,并重置初始密码。
                                    5. 将备份文件导入mysql -u root -p --force < data-for-upgrade.sql。如导出文件包含系统表,则不建议导入时开启GTID(gtid_mode=ON)。
                                    6. 执行剩余的升级操作。目标版本大于8.0.16时需重启服务器,启动时使用–upgrade=FORCE参数。8.0.16之前的版本先执行mysql_upgrade再重启MySQL。
                                    #8.0.16以后的版本
                                    mysqladmin -u root -p shutdown
                                    mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir --upgrade=FORCE &
                                    #8.0.16之前的版本
                                    mysql_upgrade -u root -p
                                    mysqladmin -u root -p shutdown
                                    mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir &
                                    #确认升级成功后,mysql schema中两张不再使用的表可以自行清理
                                    DROP TABLE mysql.event;
                                    DROP TABLE mysql.proc;
                                    

                                    大版本升级步骤案例2-1:in-place升级方式

                                    升级需求:将5.7.42升级到8.0.27,以In-Place方式直接升级到MySQL8.0.27。

                                    原版本5.7.42Centos7.6 x86_64
                                    新版本8.0.27Centos7.6 x86_64

                                    一.升级前准备

                                    1.停止业务

                                    确保业务已停止,保证数据一致性

                                    --查询数据库中哪些线程正在执行
                                    show processlist;
                                    
                                    2.查看源数据库信息
                                    #查版本
                                    mysql -V 
                                    或
                                    mysql> select version();
                                    +------------+
                                    | version()  |
                                    +------------+
                                    | 5.7.42-log |
                                    +------------+
                                    1 row in set (0.00 sec)
                                    

                                    场景1:查询所有数据库的总大小

                                    --查询所有数据库的总大小
                                    use information_schema;
                                    select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES;
                                    --统计一下所有库数据量
                                    SELECT
                                    SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb
                                    FROM information_schema.TABLES; 
                                    --统计每个库大小
                                    SELECT
                                    table_schema,SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb
                                    FROM information_schema.TABLES group by table_schema;  
                                    

                                    场景2:查看指定数据库的大小

                                    use information_schema;
                                    select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES where table_schema='test';
                                    

                                    场景3:记录数

                                    --查看所有数据库各容量大小
                                    select
                                    table_schema as '数据库',
                                    sum(table_rows) as '记录数',
                                    sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)',
                                    sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)'
                                    from information_schema.tables
                                    group by table_schema
                                    order by sum(data_length) desc, sum(index_length) desc;
                                    --查看所有数据库各表容量大小
                                    select
                                    table_schema as '数据库',
                                    table_name as '表名',
                                    table_rows as '记录数',
                                    truncate(data_length/1024/1024, 2) as '数据容量(MB)',
                                    truncate(index_length/1024/1024, 2) as '索引容量(MB)'
                                    from information_schema.tables
                                    order by data_length desc, index_length desc;
                                    --查看指定数据库容量大小(例:查看mysql库容量大小)
                                    select
                                    table_schema as '数据库',
                                    sum(table_rows) as '记录数',
                                    sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)',
                                    sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)'
                                    from information_schema.tables
                                    where table_schema='test'; 
                                    --查看指定数据库各表容量大小(例:查看mysql库各表容量大小)
                                    select
                                    table_schema as '数据库',
                                    table_name as '表名',
                                    table_rows as '记录数',
                                    truncate(data_length/1024/1024, 2) as '数据容量(MB)',
                                    truncate(index_length/1024/1024, 2) as '索引容量(MB)'
                                    from information_schema.tables
                                    where table_schema='test'
                                    order by data_length desc, index_length desc;
                                    
                                    3.备份数据库
                                    3.1.逻辑备份
                                    --多个数据库备份成1个文件
                                    mysqldump -uroot -p  --databases  xiaomiaoao pijiake  > /root/all-databases2213.sql
                                    --备份test数据库
                                    mysqldump -uroot -p test > /data/mysqldb/tmp/test_exp_$(date +%F).sql 
                                    
                                    3.2.目录备份

                                    如果升级失败能更快的回退

                                    --停止数据库
                                    systemctl stop mysqld
                                    --安装目录备份
                                    cp -r /data/mysqldb/mysql /data/mysqldb/mysql_bak_`date +%Y%m%d`
                                    --数据目录备份
                                    cp -r /data/mysqldb/data /data/mysqldb/data_bak_`date +%Y%m%d`
                                    --配置文件备份
                                    cp /etc/my.cnf /etc/my5.cnf_bak_`date +%Y%m%d`
                                    
                                    4.下载并安装新版本MySQL软件
                                    #1.安装介质上传至/opt/下
                                    #2.创建目录
                                    mkdir -p /data/mysqldb8
                                    #3.解压安装包
                                    tar -xvf mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz  -C /data/mysqldb8
                                    #4.文件夹重命名为mysql8 
                                    mv /data/mysqldb8/mysql*  /data/mysqldb8/mysql8
                                    #5.更改文件夹所属
                                    chown -R mysql.mysql /data/mysqldb8
                                    
                                    5.更改配置文件

                                    因5.7版本与8.0版本参数有所不同,为了能顺利升级,需要更改部分配置参数。主要注意sql_mode、basedir、密码认证插件及字符集设置,其他参数最好还是按照原5.7的来,不需要做调整。

                                    更改/etc/my.conf配置,末尾添加关键配置

                                    #add for 8.0
                                    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                                    character-set-server = utf8
                                    collation-server = utf8_general_ci
                                    basedir = /data/mysqldb8/mysql8
                                    skip_ssl
                                    default_authentication_plugin=mysql_native_password
                                    

                                    https://blog.csdn.net/weixin_42689212/article/details/121293222

                                    二.开始升级

                                    1.关闭数据库
                                    --1.进入原5.7 mysql命令行 正确关闭数据库
                                    法1:
                                    mysqladmin -uroot -p shutdown
                                    [root@mysql]# mysql -uroot -p
                                    Enter password: 
                                    #使用mysql shell 命令util.checkForServerUpgrade('root@127.0.0.1:3307', {"password":"XXXXX", "targetVersion":"8.0.26", "configPath":"/etc/my3307.cnf"}) 检查升级到目标版本8.0.26,确认没有error级别的问题
                                    Errors:   0
                                    Warnings: 17
                                    Notices:  0
                                    #检查没有未提交的xa事务
                                    mysql> xa recover;
                                    Empty set (0.00 sec)
                                    # 确保数据都刷到硬盘上,更改成0
                                    mysql> show variables like 'innodb_fast_shutdown';
                                    +----------------------+-------+
                                    | Variable_name        | Value |
                                    +----------------------+-------+
                                    | innodb_fast_shutdown | 1     |
                                    +----------------------+-------+
                                    1 row in set (0.00 sec)
                                    mysql> set global innodb_fast_shutdown=0;
                                    Query OK, 0 rows affected (0.00 sec)
                                    mysql> show variables like 'innodb_fast_shutdown';
                                    +----------------------+-------+
                                    | Variable_name        | Value |
                                    +----------------------+-------+
                                    | innodb_fast_shutdown | 0     |
                                    +----------------------+-------+
                                    mysql> shutdown;
                                    Query OK, 0 rows affected (0.00 sec)
                                    mysql> exit
                                    #查看进程和端口后,已无输出记录,确保已停止
                                    [root@localhost mysqldb8]# ps -ef | grep mysql
                                    root       6330   6202  0 07:35 pts/0    00:00:00 mysql -uroot -p -P2213 test
                                    root       6466   6202  0 09:18 pts/0    00:00:00 mysql -uroot -p
                                    root       6522   6293  0 09:58 pts/1    00:00:00 mysql -uroot -p
                                    root       6603   6551  0 10:14 pts/3    00:00:00 grep --color=auto mysql
                                    [root@localhost mysqldb8]# ss -ntl | grep 2213
                                    
                                    2.用mysql8.0.27客户端直接启动数据库

                                    因目标版本8.0.27,直接在现有数据目录上启动新版本MySQL。由MySQL服务执行升级任务,可指定–upgrade=FORCE参数

                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --upgrade=FORCE &
                                    [1] 6611
                                    [root@localhost mysqldb8]# 2023-10-15T02:20:11.533316Z mysqld_safe Logging to '/data/mysqldb/log/mysqld_error.log'.
                                    2023-10-15T02:20:11.557198Z mysqld_safe Starting mysqld daemon with databases from /data/mysqldb/data
                                    2023-10-15T02:20:12.121520Z mysqld_safe mysqld from pid file /data/mysqldb/data/mysqld.pid ended
                                    会一直卡住不用担心
                                    
                                    3.另起客户端登录mysql
                                    [root@localhost mysqldb8]# mysql -uroot -p
                                    root@localhost :(none) 10:36:19>select version();
                                    +-----------+
                                    | version() |
                                    +-----------+
                                    | 8.0.27    |
                                    +-----------+
                                    1 row in set (0.00 sec)
                                    说明数据库平滑升级成功了
                                    
                                    4.更改环境变量

                                    因basedir由/data/mysqldb/mysql变成了/data/mysqldb8/mysql8,故相关环境变量修改如下

                                    将mysql5.7的环境变量参数更改为mysql8.0的

                                    #更改环境变量
                                    [root@localhost ~]# vi .bash_profile
                                    ...
                                    MYSQL_DATA=/data/mysqldb/data
                                    #mysql5.7弃用
                                    #export PATH=$PATH:/data/mysqldb/mysql/bin
                                    #export MYSQL_HOME=/data/mysqldb/mysql
                                    #add for mysql8.0
                                    export MYSQL_HOME=/data/mysqldb8/mysql8
                                    export PATH=$PATH:/data/mysqldb8/mysql8/bin
                                    #生效环境变量
                                    [root@localhost ~]# source .bash_profile
                                    #查看版本
                                    [root@localhost ~]# mysql -V
                                    mysql  Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)
                                    或
                                    [root@localhost ~]# mysql -uroot -p
                                    root@localhost :(none) 10:40:24>select version();
                                    +-----------+
                                    | version() |
                                    +-----------+
                                    | 8.0.27    |
                                    +-----------+
                                    1 row in set (0.00 sec)
                                    root@localhost :(none) 10:40:30>exit
                                    
                                    5.配置系统服务
                                    --停止mysql5系统服务
                                    systemctl stop mysqld
                                    systemctl disable mysqld
                                    --配置mysql8系统服务
                                    cp /usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/mysqld8.service
                                    [root@localhost ~]# cat /usr/lib/systemd/system/mysqld8.service
                                    [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=/data/mysqldb8/mysql8/bin/mysqld --defaults-file=/data/mysqldb/my.cnf
                                    LimitNOFILE=65536  
                                    LimitNPROC=65536
                                    systemctl start mysqld8
                                    systemctl enable mysqld8
                                    systemctl status mysqld8
                                    

                                    三.总结

                                    至此,数据库由5.7成功升级至8.0!对比MySQL安装过程及升级过程,发现二者很相似,其实升级过程并不复杂,复杂的是升级后的验证及兼容测试,特别是对于复杂的业务库,MySQL版本升级还是要小心的。真实环境建议先升级从库,验证无误后再逐步对主库进行升级。

                                    问题1:登录数据库失败
                                    --问题描述
                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysql -uroot -p
                                    Enter password: 
                                    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysqldb/data/mysql.sock' (2)
                                    --问题处理
                                    找到 mysql.sock
                                    find / -name mysql.sock
                                    --更改/etc/my.cnf
                                    更改为上一步找到的mysql.sock文件目录
                                    
                                    问题2:sql_mode错误
                                    --问题描述
                                    2023-10-15T10:20:12.102785+08:00 0 [ERROR] [MY-000077] [Server] /data/mysqldb8/mysql8/bin/mysqld: Error while setting value 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER' to 'sql_mode'.
                                    --问题原因
                                    8.0以上已经取消了NO_AUTO_CREATE_USER这个关键字,在my.cnf中的sql_mode中删掉这个关键字重启即可
                                    是每次升级后sql_mode的值。逗号后面都会自动加上空格导致无法启动,要手动删掉空格
                                    --问题处理
                                    将sql_mode替换为如下:
                                    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                                    再次启动
                                    [root@localhost mysqldb8]# /data/mysqldb8/mysql8/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
                                    或
                                    systemctl restart mysqld8
                                    systemctl status mysqld8
                                    

                                    大版本升级步骤案例2-2:logical升级方式

                                    升级需求:将5.7.42升级到8.0.27,升级方式

                                    原版本5.7.42Centos7.6 x86_64
                                    新版本8.0.27Centos7.6 x86_64

                                    逻辑升级是指使用逻辑备份从旧版本MySQL中导出数据,安装新版本MySQL并导入数据的升级方式。由于可能存在的不兼容问题会导致导入失败,导出前需要做升级前检查,导入前可能还需要对备份文件进行修改。

                                    升级主要步骤:

                                    1. 对旧版本数据做全量导出。mysqldump -u root -p --add-drop-table --routines --events --all-databases --force > data-for-upgrade.sql
                                    2. 关闭当前版本数据库。
                                    3. 安装8.0版本数据库并初始化(从error log中获取’root’@'localhost’用户初始密码)。
                                    4. 在新的数据目录中启动MySQL8.0,并重置初始密码。
                                    5. 将备份文件导入mysql -u root -p --force < data-for-upgrade.sql。如导出文件包含系统表,则不建议导入时开启GTID(gtid_mode=ON)。
                                    6. 执行剩余的升级操作。目标版本大于8.0.16时需重启服务器,启动时使用–upgrade=FORCE参数。8.0.16之前的版本先执行mysql_upgrade再重启MySQL。
                                    #8.0.16以后的版本
                                    mysqladmin -u root -p shutdown
                                    mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir --upgrade=FORCE &
                                    #8.0.16之前的版本
                                    mysql_upgrade -u root -p
                                    mysqladmin -u root -p shutdown
                                    mysqld_safe --user=mysql --datadir=/path/to/8.0-datadir &
                                    #确认升级成功后,mysql schema中两张不再使用的表可以自行清理
                                    DROP TABLE mysql.event;
                                    DROP TABLE mysql.proc;
                                    

                                    补充:参数详解

                                    1.sql_mode参数详解

                                    1.STRICT_TRANS_TABLES:如果插入或更新操作反了表定义的约束条件,则会导致警告或错误2.NO_ZERO_IN_DATE:禁止在日期中使用零值,例如0000-00-00’

                                    3.NO_ZERO_DATE:禁止日期列中的零值,默认情况下,MySQL允许使用0000-00-00表示无效日期

                                    4.ERROR_FOR_DIVISION_BY_ZERO:如果除数为零,则会引发错误

                                    5.NO_ENGINE_SUBSTITUTION: 如果指定了一个不存在的存储引擎,MySQL将引发错误

                                    2.innodb_fast_shutdown参数详解

                                    innodb_fast_shutdown有3个值:

                                    默认是1 可选0 1 2

                                    支持全动态局设置

                                    使用场景:在做数据库关闭升级的时候 set global innodb_fast_shutdown=0,这个时候能最大保障数据的完整性。

                                    设置为1:关闭MySQL的时候不会做清除脏页和插入缓冲区的合并操作,也不会将脏页刷新到磁盘

                                    设置为0:会做清除脏页和插入缓冲区的合并操作,也会将脏页全部刷新到磁盘上面去,但是这个时候关闭的速度也是最慢的

                                    设置为2:不会做清除脏页和插入缓冲区的合并操作,也不会将脏页刷新到磁盘,但是会刷新到redo log里面,再下次启动mysql的时候恢复

                                    参考链接:https://zhuanlan.zhihu.com/p/426007112