功能增强

所有系统表更换为InnoDB引擎

系统表全部换成事务型的innodb表,默认的MySQL实例将不包含任何MyISAM表,除非手动创建MyISAM表。

DDL原子化

InnoDB表的DDL支持事务完整性,要么成功要么回滚,将DDL操作回滚日志写入到data dictionary 数据字典表 mysql.innodb_ddl_log 中用于回滚操作,该表是隐藏的表,通过show tables无法看到。通过设置参数,可将ddl操作日志打印输出到mysql错误日志中。

mysql> set global log_error_verbosity=3;
mysql> set global innodb_print_ddl_logs=1;

公用表表达式(CTE:Common Table Expression)

CTE(Common Table Expression)可以认为是派生表(derived table)的替代,在一定程度上,CTE简化了复杂的join查询和子查询,另外CTE可以很方便地实现递归查询,提高了SQL的可读性和执行性能。CTE是ANSI SQL 99标准的一部分,在MySQL 8.0.1版本被引入。

Clone插件

MySQL 8.0 clone插件提供从一个实例克隆出另外一个实例的功能,克隆功能提供了更有效的方式来快速创建MySQL实例,搭建主从复制和组复制。

资源组

MySQL 8.0新增了一个资源组功能,用于调控线程优先级以及绑定CPU核。MySQL用户需要有 RESOURCE_GROUP_ADMIN权限才能创建、修改、删除资源组。在Linux环境下,MySQL进程需要有 CAP_SYS_NICE 权限才能使用资源组完整功能。

角色管理

角色可以认为是一些权限的集合,为用户赋予统一的角色,权限的修改直接通过角色来进行,无需为每个用户单独授权。

多值索引

从 MySQL 8.0.17 开始,InnoDB 支持创建多值索引,这是在存储值数组的 JSON 列上定义的二级索引,单个数据记录可以有多个索引记录。这样的索引使用关键部分定义,例如 CAST(data->’$.zipcode’ AS UNSIGNED ARRAY)。 MySQL 优化器自动使用多值索引来进行合适的查询,可以在 EXPLAIN 的输出中查看。

函数索引

MySQL 8.0.13 以及更高版本支持函数索引(functional key parts),也就是将表达式的值作为索引的内容,而不是列值或列值前缀。 将函数作为索引键可以用于索引那些没有在表中直接存储的内容。

其实MySQL5.7中推出了虚拟列的功能,而MySQL8.0的函数索引也是依据虚拟列来实现的。

  • 只有那些能够用于计算列的函数才能够用于创建函数索引。
  • 函数索引中不允许使用子查询、参数、变量、存储函数以及自定义函数。
  • SPATIAL 索引和 FULLTEXT 索引不支持函数索引。

不可见索引

使用INVISIBLE关键字在创建表或者进行表变更中设置索引是否可见。索引不可见只是在查询时优化器不使用该索引,即使使用force index,优化器也不会使用该索引,同时优化器也不会报索引不存在的错误,因为索引仍然真实存在,在必要时,也可以快速的恢复成可见。

新增降序索引

MySQL在语法上很早就已经支持降序索引,但实际上创建的仍然是升序索引。从8.0开始,实际创建的为降序索引。

SET_VAR 语法

在sql语法中增加SET_VAR语法,动态调整部分参数,有利于提升语句性能。

select /*+ SET_VAR(sort_buffer_size = 16M) */ id from test order id ;
insert /*+ SET_VAR(foreign_key_checks=OFF) */ into test(name) values(1);

参数修改持久化

MySQL 8.0版本支持在线修改全局参数并持久化,通过加上PERSIST关键字,可以将修改的参数持久化到新的配置文件(mysqld-auto.cnf)中,重启MySQL时,可以从该配置文件获取到最新的配置参数。

例如执行:

set PERSIST expire_logs_days=10 ;

系统会在数据目录下生成一个包含json格式的 mysqld-auto.cnf 的文件,格式化后如下所示,当 my.cnf 和 mysqld-auto.cnf 同时存在时,后者具有更高优先级。

innodb select for update跳过锁等待

select … for update,select … for share(8.0新增语法) 添加 NOWAIT、SKIP LOCKED语法,跳过锁等待,或者跳过锁定。

在5.7及之前的版本,select…for update,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时。

在8.0版本,通过添加nowait,skip locked语法,能够立即返回。如果查询的行已经加锁,那么nowait会立即报错返回,而skip locked也会立即返回,只是返回的结果中不包含被锁定的行。

