MySQL 8.0新特性详解:从隐藏索引到窗口函数全面解析

关键词:MySQL8, 新特性, 隐藏索引, 窗口函数, CTE, 降序索引, 函数索引, 原子DDL

MySQL 5.7将于2023年10月31日停止支持,官方不再进行代码维护。MySQL 8.0全内存访问可轻易跑到200W QPS,I/O极端高负载场景跑到16W QPS,性能提升显著。除此之外,MySQL 8还新增了大量实用功能。本文将从账户安全、索引增强、通用表表达式、窗口函数等多个维度,全面解析MySQL 8.0的新特性,帮助你顺利升级到MySQL 8。


目录

  1. [MySQL 8.0简介](#MySQL 8.0简介)
  2. 账户与安全增强
  3. 索引增强
  4. 通用表表达式(CTE)
  5. 窗口函数
  6. 原子DDL操作
  7. JSON增强
  8. InnoDB其他改进

1. MySQL 8.0简介

MySQL 5.7生命周期结束

  • MySQL 5.7 将于2023年10月31日停止支持
  • 官方不再进行后续代码维护
  • 建议升级到MySQL 8.0以获得持续支持

MySQL 8.0性能提升

场景 QPS性能
全内存访问 轻易跑到 200W QPS
I/O极端高负载场景 跑到 16W QPS

2. 账户与安全增强

2.1 用户创建和授权分离

MySQL 5.7及之前版本

sql 复制代码
-- 用户创建和授权可以一起执行
GRANT ALL PRIVILEGES ON *.* TO 'lijin'@'%' IDENTIFIED BY 'Lijin@2022';

MySQL 8.0版本

sql 复制代码
-- 用户创建和授权必须分开执行
-- 步骤1:创建用户
CREATE USER 'lijin'@'%' IDENTIFIED BY 'Lijin@2022';

-- 步骤2:授权
GRANT ALL PRIVILEGES ON *.* TO 'lijin'@'%';

注意:MySQL 8.0中不能将用户创建和授权语句合并执行。

2.2 认证插件更新

MySQL 8.0默认认证插件变更

版本 默认认证插件
MySQL 5.7 mysql_native_password
MySQL 8.0 caching_sha2_password

查看当前认证插件

sql 复制代码
SHOW VARIABLES LIKE 'default_authentication%';

-- 查看所有用户的认证插件
SELECT user, host, plugin FROM mysql.user;

兼容性问题

  • 如果客户端没有更新,可能连接不上MySQL 8.0
  • 老版本的Navicat等工具可能无法正常连接

解决方案1:修改配置文件(需要重启)

ini 复制代码
# my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password

解决方案2:动态修改用户认证方式(无需重启)

sql 复制代码
-- 修改指定用户的认证插件
ALTER USER 'lijin'@'%' IDENTIFIED WITH mysql_native_password BY 'Lijin@2022';

2.3 密码管理

MySQL 8.0开始允许限制重复使用以前的密码,并加入了密码修改管理功能。

查看密码相关变量

sql 复制代码
SHOW VARIABLES LIKE 'password%';

密码历史设置

变量名 说明
password_history 不能和最近N次密码一致
password_reuse_interval 按照天数限制密码重复使用
password_require_current 是否需要校验旧密码(OFF不校验,ON校验)

全局级设置

sql 复制代码
-- 修改密码不能和最近3次一致
SET PERSIST password_history = 3;

用户级设置

sql 复制代码
-- 为指定用户设置密码历史策略
ALTER USER 'lijin'@'%' PASSWORD HISTORY 3;

-- 查看用户的密码历史设置
SELECT user, host, Password_reuse_history FROM mysql.user;

要求校验旧密码(针对非root用户)

sql 复制代码
SET PERSIST password_require_current = ON;

3. 索引增强

3.1 隐藏索引

概念:MySQL 8.0开始支持隐藏索引(invisible index),隐藏索引不会被优化器使用,但仍然需要进行维护。

应用场景

  1. 软删除

    • 线上经常删除和创建索引,如果删除了发现删错了,又需要重新创建
    • 先把索引变成隐藏索引(查询优化器用不上)
    • 最后确定要删除时再进行删除操作
  2. 灰度发布

    • 想在线上进行测试,先创建一个隐藏索引,不影响当前生产环境
    • 通过测试发现索引没问题,直接把隐藏索引改成正式索引

创建隐藏索引

sql 复制代码
-- 创建表
CREATE TABLE t1(i INT, j INT);

-- 创建正常索引
CREATE INDEX i_idx ON t1(i);

-- 创建隐藏索引
CREATE INDEX j_idx ON t1(j) INVISIBLE;

查看索引信息

sql 复制代码
SHOW INDEX FROM t1\G

测试隐藏索引

sql 复制代码
-- 查看查询是否使用索引
EXPLAIN SELECT * FROM t1 WHERE i = 1;  -- 会使用i_idx
EXPLAIN SELECT * FROM t1 WHERE j = 1;  -- 不会使用j_idx(隐藏索引)

让优化器看到隐藏索引(会话级别)

sql 复制代码
-- 查看优化器参数
SELECT @@optimizer_switch\G;

-- 开启隐藏索引可见
SET SESSION optimizer_switch = 'use_invisible_indexes=on';

切换索引可见性

sql 复制代码
-- 隐藏索引变为可见
ALTER TABLE t1 ALTER INDEX j_idx VISIBLE;

-- 正常索引变为隐藏
ALTER TABLE t1 ALTER INDEX j_idx INVISIBLE;

限制:不能把主键设置成隐藏索引(MySQL做了限制)。

3.2 降序索引

MySQL 8.0开始真正支持降序索引(descending index)。

特点

  • 只有InnoDB存储引擎支持降序索引
  • 只支持BTREE降序索引
  • MySQL 8.0不再对GROUP BY操作进行隐式排序

创建降序索引

sql 复制代码
CREATE TABLE t2(
    c1 INT,
    c2 INT,
    INDEX idx1(c1 ASC, c2 DESC)  -- c1升序,c2降序
);

查看表结构

sql 复制代码
SHOW CREATE TABLE t2\G

MySQL 8.0会显示升序/降序信息,而5.7不会显示。

插入测试数据

sql 复制代码
INSERT INTO t2(c1, c2) VALUES(1, 100), (2, 200), (3, 150), (4, 50);

使用降序索引查询

sql 复制代码
-- 会使用索引(不需要额外排序)
EXPLAIN SELECT * FROM t2 ORDER BY c1, c2 DESC;

-- MySQL 5.7需要额外的排序操作
-- MySQL 8.0可以直接使用索引

GROUP BY不再隐式排序

MySQL 8.0中GROUP BY不再默认排序:

sql 复制代码
-- 8.0版本:不会自动排序
SELECT COUNT(*), c2 FROM t2 GROUP BY c2;

-- 需要手动添加ORDER BY
SELECT COUNT(*), c2 FROM t2 GROUP BY c2 ORDER BY c2;

3.3 函数索引

问题背景:如果在查询中加入了函数,普通索引不会生效。

MySQL 8.0.13开始支持在索引中使用函数(表达式)的值,支持JSON数据的索引。

函数索引基于虚拟列功能实现

创建函数索引(表达式)

sql 复制代码
-- 创建表
CREATE TABLE t3(c1 VARCHAR(10), c2 VARCHAR(10));

-- 创建普通索引
CREATE INDEX idx_c1 ON t3(c1);

-- 创建函数索引(大写转换)
CREATE INDEX func_idx ON t3((UPPER(c2)));

测试函数索引

sql 复制代码
-- 普通索引不会生效(使用了函数)
EXPLAIN SELECT * FROM t3 WHERE UPPER(c1) = 'ABC';

-- 函数索引会生效
EXPLAIN SELECT * FROM t3 WHERE UPPER(c2) = 'ABC';

创建函数索引(JSON)

sql 复制代码
-- 创建JSON函数索引
CREATE TABLE t4(
    data JSON,
    INDEX ((CAST(data->>'$.name' AS CHAR(25))))
);

-- 查询使用函数索引
EXPLAIN SELECT * FROM t4 WHERE CAST(data->>'$.name' AS CHAR(25)) = 'lijin';

原理:函数索引相当于新增了一个列,这个列根据函数进行计算,然后使用计算后的列作为索引。


4. 通用表表达式(CTE)

MySQL 8.0开始支持通用表表达式(Common Table Expression,CTE),即WITH子句。

简单入门示例

sql 复制代码
WITH RECURSIVE cte(n) AS (
    SELECT 1
    UNION ALL
    SELECT n + 1 FROM cte WHERE n < 10
)
SELECT * FROM cte;

结果:返回1到10的数字。

执行过程

  1. 首先执行SELECT 1,得到结果n=1
  2. 把n=1送入UNION ALL下面的SELECT n+1 FROM cte WHERE n < 10
  3. 递归调用,直到n >= 10

递归CTE实际案例

场景:查询员工的上下级关系

表结构

sql 复制代码
CREATE TABLE staff (
    id INT,
    name VARCHAR(50),
    m_id INT  -- 上级ID
);

递归CTE查询上下级关系

sql 复制代码
WITH RECURSIVE staff_view(id, name, m_id) AS (
    -- 递归起始:查询顶级员工(m_id=0)
    SELECT id, name, CAST(id AS CHAR(200))
    FROM staff 
    WHERE m_id = 0
    
    UNION ALL
    
    -- 递归部分:查询下级员工
    SELECT s2.id, s2.name, CONCAT(s1.m_id, '-', s2.id)
    FROM staff_view AS s1 
    JOIN staff AS s2 ON s1.id = s2.m_id
)
SELECT * FROM staff_view ORDER BY id;

优势

  • 上下级层级有4、5、6甚至更多层,都可以帮助遍历出来
  • 老的方式需要写复杂的SQL,递归CTE更加简洁

CTE总结

  • CTE类似于派生表,就像语句级别的临时表或视图
  • CTE可以在查询中多次引用
  • CTE可以引用其他CTE
  • CTE支持递归
  • CTE支持SELECT/INSERT/UPDATE/DELETE等语句

5. 窗口函数

MySQL 8.0支持窗口函数(Window Function),也称分析函数。

窗口函数与分组聚合函数类似,但每一行数据都生成一个结果

聚合窗口函数

普通分组聚合(以国家统计):

sql 复制代码
SELECT country, SUM(sum)
FROM sales
GROUP BY country
ORDER BY country;

窗口函数聚合(以国家汇总,保留所有行):

sql 复制代码
SELECT 
    year, country, product, sum,
    SUM(sum) OVER (PARTITION BY country) AS country_sum
FROM sales
ORDER BY country, year, product, sum;

计算平均值

sql 复制代码
SELECT 
    year, country, product, sum,
    SUM(sum) OVER (PARTITION BY country) AS country_sum,
    AVG(sum) OVER (PARTITION BY country) AS country_avg
FROM sales
ORDER BY country, year, product, sum;

专用窗口函数

类型 函数
序号函数 ROW_NUMBER()、RANK()、DENSE_RANK()
分布函数 PERCENT_RANK()、CUME_DIST()
前后函数 LAG()、LEAD()
头尾函数 FIRST_VALUE()、LAST_VALUE()
其他函数 NTH_VALUE()、NTILE()

排名示例

sql 复制代码
SELECT
    YEAR,
    country,
    product,
    sum,
    ROW_NUMBER() OVER (ORDER BY sum) AS 'rank',
    RANK() OVER (ORDER BY sum) AS 'rank_1'
FROM sales;

ROW_NUMBER() vs RANK()区别

  • ROW_NUMBER():连续排名,1、2、3、4...
  • RANK():跳跃排名,1、1、3、4...(相同值排名相同,跳过后续序号)

累计求和示例

sql 复制代码
SELECT
    YEAR,
    country,
    product,
    sum,
    SUM(sum) OVER (
        PARTITION BY country 
        ORDER BY sum 
        ROWS UNBOUNDED PRECEDING
    ) AS sum_1
FROM sales 
ORDER BY country, sum;

6. 原子DDL操作

MySQL 8.0开始支持原子DDL操作,与表相关的原子DDL只支持InnoDB存储引擎。

原子DDL操作内容

  • 更新数据字典
  • 存储引擎层的操作
  • 在binlog中记录DDL操作

支持的DDL

对象 操作
数据库 CREATE、ALTER、DROP
表空间 CREATE、ALTER、DROP
CREATE、ALTER、DROP、TRUNCATE TABLE
索引 CREATE、ALTER、DROP
存储程序 CREATE、ALTER、DROP
触发器 CREATE、ALTER、DROP
视图 CREATE、ALTER、DROP
UDF CREATE、ALTER、DROP
用户和角色 CREATE、ALTER、DROP、RENAME
权限 GRANT、REVOKE

原子DDL示例

sql 复制代码
DROP TABLE t1, t2;

场景:只有t1表,没有t2表

版本 表现
MySQL 5.7 删除t1表,报错(非原子操作)
MySQL 8.0 报错,不会删除t1表(原子操作)

原子性保证:要么全部成功,要么全部失败。


7. JSON增强

MySQL 8.0对JSON数据类型进行了大量增强。

官方文档MySQL 8.0 JSON Data Type

主要增强

  • JSON数据类型的性能优化
  • 新增的JSON函数
  • JSON路径语法增强
  • 排序和比较改进

8. InnoDB其他改进

8.1 自增列持久化

问题:MySQL 5.7及早期版本,InnoDB自增列计数器(AUTO_INCREMENT)的值只存储在内存中。

MySQL 8.0改进

  • 每次变化时将自增计数器的最大值写入redo log
  • 每次检查点时将其写入引擎私有的系统表
  • 解决了长期以来的自增字段值可能重复的bug

8.2 死锁检查控制

MySQL 8.0(MySQL 5.7.15)增加了新的动态变量,用于控制系统是否执行InnoDB死锁检查。

sql 复制代码
-- 查看死锁检查设置
SHOW VARIABLES LIKE 'innodb_deadlock_detect';

适用场景:对于高并发的系统,禁用死锁检查可能带来性能提高。

8.3 锁定语句选项

SELECT ... FOR SHARE 和 SELECT ... FOR UPDATE 中支持 NOWAIT、SKIP LOCKED 选项。

选项 说明
NOWAIT 如果请求的行被其他事务锁定,语句立即返回
SKIP LOCKED 从返回的结果集中移除被锁定的行

示例

sql 复制代码
-- 立即返回,不等待锁
SELECT * FROM t1 WHERE id = 1 FOR UPDATE NOWAIT;

-- 跳过被锁定的行
SELECT * FROM t1 WHERE status = 'pending' FOR UPDATE SKIP LOCKED;

8.4 其他改进

特性 说明
部分快速DDL ALTER TABLE ALGORITHM=INSTANT
临时表空间 InnoDB临时表使用共享的临时表空间ibtmp1
自动配置 innodb_dedicated_server自动配置InnoDB内存参数
UNDO表空间 默认创建2个UNDO表空间,不再使用系统表空间
重命名表空间 支持ALTER TABLESPACE ... RENAME TO

总结

本文全面介绍了MySQL 8.0的新特性,帮助你顺利升级:

核心新特性

  1. 账户与安全

    • 用户创建和授权必须分开执行
    • 默认认证插件变为caching_sha2_password
    • 支持密码历史管理和重复使用限制
  2. 索引增强

    • 隐藏索引:支持灰度发布和软删除
    • 降序索引:真正支持DESC索引,优化排序性能
    • 函数索引:支持表达式和JSON路径索引
  3. CTE通用表表达式

    • 支持递归CTE
    • 简化层级查询(如组织架构、树形结构)
  4. 窗口函数

    • 聚合窗口函数:SUM、AVG、COUNT等
    • 专用窗口函数:ROW_NUMBER、RANK、LAG、LEAD等
  5. 原子DDL

    • DDL操作要么全部成功,要么全部失败
    • 避免部分执行导致的数据不一致
  6. InnoDB改进

    • 自增列持久化,解决重复问题
    • 死锁检查可控
    • 锁定语句支持NOWAIT和SKIP LOCKED

升级建议

  • MySQL 5.7已停止支持,建议尽快升级到8.0
  • 升级前测试应用兼容性(特别是认证插件)
  • 利用新特性优化查询性能(窗口函数、CTE、函数索引)
  • 使用隐藏索引进行灰度测试

面试高频问题

  • MySQL 8.0有哪些新特性?(隐藏索引、窗口函数、CTE、原子DDL等)
  • 隐藏索引有什么作用?(灰度发布、软删除)
  • 什么是窗口函数?和普通聚合函数有什么区别?(每行都返回结果)
  • 什么是原子DDL?有什么好处?(DDL操作原子性)
  • MySQL 8.0默认认证插件是什么?(caching_sha2_password)

希望这篇文章能帮助你全面了解MySQL 8.0新特性!如果觉得有帮助,欢迎点赞、收藏、关注


推荐标签

  • MySQL8
  • 新特性
  • 隐藏索引
  • 窗口函数
  • CTE
  • 降序索引
  • 原子DDL
  • 面试
相关推荐
数据库安全1 小时前
业务可用、数据可控:美创“动态脱敏+数据库透明加密“合规方案
数据库
Wonderful U1 小时前
AI智能日志异常检测告警平台:告别人工排查,秒级定位线上故障
数据库·人工智能·python·django
天河归来2 小时前
国产数据库安全可靠测评产品观察:从集中式、分布式到 HTAP 的发展趋势
数据库·分布式
rising start2 小时前
Redis 哨兵模式(Sentinel)
数据库·redis·sentinel
一切皆是因缘际会2 小时前
AI高速迭代下的技术风险与理性突围
大数据·数据结构·人工智能·架构
追光者♂2 小时前
【测评系列3】CSDN AI数字营销实测体验官:测试 开源项目——Superpowers 游戏引擎从零开发实战指南
人工智能·深度学习·机器学习·typescript·开源·游戏引擎·superpowers
小a杰.2 小时前
PTO ISA 指令架构 - PTO虚拟指令集架构解析
java·开发语言·架构
梦幻通灵2 小时前
Mysql处理锁冲突Lock conflict可用方案
数据库·mysql
小碗羊肉2 小时前
【Redis | 第五篇】分布式锁
数据库·redis·分布式