MySQL 5.7 新特性详解
我们自豪的宣布 MySQL 5.7 稳定版开放下载了。 MySQL 5.7.9 是目前世界上最流行开源数据库的一令人兴奋的新版本, 比 MySQL 5.6 快 3 倍,同时还提高了可用性,可管理性和安全性。一些重要的增强功能如下:
- 性能和可扩展性:改进 InnoDB 的可扩展性和临时表的性能,从而实现更快的网络和大数据加载等操作。
- JSON支持:使用 MySQL 的 JSON 功能,你可以结合 NoSQL 的灵活和关系数据库的强大。
- 改进复制 以提高可用性的性能。包括多源复制,多从线程增强,在线 GTIDs,和增强的半同步复制。
- 性能模式 提供更好的视角。我们增加了许多新的监控功能,以减少空间和过载,使用新的 SYS 模式显著提高易用性。
- 安全: 我们贯彻“安全第一”的要求,许多 MySQL 5.7 新功能帮助用户保证他们数据库的安全。
- 优化: 我们重写了大部分解析器,优化器和成本模型。这提高了可维护性,可扩展性和性能。
- GIS: MySQL 5.7 全新的功能,包括 InnoDB 空间索引,使用 Boost.Geometry,同时提高完整性和标准符合性。
上述只是一些亮点,我鼓励你们深入了解。可以通过一系列的里程碑博客5.7.1,5.7.2,5.7.3,5.7.4,5.7.5,5.7.6,5.7.7,5.7.8 —甚至通过记录他们的技术规范和实施细则的个人 worklogs ,或许你只是想在 github.com/mysql 上看一下代码。我们已经实施了 365 个worklogs,添加了 1007 个 MTR 测试,并且修复了 28125.7 个具体的 bug。势不可挡的感觉,所以这个“小的”指导可能是有用的。
非常感谢开发团队的每一个成员,是你们成就了这些!我说开发是指所有人,包括:需求,设计,编码,审核,测试,bug 修复,文档,发布和实验支持,真的是一个团队的努力。非常感谢开源社区的每一个人,感谢你们反馈 bug,建议和贡献!一个世界的努力。
为 MySQL 添加 JSON 支持
使用 MySQL 的最新的 JSON 功能,你可以结合 NoSQL 的灵活和关系数据库的力量。
我们开发了一个 JSON 数据类型和一个二进制存储格式 ,使用服务器可以高效存储,检索和查找 JSON 数据(WL#8132) 。
这项工作改进了 CREATE TABLE 和 ALTER TABLE ,所以你可以创建 JSON 类型的数据列,并且它扩展了 Field 类,允许对 JSON 类型数据进行 INSERT和SELECT 操作。
我们已经引入了一系列服务端功能,内置的 JSON 函数(WL#7909),这项工作可以让用户,从其他关系数据构建 JSON 数据,从 JSON 数据中抽取关系数据, 感知 JSON 数据值和文本(效度,长度,深度,键)的结构,对JSON 数据进行检索和操作。
我们已经介绍了 JSON 比较器 ,类似于 DATE/TIME/DATETIME(日期/时间/日期时间)比较器,它允许 JSON 常量和 SQL 常量比较、JSON 变量和 SQL 变量比较(WL#8249)。比较器依赖在 WL#7909 添加的 DOM 元素的支持。比较器将 SQL 常量转换为为 JSON 变量然后比较他们的值。
我们已经实现了 JSON 变量值排序(WL#8539),即一个函数产生内部方法 filesort 所需的用老排序 JSON 值的排序键。当排序 JSON 变量时用 ORDER BY,它将会返回 JSON 比较器 WL#8249 定义的排序规则所排序的结果。
我们已经为生成的列(WL#8170)实现了一个表达式分析器。这样做可以让我们的排序和参考优化器有机会使用已经为生成的列定义的索引。关于这个功能的一个案例是在 JSON 文档上产生和自动使用索引。
我们已经在 SQL 查询(WL#8607)中加上了内联 JSON 路径表达式。MySQL 现在这样执行查询:SELECT … FROM t1 WHERE t1.json_field->”$.path.to[0].key”= 123;
生成的列&可生成索引的虚拟化列
我们第一次实现生成的列(WL#411, WL#8114)。每列的值,不像一个有规律的字段的值,没有通过用户设置而是当行创建或者更新时通过服务器使用用户定义表时定义的特殊的表达式计算。生成的列也可以被物化(被存储)或者非物化(虚拟)。关于这方面的内容可以看看 Evgeny Potemkin 的文章“在MySQL 5.7.5中的生成列“。
然后我们在非物化虚拟列上为二级索引的创建提供了支持,以及这些索引在快速检索计算值和搜索方面的使用(( WL#8149, WL#8227 , WL#8481) 。
非物化虚拟列是用来处理在真正的 InnoDB 索引记录中不存在时,但是他们的元数据在 InnoDB 系统表和元数据缓存中注册了的情况,虚拟列为表提供了灵活性和保存空间,还有较重要的一点,添加/删除这样的列而不用重新构建表。这样做是存储和处理非关系型数据如 JSON 最好的选择。然而,由于这些列不是物化的,因此扫描和检索比一般的列(物化的列)要慢一些,但是,虚拟列的值在二级索引里物化了,因此这些列的数据还是比较容易进行检索和处理的。因此这也极大的提高了虚拟列的实际值。通过这样的方式,在一个虚拟生成的列上创建索引也变成了在线操作.
性能&可伸缩性
从社区反馈,账户追踪和在计算机硬件开发及本身架构方面了解到, 对 MySql 来说性能和可伸缩性是最重要的部分。迄今为止,在 MySql5.7 中, 我们已经在 InnoDB 实现了对只读(RO)结果的可伸缩性处理和在服务层明显的提高了连接速度的处理。我们也在 InnoDB 上的可伸缩性读写,提高内部操作(快速稳定的刷新/清除),和快速批量数据加载方面有了很好的进展。
InnoDB 的可伸缩性只读。我们已经提高了只读和多数读取工作负载的性能。我们也已经极大的提高InnoDB 处理只读事务(WL#6047, WL#6899, WL#6906, WL#6578)。我们也去掉了服务层连接与元数据锁定(MDL) 有关的部分和 InnoDB 中 THR_LOCK 锁的使用(WL#7304, WL#7305, WL#7306, WL#6671)。在 WL#6671 之后的一些工作负载中,LOCK_grant 锁就在未来可伸缩性的瓶颈方面清晰了很多; 例如,单张表 InnoDB POINT_SELECT Sysbench 的测试(见 Bug#72829)。目前这个问题已经通过分割 LOCK_grant 锁解决了(见WL#8355)。最终,我们也在涉及到基于内存的临时表创建的工作负载方面突破了 LOCK_plugin 和 THR_LOCK_lock 锁的瓶颈;例如,InnoDB 中像 Sysbench 的 SELECT_DISTINCT 的测试。但是,我们不应该为内部临时表获得这些锁,因此,我们清除了这些不必要的开销(见WL#8356)。也可以看一下 Dimitri Kravtchuk 的文章“MySQL 性能: MySQL 5.7 达到 500K QPS “,“MySQL 5.7 : 使用 InnoDB 缓存插件超过 1M QPS“,Sunny Bains 的文章“MySQL5.7.3对事务生命周期的改进“,和 Jimmy Yang 的文章”MySQL 5.7.3: 深入了解使用 InnoDB缓存达到 1百万QPS “。
InnoDB 读写扩展。改善了数据库的读写负载性能。移除了 InnoDB 的索引死锁(WL#6363, WL#6326)。现在的索引锁被替换成更加精细的树的“块锁”,然而以前常常用它来保护整个的索引树结构。可以参考 Yasufumi Kinoshita 的文章“MySQL-5.7 improves DML oriented workloads(MySQL-5.7 改善了面向数据操作语言的工作负载���”。
InnoDB 更快的并行数据刷新。扫描刷新一批队列数据的时候,减少了需要检索的页面数目,从而提高了页面更新的速度(WL#7047)。检索的时间复杂度已经从 O(n*n) 降低到了 O(n)。与此同时,利用多线程的多页清除技术实现了并行的数据刷新(WL#6642)。这使得数据库在多核系统上的扩展性和吞吐量均大大得到增强的同时,避免了数据刷新成为瓶颈。最后,改善了自适应的刷新算法以及其他相关机制,来达到更加一致和平滑的吞吐量。
加速连接处理。在某些应用场景下(例如:PHP 应用程序)客户的连接常常只有很短的生命周期,有时只用执行单次的查询。这意味着,用在处理连接和断开连接的时间的长短严重关系到整体的应用程序的运行性能。在 5.7 下,压缩了线程初始化和网络初始化的负载成为一个普通的线程(WL#6606)。取而代之的是 MySQL 双倍的处理高频的连接与断开连接的能力,从每秒钟 26K 次的处理能力提升至每秒钟 56K 次。也可以参考 Jon Olav Hauglid 的一篇文章“Improving connect/disconnect performance“。
加载块数据的性能的提升。为了创建索引所进行的块数据的加载,(WL#7277)。通过实现块数据的索引排序,从而加速了 CREATE INDEX 运算操作符的实现。在此之前,InnoDB 循环遍历基表,为每访问一次基表里的每条记录创建一个索引。在此次更新之后,InnoDB 可以一次从基表读取多条记录,并且通过索引的键值排序这些记录,从而由单次的块操作下创建出一整块记录的索引集。
在线操作
“时刻在线”的特性对于所有完美的 web 解决方案而言都是必需的。对于数据库管理员或者网站的开发运维人员来说,在不影响前台服务的条件下调试和拓展其后台数据库系统是极其重要的。因此,我们要确保 MySQL 在这一领域处于领先地位。在 5.7 下,我们提供如下这些:
提供了确保全局事务始终在线是方式(WL#7083)。因此,读写的操作在此过程中是可行的,并且服务器不需要同步或者重启。在此次更新之前,用户不得不停止所有的更新操作,同步所有的服务器,并且同时重启服务器。这意味着,为了确保全局事务,必须提前规划好服务器的宕机时间。可以参考 Sven Sandberg 的文章”Enabling Global Transaction Identifiers Without Downtime in MySQL 5.7.6“(利用 MySQL 5.7.6 在不宕机的情况下确保全局事务)