group by 不再隐式排序

mysql 8.0 对于group by 字段不再隐式排序,如需要排序,必须显式加上order by 子句。

自增变量持久化

在8.0之前的版本,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。自增主键重启重置的问题很早就被发现,一直到8.0才被解决,8.0版本将会对AUTO_INCREMENT值进行持久化,MySQL重启后,该值将不会改变。

binlog日志事务压缩

MySQL 8.0.20 版本增加了binlog日志事务压缩功能,将事务信息使用zstd算法进行压缩,然后再写入binlog日志文件,这种被压缩后的事务信息,在binlog中对应为一个新的event类型,叫做Transaction_payload_event。

分区表改进

MySQL 8.0 对于分区表功能进行了较大的修改,在 8.0 之前,分区表在Server层实现,支持多种存储引擎,从 8.0 版本开始,分区表功能移到引擎层实现,目前MySQL 8.0 版本只有InnoDB存储引擎支持分区表。

自动参数设置

新增innodb_dedicated_server参数,能够让InnoDB根据服务器上检测到的内存大小自动配置innodb_buffer_pool_size,innodb_log_file_size,innodb_flush_method三个参数。

窗口函数

MySQL 8.0 版本开始支持窗口函数,主流关系型数据库,比如Oralce, PostgreSQL等都支持窗口数据功能,窗口函数对于数据分析处理具有重要作用。

索引损坏标记

当遇到索引树损坏时,InnoDB会在redo日志中写入一个损坏标志,这会使损坏标志安全崩溃。InnoDB还将内存损坏标志数据写入每个检查点的私有系统表中。

在恢复的过程中,InnoDB会从这两个位置读取损坏标志,并合并结果,然后将内存中的表和索引对象标记为损坏。

InnoDB memcached插件

InnoDB memcached插件支持批量get操作(在一个memcached查询中获取多个键值对)和范围查询。减少客户端和服务器之间的通信流量,在单个memcached查询中获取多个键、值对的功能可以提高读取性能。

Online DDL

从 MySQL 8.0.12 开始(仅仅指InnoDB引擎),以下 ALTER TABLE 操作支持 ALGORITHM=INSTANT:

  • 添加列。此功能也称为“即时添加列”。限制适用。
  • 添加或删除虚拟列。
  • 添加或删除列默认值。
  • 修改 ENUM 或 SET 列的定义。
  • 更改索引类型。
  • 重命名表。

Online DDL的好处:

支持 ALGORITHM=INSTANT 的操作只修改数据字典中的元数据。表上没有元数据锁,表数据不受影响,操作是即时的,并不会造成业务抖动。这在一些服务级别要求比较高(7*24)的系统中,是非常方便的。该特性是由腾讯游戏DBA团队贡献的。

如果未明确指定,则支持它的操作默认使用 ALGORITHM=INSTANT。如果指定了 ALGORITHM=INSTANT 但不受支持,则操作会立即失败并出现错误。需要注意的是,在 MySQL 8.0.29 之前,一列只能作为表的最后一列添加。不支持将列添加到其他列中的任何其他位置。从 MySQL 8.0.29 开始,可以将即时添加的列添加到表中的任何位置。

EXPLAIN ANALYZE

Explain 是我们常用的查询分析工具,可以对查询语句的执行方式进行评估,给出很多有用的线索。但他仅仅是评估,不是实际的执行情况,比如结果中的 rows,可能和实际结果相差甚大。

Explain Analyze 是 MySQL 8 中提供的新工具,可贵之处在于可以给出实际执行情况。Explain Analyze 是一个查询性能分析工具,可以详细的显示出 查询语句执行过程中,都在哪儿花费了多少时间。Explain Analyze 会做出查询计划,并且会实际执行,以测量出查询计划中各个关键点的实际指标,例如耗时、条数,最后详细的打印出来。

这项新功能建立在常规的EXPLAIN基础之上,可以看作是MySQL 8.0之前添加的EXPLAIN FORMAT = TREE的扩展。EXPLAIN除了输出查询计划和估计成本之外,EXPLAIN ANALYZE还会输出执行计划中各个迭代器的实际成本。

ReplicaSet

InnoDB ReplicaSet 由一个主节点和多个从节点构成. 可以使用MySQL Shell的ReplicaSet对象和AdminAPI操作管理复制集, 例如检查InnoDB复制集的状态, 并在发生故障时手动故障转移到新的主服务器.

