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
  • 面试
相关推荐
weixin_511255215 小时前
MySQL升级记录
数据库·mysql
程序猿乐锅6 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
GreenTea6 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
Leo.yuan6 小时前
2026年本地化Data Agent优质厂商盘点:哪些产品更适合企业生产环境
大数据·数据库·人工智能
Java后端的Ai之路6 小时前
SSE 接口设计 vs Agent UI:四个开源项目,把「模型吐词」和「界面更新」拆开后,我看懂了差距
ui·开源·sse·agui·agentui
m0_587383006 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
做运维的阿瑞6 小时前
数据库增删改的安全写法
数据库·sql·mysql
千桐科技6 小时前
数据中台 ETL 编排实践:基于 qData 开源版实现数据接入、转换与调度执行
数据仓库·开源·etl
程序边界6 小时前
迁移评估不再拍脑袋,这个数据迁移工具的量化报告把我救了(上)
数据库
也非非也7 小时前
DeepSeek没发公告,但它把Agent装进了你的电脑
人工智能·开源·agent·deepseek·dsh