为什么要专门讲Mysql8.0的新特性呢, 因为之前对Mysql固有的认知,在Mysql8.0中的实现方式不一样,所以还是有必要了解下这其中的差别。
1、新增降序索引
mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));mysql> insert into t1 (c1,c2) values(1, 10),(2,50),(3,50),(4,100),(5,80);mysql> explain select * from t1 order by c1,c2 desc;
- mysql5.7中执行查询,Extra字段里有filesort文件排序(未使用索引)。 表结构中也是KEY `idx_c1_c2` (`c1`,`c2`) --注意这里,c2字段是升序。
- mysql8.0中执行查询,Extra字段里有using index(使用了索引)。表结构KEY `idx_c1_c2` (`c1`,`c2` DESC) --注意这里的区别,降序索引生效了。
- mysql8.0中执行explain select * from t1 order by c1 desc,c2; , 意思是反向扫描索引(索引树中的叶子节点之间是双向链表), 这时候Extra字段里有using index(使用了索引)
2、group by 不在隐式排序
如果需要排序,加上order by
3、增加隐藏索引
在创建表或修改表的时候可以设置隐藏索引。 隐藏索引只是不可见,查询的时候使用不到该索引,但是依然在后台维护。
使用场景:线上已有表且数据量很大,如果觉得某个索引没用了,删除索引后发现还有业务场景需要用到这个索引,则还需要把索引加回来,非常的麻烦。这是可以先将这个索引隐藏起来,等真正确认业务上不使用这个索引的时候再删除。
4、新增函数索引
之前的经验是,如果查询中使用了函数,则索引不生效。Mysql8支持在索引中使用函数(表达式)的值。
函数索引基于虚拟列功能实现,在MySQL中相当于新增了一个列,这个列会根据你的函数来进行计算结果,然后使用函数索引的时候就会用这个计算后的列作为索引。
mysql> create table t3(c1 varchar(10),c2 varchar(10));--创建一个大写的函数索引
mysql> create index func_idx on t3((UPPER(c2)));
5、InnodDB存储引擎select for update 跳过锁等待
- msyql5.7及其之前,select ...for update,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时
- mysql8.0新增查询共享锁的语法select....for share;
- select....for share 和 select....for update, 在语句后面添加NOWAIT、SKIP LOCKED语法可以跳过锁等待,或者跳过锁定。
6、新增innodb_dedicated_server自适应参数
能够让InnoDB根据服务器上检测到的内存大小自动配置innodb_buffer_pool_size,innodb_log_file_size等参数,会尽可能多的占用系统可占用资源提升性能。前提是服务器是专用来给MySQL数据库的,如果还有其他软件或者资源或者多实例MySQL使用,不建议开启该参数,不然会影响其它程序。
--默认是OFF关闭,修改为ON打开
mysql> show variables like '%innodb_dedicated_server%';
7、死锁检查控制
MySQL 8.0 (MySQL 5.7.15)增加了一个新的动态变量 innodb_deadlock_detect,用于控制系统是否执行 InnoDB 死锁检查,默认是打开的。死锁检测会耗费数据库性能的,对于高并发的系统,我们可以关闭死锁检测功能,提高系统性能。
8、undo文件不再使用系统表空间
默认创建2个UNDO表空间,不再使用系统表空间。(data目录下两个专门的UNDO文件)
9、 binlog日志过期时间精确到秒
- 之前是天
- 参数名称发生变化:在8.0版本之前,binlog日志过期时间设置都是设置expire_logs_days参数,而在8.0版本中,MySQL默认使用binlog_expire_logs_seconds参数。
10、新增窗口函数:分析函数
# 创建一张账户余额表
CREATE TABLE `account_channel` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL
COMMENT '姓名',`channel` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL
COMMENT '账户渠道',`balance` int DEFAULT NULL COMMENT '余额',
PRIMARY KEY (`id`)
) ENGINE=InnoDB;# 普通方法:统计每个人的总金额
mysql> select name,sum(balance) from account_channel group by name;# 在聚合函数后面加上over()就变成分析函数了,后面可以不用再加group by制定分组,因为在over里已经用partition关键字指明了如何分组计算,这种可以保留原有表数据的结构,不会像分组聚合函数那样每组只返回一条数据
mysql> select name,channel,balance,sum(balance) over(partition by name) as sum_balance
from account_channel;
分析函数结果:

11、默认字符集由latin1变为utf8mb4
在8.0版本之前,默认字符集为latin1,utf8指向的是utf8mb3,8.0版本默认字符集为utf8mb4,utf8默认指向的也是utf8mb4。
12、MyISAM系统表全部换成InnoDB表
将系统表(mysql)和数据字典表全部改为InnoDB存储引擎,默认的MySQL实例将不包含MyISAM表,除非手动创建MyISAM表。
13、元数据存储变动
MySQL 8.0删除了之前版本的元数据文件,例如表结构.frm等文件,全部集中放入mysql.ibd文件里。可以看见下图test库文件夹里已经没有了frm文件。
14、自增变量持久化
- 在8.0之前的版本,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。
- 8.0版本将会对AUTO_INCREMENT值进行持久化,MySQL重启后,该值将不会改变。
15、最左前缀原则
Mysql索引遵循最做前缀匹配原则, 但是在Mysql8.0后,对于索引 index1(a, b, c), 如果where b = b1 and c = c1, 可能使用索引跳跃扫描(Index Skip Scan),前提是a列的范围比较少。
但是我们不能以来这个优化,建立索引的时候,还是有限吧区分度高的,查询频繁的字段放到联合索引的左边。