ReplicaSet 所有的节点必须基于GTID,并且数据复制采用异步的方式。使用复制集还可以接管既有的主从复制,但是需要注意,一旦被接管,只能通过AdminAPI对其进行管理。

备份锁

在MySQL 8.0中,引入了一个轻量级的备份锁,这个锁可以保证备份一致性,而且阻塞的操作相对比较少,是一个非常重要的新特性。

在MySQL 8.0中,为了解决备份FTWRL的问题,引入了轻量级的备份锁;可以通过LOCK INSTANCE FOR BACKUP和UNLOCK INSTANCE,以获取和释放备份锁,执行该语句需要BACKUP_ADMIN权限。

backup lock不会阻塞读写操作。不过,backup lock会阻塞大部分DDL操作,包括创建/删除表、加/减字段、增/删索引、optimize/analyze/repair table等。

总的来说,备份锁还是非常实用的,毕竟其不会影响业务的正常读写;至于备份锁和DDL操作的冲突,还是有很多方法可以避免,比如错开备份和变更的时间、通过pt-online-schema-change/gh-ost避免长时间阻塞等等。随着备份锁的引入,Oracle官方备份工具MEB 8.0和Percona开源备份工具XtraBackup 8.0,也是更新了对backup lock的支持。

Binlog增强

MySQL 8.0.20 版本增加了binlog日志事务压缩功能,将事务信息使用zstd算法进行压缩,然后再写入binlog日志文件,这种被压缩后的事务信息,在binlog中对应为一个新的event类型,叫做Transaction_payload_event。

默认字符集由latin1变为utf8mb4

在8.0版本之前,默认字符集为latin1,utf8指向的是utf8mb3,8.0版本默认字符集为utf8mb4,utf8默认指向的也是utf8mb4。

性能提升

基于竞争感知的事务调度(CATS:Contention-Aware Transaction Scheduling)

MySQL 在 8.0.3 版本引入了新的事务调度算法,基于竞争感知的事务调度,Contention-Aware Transaction Scheduling,简称CATS。在CATS算法之前,MySQL使用FIFO算法,先到的事务先获得锁,如果发生锁等待,则按照FIFO算法进行排队。CATS相比FIFO更加复杂,也更加聪明,在高负载、高争用的场景下,性能提升显著。

基于WriteSet的并行复制

MySQL 8.0 版本引入了一个新的机制 WriteSet,来追踪事务之间的依赖性,这个特性被用于优化从库应用binlog的速度,在主库并发较低的场景下,能够显著提高从库回放binlog的速度,基于WriteSet 的并行复制方案,彻底解决了MySQL复制延迟问题。

JSON特性增强

MySQL 8 大幅改进了对 JSON 的支持,添加了基于路径查询参数从 JSON 字段中抽取数据的 JSON_EXTRACT() 函数,以及用于将数据分别组合到 JSON 数组和对象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 聚合函数。

在主从复制中,新增参数 binlog_row_value_options,控制JSON数据的传输方式,允许对于Json类型部分修改,在binlog中只记录修改的部分,减少json大数据在只有少量修改的情况下,对资源的占用。

空间数据类型增强

MySQL 8 大幅改进了空间数据类型和函数,支持更多的空间分析函数和空间类型对象,空间分析功能和性能得到大幅提升。

doublewrite改进

在MySQL 8.0.20 版本之前,doublewrite 存储区位于系统表空间,从 8.0.20 版本开始,doublewrite 有自己独立的表空间文件,这种变更,能够降低doublewrite的写入延迟,增加吞吐量,为设置doublewrite文件的存放位置提供了更高的灵活性。

hash join

MySQL 8.0.18 版本引入 hash join 功能,对于没有走索引的等值 join 连接可以使用 hash join 进行优化。8.0.20 版本对 hash join 进行了加强,即使 join 连接没有使用等值条件也可以使用 hash join 优化,原来使用 BNL 算法的 join 连接将全部由 hash join 代替。

anti join(反连接)

MySQL 8.0.17版本引入了一个anti join的优化,这个优化能够将where条件中的not in(subquery), not exists(subquery),in(subquery) is not true,exists(subquery) is not true,在内部转化成一个anti join,以便移除里面的子查询subquery,这个优化在某些场景下,能够将性能提升20%左右。

anti join适用的场景案例通常如下:

  • 找出在集合A且不在集合B中的数据
  • 找出在当前季度里没有购买商品的客户
  • 找出今年没有通过考试的学生
  • 找出过去3年,某个医生的病人中没有进行医学检查的部分

redo优化

mysql8.0一个新特性就是redo log提交的无锁化。在8.0以前,各个用户线程都是通过互斥量竞争,串行的写log buffer,因此能保证lsn的顺序无间隔增长。

mysql8.0通过redo log无锁化,解决了用户线程写redo log时竞争锁带来的性能影响。同时将redo log写文件、redo log刷盘从用户线程中剥离出来,抽成单独的线程,用户线程只负责将redo log写入到log buffer,不再关心redo log的落盘细节,只需等待log_writer线程或log_flusher线程的通知。

直方图(统计信息)

优化器会利用column_statistics的数据,判断字段的值的分布,得到更准确的执行计划。

可以通过ANALYZE TABLE table_name [UPDATE HISTOGRAM on colume_name with N BUCKETS |DROP HISTOGRAM ON clo_name] 来收集或者删除直方图信息。

直方图统计了表中某些字段的数据分布情况,为优化选择高效的执行计划提供参考,直方图与索引有着本质的区别,维护一个索引有代价。每一次的insert、update、delete都需要更新索引,会对性能有一定的影响。而直方图一次创建永不更新,除非明确去更新它,因此不会影响insert、update、delete的性能。

关闭QC(Query Cache )

从 MySQL 8.0开始,不再使用查询缓存(Query Cache)。

随着技术的进步,经过时间的考验,MySQL的工程团队发现启用缓存的好处并不多。

首先,查询缓存的效果取决于缓存的命中率,只有命中缓存的查询效果才能有改善,因此无法预测其性能。

其次,查询缓存的另一个大问题是它受到单个互斥锁的保护。在具有多个内核的服务器上,大量查询会导致大量的互斥锁争用。

MySQL8.0取消查询缓存的另外一个原因是,研究表明,缓存越靠近客户端,获得的好处越大。MySQL8.0新增加了一些其他对性能干预的工具来支持。另外,还有像ProxySQL这样的第三方工具,也可以充当中间缓存。

安全性增强

死锁检测

可以使用一个新的动态变量 innodb_deadlock_detect 来禁用死锁检测。在高并发系统上,当多个线程等待同一个锁时,死锁检测会导致速度变慢。有时,禁用死锁检测并在发生死锁时依靠 innodb_lock_wait_timeout 设置进行事务回滚可能更有效。

redo log 和 undo log加密

增加以下两个参数,用于控制redo、undo日志的加密。

  • innodb_undo_log_encrypt
  • innodb_undo_log_encrypt

默认密码认证插件

MySQL 8.0.4 版本修改了默认的身份认证插件,从老的mysql_native_password插件变为新的caching_sha2_password,并将其作为默认的身份认证机制,同时客户端对应的libmysqlclient也默认使用新的认证插件。

升级密码过期,历史密码使用规则

设置历史密码检测规则,防止反复重用旧密码。

  • password_history
  • password_reuse_interval

双密码机制,修改密码时,创建新的密码,同时旧的密码也可以使用,保留一定的缓冲时间进行检查确认。

当修改一个账户密码时,需要去验证当前的密码,通过参数password_require_current来控制,默认关闭,当打开该选项时,如果要修改账户密码,必须要提供当前的密码才允许修改。

优化器增强

Cost Model改进

优化器能够感知到页是否存在缓冲池中。5.7其实已经开放接口,但是不对内存中的页进行统计,返回都是1.0.

可伸缩的读写负载 Scaling Read/Write Workloads

8.0版本对于读写皆有和高写负载的拿捏恰到好处。在集中的读写均有的负载情况下,我们观测到在4个用户并发的情况下,对于高负载,和5.7版本相比有着两倍性能的提高。在5.7上我们显著了提高了只读情况下的性能,8.0则显著提高了读写负载的可扩展性。为MySQL提升了硬件性能的利用率,其改进是基于重新设计了InnoDB写入Redo日志的方法。对比之前用户线程之前互相争抢着写入其数据变更,在新的Redo日志解决方案中,现在Redo日志由于其写入和刷缓存的操作都有专用的线程来处理。用户线程之间不在持有Redo写入相关的锁,整个Redo处理过程都是时间驱动。

8.0版本允许马力全开的使用存储设备,比如使用英特尔奥腾闪存盘的时候,我们可以在IO敏感的负载情况下获得1百万的采样 QPS(这里说的IO敏感是指不在IBP中,且必须从二级存储设备中获取)。这个改观是由于我们摆脱了 file_system_mutex全局锁的争用。

在高争用(热点数据)负载情况下的更优性能 Better Performance upon High Contention Loads (“hot rows”)

8.0版本显著地提升了高争用负载下的性能。高争用负载通常发生在许多事务争用同一行数据的锁,导致了事务等待队列的产生。在实际情景中,负载并不是平稳的,负载可能在特定的时间内爆发(80/20法则)。8.0版本针对短时间的爆发负载无论在每秒处理的事务数(换句话,延迟)还是95%延迟上都处理的更好。对于终端用户来说体现在更好的硬件资源利用率(效率)上。因为系统需要尽量使用榨尽硬件性能,才可以提供更高的平均负载。

安全性增强

认值加密插件

老版本:认证方式为sha256_password

8.0 版本:在老版本的基础上,新增caching_sha2_password,可以使用缓存解决连接时的延时问题。

需要注意的问题是:如果客户端与服务端配置不同,无法进行连接,两者的加密认证方式需要一样。

用户密码增强

(1)密码的重复使用策略

密码*次数*:无法从指定数量的最近密码中选择新密码。如果密码更改的最小数量设置为5,则新密码不能与最近最新的5个密码相同。

时间间隔:\ 无法从历史记录中比指定天数更新的密码中选择新密码。例如,密码重用间隔设置为90,则新密码不能和过去90天内的密码相同。

(2)修改密码必要的验证策略

修改密码,要输入当前的密码。增加了用户的安全性。

(3)双密码

相比于一个用户只有一个密码最大优点就是:修改密码不会导致应用不可用。那么应用就可以自动使用副密码(副密码和当前密码保持一致)连接数据库库。确保了业务的不中断。修改密码不会导致应用不可用;应用就可以自动使用副密码连接数据库。

角色功能

MySQL角色是指定权限集合。像用户账户一样,角色可以拥有授予和撤销的权限。

可以授予用户账户角色,授予该账户与每个角色相关的权限。

方便了用户权限管理和维护。很好地解决了多个用户使用相同的权限集。权限–》角色–》用户。

redo & undo 日志加密

增加以下两个参数,用于控制redo、undo日志的加密。

innodb_undo_log_encrypt
innodb_undo_log_encrypt

其他增强

支持在线修改全局参数并持久化

通过加上PERSIST关键字,可以将修改的参数持久化到新的配置文件(mysqld-auto.cnf)中,重启MySQL时,可以从该配置文件获取到最新的配置参数。

系统会在数据目录下生成mysqld-auto.cnf 文件,该文件内容是以json格式存储的。当my.cnf 和mysqld-auto.cnf 同时存在时,后者优先级更高。

例如:

SET PERSIST max_connections = 1000;
SET @@PERSIST.max_connections = 1000;

此 SET 语法使您能够在运行时进行配置更改,这些更改也会在服务器重新启动后持续存在。与 SET GLOBAL 一样,SET PERSIST 设置全局变量运行时值,但也将变量设置写入 mysqld-auto.cnf 文件(如果存在则替换任何现有变量设置)。

binlog日志过期时间精确到秒

之前是天,并且参数名称发生变化. 在8.0版本之前,binlog日志过期时间设置都是设置expire_logs_days参数,而在8.0版本中,MySQL默认使用binlog_expire_logs_seconds参数。

undo空间自动回收

innodb_undo_log_truncate参数在8.0.2版本默认值由OFF变为ON,默认开启undo日志表空间自动回收。

innodb_undo_tablespaces参数在8.0.2版本默认为2,当一个undo表空间被回收时,还有另外一个提供正常服务。

innodb_max_undo_log_size参数定义了undo表空间回收的最大值,当undo表空间超过这个值,该表空间被标记为可回收。

地理信息系统 GIS

8.0 版本提供对地形的支持,其中包括了对空间参照系的数据源信息的支持,SRS aware spatial数据类型,空间索引,空间函数。总而言之,8.0版本可以理解地球表面的经纬度信息,而且可以在任意受支持的5000个空间参照系中计算地球上任意两点之间的距离.

注意:升级前,一定要验证jdbc驱动是否匹配,是否需要随着升级。

picture loss