MySQL 5.7 新特性详解

MySQL 5.7 新特性详解

我们自豪的宣布 MySQL 5.7 稳定版开放下载了。 MySQL 5.7.9 是目前世界上最流行开源数据库的一令人兴奋的新版本, 比 MySQL 5.6 快 3 倍,同时还提高了可用性,可管理性和安全性。一些重要的增强功能如下:

  1. 性能和可扩展性:改进 InnoDB 的可扩展性和临时表的性能,从而实现更快的网络和大数据加载等操作。
  2. JSON支持:使用 MySQL 的 JSON 功能,你可以结合 NoSQL 的灵活和关系数据库的强大。
  3. 改进复制 以提高可用性的性能。包括多源复制,多从线程增强,在线 GTIDs,和增强的半同步复制。
  4. 性能模式 提供更好的视角。我们增加了许多新的监控功能,以减少空间和过载,使用新的 SYS 模式显著提高易用性。
  5. 安全: 我们贯彻“安全第一”的要求,许多 MySQL 5.7 新功能帮助用户保证他们数据库的安全。
  6. 优化: 我们重写了大部分解析器,优化器和成本模型。这提高了可维护性,可扩展性和性能。
  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 在不宕机的情况下确保全局事务)

我们已经添加了动态修改innodb_buffer_pool_size值的功能(WL#6117).。这个功能可以在无当机的情况下修改缓冲池的大小。参见Yasufumi Kinoshita的文章:“Resizing the InnoDB Buffer Pool Online“。

我们已经实现了 UNDO 日志的自动分割,如果 UNDO 分片大小已经配置就可以使用((WL#6965). InnoDB 的操作有多个 UNDO 表空间会定时分割,一次一个。当一个 UNDO 表空间正在被分割时,其他的 UNDO 表空间可以继续为分割管理服务以将分割过程的影响降到最小。这个功能的目的是为了防止在一些应用场景中发生的 UNDO 日志文件过大问题。参见 Scott Ellsworth 提交的 Bug#1287 。

我们已经增加了在线 ALTER TABLE, RENAME INDEX (WL#6752, WL#6555) 操作,扩展了VARCHAR 数据列的操作大小(WL#6554)。

通过新的命令 CHANGE REPLICATION FILTER,我们实现了一个从服务器可设置选项–replicate-*settable (WL#7057)。这些选项可以在服务器运行期间动态修改,使用用户可以修改复制过滤规则,不要停止或重启服务。这个工作起源于 Davi Arnaut 的贡献 (Bug#67362)。参见 Venkatesh Duggirala’s 的文章 “Making MySQL Slave Replication Filters Dynamic“。

我们已经可以在不停止复制的情况下执行 CHANGE MASTER(WL#6120)。使用 CANGE MASTER TO 添加或修改选项,在以前要先先执行 STOP SLAVE 然后执行 CHANGE MASTER TO 命令。这个工作放松了这个限制。参见 Shivji Jha的文章 “Change master without stopping slave altogether“。

优化改进

深入优化区才是最令人兴奋的事,就像新的Cost Model,一个新的升级的分析器,一个优化架构分层 , 和一个新的 GIS 实现。另外我们已经实现了下面的功能需求:Query Rewrite Plugins (WL#7589) : 我们已经实现了查询重写插件,以及为使用者写他们自己定制的查询重写插件提供了一个框架(API)。查询重写插件指定了怎样确定一个已发送到服务器的查询应该在他们被服务器执行之前被重写。一种用法是通过添加一个标记到查询里去增强/阻止一个确定的查询计划。我们的查询重写插件是最好的工具 ,特别是处理那些当用户不能在应用内部重写查询时的查询,例如:由于它是从一个外部工具(如对象关系映射工具 Hibernate)衍生而来的或从一些第三方应用。见 Martin Hansson 的文章“ 写自己的查询重写工具:Part 1” 和“Part 2“。

对 FROM 子句中的子查询的处理和 view(WL#5275)一样:我们对派生表和视图有统一的扩展,目前,FROM 中的子查询(派生表)已经完全物化,而从相同查询表达式创建的视图则有时物化,有时合并到外部查询。这种做法存在不一致问题,会导致严重的性能问题,这项工作解决了 Bug#59203,Bug#67631, 和 Bug#1275。

让索引的切换代价最小化(WL#6986):为了支持”ORDER BY … LIMIT N”,我们已经做出决定make_join_select()。这项工作解决了Bug#73837。

使用范围扫描替换“IN queries”使用行值表达式(WL#7019) :我们删除了以前将 WHERE 条件重写进等效 AND/OR 形式的前置条件。见 Mark Callaghan 报告的 Bug#31188 和 Domas Mituzas 报告的Bug#16247。和 Martin Hansson 的文章“Range access: now in an IN predicate near you“.

“UNION ALL” 不再创建一个临时表 (WL#1763) : 如果没有必要在 5.7 优化器将避免为 UNION ALL 查询创建临时表,例如,没有顶级的 ORDER BY 子句。在执行大的联合查询时这将减少磁盘空间和磁盘 I/O when ,有时这是很重要的,终端将会立即获得第一行。见 Mark Callaghan 报告的Bug#50674 ,还有 Norvald H. Ryeng 的文章 “State of the UNION“。

在排序缓冲中的非存储字段不受影响N(WL#1509)
: 这项优化有助于更好的利用排序缓冲区,从而避免或减少在排序时使用磁盘。用户的好处是提高查询性能。

EXPLAIN 的运行查询(WL#6369) : 如果你在一个 session 里要运行一个耗时的查询这个功能非常有用;使用EXPLAIN FOR CONNECTION;在另一个 session 上运行可以产生关于对延迟原因有用的信息以帮助你优化你的模式和表达式。

JSON EXPLAIN (WL#6510) : 我们已经通过打印整个查询消耗,每张表的消耗,和数据处理数量的方式增强了JSON EXPLAIN输出。这将会让用户更容易看出好的执行计划和坏的执行计划。见Øystein Grøvlen的文章“MySQL EXPLAIN 说明“。

条件过滤在优化器中使用(WL#6635)。这项工作提高了连接排序(Cost Model 操作的一部分)。我们通过不仅考虑选择入口方法的条件,而且也考虑所有其他相关条件的方式获得了很好的前缀列的估算。  见 Jørgen Løland 的文章“从新的角度看 MySQL 查询优化” part1 和 part2 。

改进 ONLY_FULL_GROUP_BY SQL 模块(WL#2489):我们已经改进了 ONLY_FULL_GROUP_BY SQL 的工作模式并且也默认在 5.7.5 以上版本可用。由于服务器目前也意识到了函数依赖,因此这项工作让SQL模块远不如严谨的选择/排序表达式 。 所以这项工作也引起了很多用户抱怨,例如在 Roland Bouman 的文章“揭穿分组的神话” 和 Bug#51058。见 Guilhem Bichot 的文章“MySQL 5.7: only_full_group_by 改进, 意识到函数依赖, 默认可用!“。

分析器重构

我们以增量方式进入了重构 SQL 分析器阶段。由于旧的分析器的复杂语法和自上而下的分析方式而导致缺乏可维护性和可扩展性,因此它已经不能满足要求。迄今为止我们已经做了很多准备工作(WL#5967, WL#7199),重构 SELECT 声明 (WL#7200),  SET 声明 (WL#7203),INSERT/REPLACE  声明(WL#7201),DELETE  声明 (WL#7202) 和 UPDATE 声明 (WL#8062)。我们计划重写整个分析器。见 Gleb Shchepa 的文章“MySQL 5.7.4 LAB release 重构解析器“。

优化标记

为了优化标记我们已经增加了分析规则来支持新的标记语法(WL#8016)。目前在一个 SQL 语句内,标记可以在 SELECT|INSERT|REPLACE|UPDATE|DELETE 关键词之后直接指定,但是他们必须放在/*+ */以内。这不仅为最终用户提供了较为一致的和容易使用的管理标记方法,而且内在的重构也让它更容易地从前端为服务器端添加额外的标记 (见 WL#8241 和 WL#8243 以下)。我们也实现了通用的功能(WL#8017)对所有的标记提供新的语法(见 WL#8016)。这包括:1.在解析期间连接相关查询块和标记的数据结构。2.为解决数据库对象名称(例如表名,索引名等等)的功能函数和关联相关对象的标记。3 .优化器能够用于在当前查询内查找标记的一个数据结构。

我们已经添加了新的“索引层标记”,这种索引标记可以让用户控制应该成为索引条件下推(ICP),多范围读(MMR),和范围优化的候选索引(WL#8243)。我们也已经增加了一种新的标记,这种新的标记可以替代表的设置,而让用户设置优化器在执行查询期间决定是否使用连接缓存或批量关键字存取(WL#8241)。

我们还新增了控制子查询执行策略的标记(WL#8244)。这包括是否使用半连接,使用哪种半连接策略,如果不使用半连接,那么是使用子查询实例化还是 in-to-exist 转变。这项功能使用了由 WL#8016 和 WL#8017 提供的新的语法和基本功能来标记。注意:这项功能可以阻止任何特定的半连接策略,包括不能通过使用–optimizer_switch来关闭的多淘汰策略。

优化器重构

前面提到的分析,优化,和执行的阶段都涉及到了这部分内容。几乎每一个模块都涉及到不同的部分和优化器部分。因此,维护代码库的消耗变得很高而且不易扩展。我们以清晰的分离这些部分为目的而开始优化器重构项目。由于代码库的重构,优化器变得非常快。例如,我们明白这是作为提高我们的预处理语句的先决条件。见 WL#6016,  WL#6042,  WL#7082, WL#7540, 和 WL#7870 和 Guilhem Bichot 的文章“ MySQL5.7:重构预处理语句的内核“。

面向新的消耗模块

消耗模块项目的动机和概述在 Jørgen Løland 的文章 “MySQL 优化 Cost Model 项目“里有描述 。在 5.7 上为了“条件过滤”(part1 和 part2)和“准确的 InnoDB 统计”,我们改进的 DBT-3 的性能。另外我们也已经为其他的很多目标奠定了基础,例如,由于代码重构,用户消耗数量变得可控,并且可以了解到数据消耗是在磁盘上还是在缓存上。

我们开始了重构已有的消耗模块代码并清除了难以理解的代码。这是为了让代码更加的稳定,并且尽可能多的让用户为他们自己的硬件环境配置和调整,这也为存储引擎提供数据请求消耗因子是在缓存上还是磁盘上,奠定了基础工作。我们也做了些基础准备工作,并清除费解的代码。目前已经替换成,普通用户通过配置改变消耗值,服务器管理员可以调整消耗值,而不需要改变源代码。(WL#7182, WL#7209, WL#7338, WL#5869, WL#6068, WL#7339, WL#7276, WL#7315, WL#7316, WL#7168)。

我们已经扩展了消耗模型优化器。这个旧的优化器可以让存储引擎估算一张表目前在内存中大约需要多少行和多少索引(WL#7340)。而新的优化器将使用不同的消耗常量来计算获取在内存中的数据和需要从磁盘中读取的数据的消耗。在最初的实现里,这两个消耗常量有相同的默认值,但是可以通过服务器管理员修改让优化器在内存中缓存的数据和需要从磁盘读取的数据使用不同的消耗常量。而目前,估算关于数据是否在内存中还是需要从磁盘中读取仅仅基于探索算法。而当这些估算支持通过独立于存储引擎而实现时,这些估算的精度将会有很大的提升。

分页压缩

我们已经在 InnoDB 层实现了透明分页压缩 (WL#7696)。这个功能可以在任何操作系统/文件系统中组合运行,并支持稀疏文件和“打孔”(例如:fallocate 函数的 FALLOC_FL_PUNCH_HOLE 标示)。这其实很简单——给一个 16K 的页面,我们使用你最喜欢的压缩算法压缩它,然后输出压缩后的数据,接下来我们“打一个空”释放 16k 块中没有使用的部分到文件系统中。

InnoDB 全文检索

在 5.6 中,我们介绍了 InnoDB 全文搜索。目前,我们添加了更灵活性和更加优化的全文搜索。例如,目前在全文本索引支持外部的分析器,就像 MyISAM (WL#6943)。插件可以替代内置分析器也可以作为一个前端来使用。见来自 Daniel van Eeden 和 Hartmut Holzgraefe 的功能需求(Bug#68816) 。我们也实现了标记优化器,这个优化器可以将查询传递到 InnoDB ,因此 InnoDB 可以跳过全文检索部分,例如,如果不需要,他们可以不用计算排序值 (WL#7123)。见 Shaohua Wang 的文章“InnoDB 全文索引支持插件分析器”和 Matt Lord 的文章“ 使用 InnoDB 的全文检索排序“.

我们也在 InnoDB 上实现了支持 CJK(中文,日文,和韩文)的全文检索 (WL#6607):我们为 CJK 提供了一个默认的全文分析器 (N-GRAM 分析器) 和一个为日文提供支持 MeCab 的备选插件。用户也可以使用可插拔分析器实现他们自己的支持 CJK 的全文检索分析器插件。见 Shaohua Wang 的两篇文章“InnoDB Full-Text : N-gram Parser”和“InnoDB Full-Text: MeCab Parser“。

性能架构

对于我们的用户和任何数据管理系统来说,监控都是非常重要的。在这方面我们的目标是要做到一流的水平。我们的监控的核心策略包含 MySQL 5.5 引入的 性能架构。这是一个特殊的 MySQL 存储引擎,用来存储动态创建的事件,然后以惯用的 SQL 接口提供对事件和对应配置的查询。5.7 版我们继续提供对监控的扩展和增强,通过 性能架构 架构,我们可以提供这些对这些信息的监控:Metadata Locking (WL#5879),事务 (WL#5864), 内存使用 (WL#3249, WL#7777), Stored Programs(WL#5766), Prepared Statements (WL#5768).

在性能架构里我们还提供了 SHOW SLAVE STATUS 信息(WL#3656) 和 用户变量(WL#6884) 。我们还提供了全局和会话级别的状态和变量(WL#6629),同时为了向前兼容继续支持SHOW STATUS 和 SHOW VARIABLES 命令。另外,还提供了对长时间运行的操作进行统计 (WL#5889) 。

我们已经提高了内存分配的性能架构(WL#5889) 。此前的性能架构当服务启动时会分配所需的所有内存。现在我们可以根据服务负载自动调整内存消耗,从而降低开销(WL#7802)。我们通过重构性能架构的内部缓冲减少内存的使用,当数据表过多时,表结构导致的内存过载会有所改善。(WL#7698) .

我们通过允许用户/主机排除提高易用性(WL#7800) .这了实现这一点,一个名为 ENABLED 列已经添加到表 setup_actors 为用户提供排除或包含指定规则的能力。 我们已经提供了两个与查询文本长度 —SQL text 和 digest—匹配的实体 (WL#7270). 两者默认大小1024 bytes。

现在我们通过标准接口—PERFORMANCE_SCHEMA.THREADStable,  Audit log API,  Audit log file, 和 General Query Log (WL#7729)暴露连接类型信息。到现在为止 MySQL 没有为 DBA 提供已经建立和使用的连接可视化;例如区分未加密的 TCP/IP 连接 , 或者 socket,共享内存或者管道连接。

现在我可以对单个线程打开或关闭历史记录 (WL#7795) 。到目前为止,全局自定义标记已经可以用来控制是否记录历史事件的日志。这些标记对服务器来说是全局的,因此不同线程的历史事件的集合有的有,有的没有。对于这个功能,现在 DBA 可以对会话,账户, 用户, 和主机指定他们想收集的历史记录,而独立于基本的打开或关闭设置。这让 DBA 更加精确的控制什么样的事件可以在历史数据表里记录日志,从而减少了当历史数据仅需要基础会话的子集时的运行负载,也减少了在 Performance  Schema 表中不想要数据——events_waits_history_long, events_stages_history_long, events_statements_history_long, events_transactions_history_long——这些数据有助于在繁忙服务器上促进故障排除(也会产生很多事件)。见 Mayank Prasad 文章“Performance Schema implementation Internals: Registering instruments“, “MySQL Performance Schema : Prepared Statements Instrumentation“, “MySQL Performance Schema: Instrumentation Exceptions“, 和“MySQL Statement Digests“.

SYS 模式

我们已经在 MySQL 服务里默认的整合了 SYS Schema(以前的 ps_helper) (WL#8159)。在过去的一年里 MySQL SYS schema 项目在我们的基础用户中广受欢迎。在我们的基础用户中的许多 DBA 和开发者注意到它更加简单的配置和查询 Performance Schema,也更加的简单的整合它和 Information_Schema,还有其他更多功能。例如,看一下这篇文章,也可参考 Mark Leith 的文章“The MySQL SYS Schema in MySQL 5.7.7“。

Fabric支持

在 2014 年 5 月 27 日,Oracle 宣布了 GA 支持 MySQL Fabric。目前服务器团队正在为提高切片,故障转移,和服务器集群管理而改进一些功能。

我们已经为清理会话状态而实现一个新的服务器方法(WL#6797)。现在用户可以重置已有连接,例如,清理已有的会话和释放资源。

我们也增加一个新的服务器方法来实现离线服务器(WL#3836)。这个功能为升级和其他的维护而使用。设置服务器处于离线模式可以优雅的断开所有连接的用户除了那些有超级权限的用户。当系统处于离线模式时,“超级”用户可以连接和管理系统。

我们增加了一个服务器标记来检测已经发起的新的事务 (WL#6631)。session_track_transaction_state 是一个新的系统变量。在一个负载平衡的设置里,需要知道在新的事务启动时,哪一个连接器可以转换,从而从连接池里使用不同的连接。关键就在于检测当事务“刷新”时并且还没有对事务做任何读写操作。那么仅仅在这种情况下连接器可以转换使用不同的连接,如果一个声明启动一个新的事务并有读写操作,那么就不能再转换连接,除非先做一个 ROLLBACK 操作。

我们来介绍一个基于 DBA/Application 定义标志的同步机制 (WL#6940,WL#8161)。一个有超级权限的用户可以在服务器设置一个全局的标志(例如一些 ID)并且客户端可以设置会话标志。在执行查询之前,会话标志会和全局标志比较,如果这两个标志不同就会触发一个错误。

默认安全

MySQL 5.7 的目标是成为发布以来最安全的 MySQL 服务器,这就是说在 SSL/TLS 和全面安全开发方面有一些重要的改变。

MySQL 开发现在默认是安全的(WL#6962)。安装的过程中只创建一个 root 账号,root@localhost,并随机自动的为这个账号生成一个密码,而且标记这个密码为过期状态。然后 MySQL 管理员必须使用 root 和随机生成的密码登陆,然后使用 SET PASSWORD 命令设置一个新的密码。

安装过程中创建非随机用户账号,默认没有演示相关文件(WL#6977, WL#6973,WL#7787)。测试数据库和演示相关文件在其他包下。

我们简化了 mysql 服务器安装后的初始化过程,也移除了 mysql_install_db
这个玩意(以前安装过mysql的同学应该清楚这个脚本,可以手动初始化数据库)(WL#7307),现在只要添加上 –initialize 参数即可,像这样
>mysql
–initialize.运行这个命令之后会自动初始化数据库,建立缺省的数据目录并构建数据库。同时,还可以生成一个带有高强度随机密码的用户(但这个密码被标记为过期,也就是说第一次登陆之后,管理员要通过 SET PASSWORD 修改密码)

我们给参数 –secure-file-priv (指定LOAD DATA, SELECT … OUTFILE, and
LOAD_FILE()命令的作用路径)添加了一个安全的默认参数(之前的版本没有默认值)(WL#6782),主要是为了文件读写权限的作用域安全而考虑。加了这个参数后,如果用户的配置文件有不安全因素,数据库在启动时给出警告提示

我们重新定义了 –ssl 参数进行强制加密连接了(WL#6791)。以前,即使
MySQL 客户端在连接服务器时指定了 –ssl 参数,如果没有执行加密连接,依然可以连接服务器。现在指定了这个参数,如果没有 SSL
加密连接,连接就会失败。同时,我们也给 mysqlbinlog 添加了 SSL 支持(WL#7198)。

在安装期间,我们提供了“最佳努力”SSL 安装进程。如果安装成功,MySQL 服务的配置文件也可以修改成新生成的证书和密匙(WL#7706)。不管它什么时候在服务器里启用,我们都会确保 SSL 的使用。如果 SSL 选择定义了 none,那么如果服务器支持这样做,libmysql 客户端就会尝试 SSL 连接。如果 SSL 连接不可用,那么 libmysql 客户端将会使用未加密的连接。参见 odd Farmer’的文章“SSL/TLS in MySQL 5.7” 和 “对第三方产品来说 TLS 计划的意义“.

我们已经增加了— require_secure_transport 服务器选项,这可以让 MySQL 服务拒绝任何没有使用 SSL 的 TCP/IP连接。在这之前,MySQL 服务仅仅提供了一个为独立用户账户在多种账户管理报表中使用 REQUIRE SSL 条件的机制。

我们改变了 sql_mode 的默认值,包含了 NO_AUTO_CREATE_USER(WL#8326)。这是为了防止 GRANT 语句在无意和自动的创建新的用户时而没有提供/设置任何权限信息。

安全特性

除了“默认安全”的安装之外。我们也增加了许多个性安全来帮助用户保持他们的数据库实例远离意外使用。这包括了较好的数据加密,较好的密码处理,较安全的传输层等等。

目前,我们也支持了多 AES 加密模式 (WL#6781)。我们也增强了我们的高级加密标准(AES)加密/解密函数 AES_ENCRYPT() 和 AES_DECRYPT() 的安全强度——通过增加对较大密匙长度和不同的块模式的支持。参见 Georgi Kodinov 的文章“在 MySQL5.6.17 里理解和满足你的 ASES 加密需要“。

我们在 mysql.user 表里增加了一个时间戳字段用于保存密码最后一次改变的时间(WL#7131)。这为密码轮换政策的实行提供了基础。参见 Todd Farmer 的文章 “MySQL 实施密码策略“。

我们通过扩展 CREATE USER 和 ALTER USER 命令实现了对用户账户(登陆权限)的可用(解锁)或不可用(加锁)的设置(WL#6054)。参见 Todd Farmer 的文章“构建一个好的 CREATE USER 命令“.

我们扩展了内置身份认证插件用以支持代理用户(WL#7724)。MySQL 已经有一个可以支持主要用户功能的代理用户的概念。比如 SQL 角色:从权限分配里抽象出用户标识/身份的功能。这允许多个用户——在不同的方式中的定义,日志,和审核——分享一个单独的管理权限的设置。在部署很多个已经定义了权限的用户时,这提供了操作上的便利,但是直到现在,通过扩展身份认证插件,代理用户促使了这种改变。这清除了以前的限制。参见 Todd Farmer 的文章 “在 5.7.7 中使用扩展的代理用户模仿角色“。

我们还增加了用户名的最大长度,从 16 个字符倒 32 个字符(WL#2284)。

我们已经在 CREATE USER 和 DROP USER 命令里实现了 IF [NOT] EXISTS 条件判断。这可以让分布式账户在复制组内使用非同步账户事件时(故意地),复制而不会触发复制失败。这也简化了账户管理操作的脚本。见在 Bug#15287里的特性请求。

InnoDB 的本地分区

我们已经增加了对 InnoDB 本地分区的支持(WL#6035)。到目前为止,对 InnoDB 分区的支持依赖于 ha_partition 处理器,这个处理器可以为每一个分区创建一个新的处理器,当使用很多分区时,这个处理器也相应的浪费了很多资源。通过在 InnoDB 内对本地分区的支持,你可以使用更少的整体资源(见: bug#62536, bug#37252, 和 bug#70641)。InnoDB 的本地分区也为较好的整体分区铺平了道路。这包含诸如并行查询进程,改进分区裁剪(由于较精确的计数统计),外键支持,全局二级索引,和在分区表上的全文本搜索之类的功能。作为这项工作的一部分也已经从分区处理器类中的特性部分分离出了它自己的分区接口(WL#4807)。这是为了重构成模块化,并且从其他的服务器基础代码中解耦分区引擎。

另外,我们为分区表增加了对索引条件下推(ICP) 的支持 (WL#7231, 来自于 Bug#70001)。我们也增加了 EXCHANGE PARTITION 命令的 对[{WITH| WITHOUT} VALIDATION]条件的支持 (WL#5630, 来自于Bug#57708)。我们还为已分区的InnoDB 表增加了可移动表空间 的支持。见 Mattias Jonsson的文章“MySQL 5.7.4 目前对InnoDB分区支持可移动的表空间“。

InnoDB 的通用表空间

我们新增了CREATE TABLESPACE 语句来创建一个通用表空间(WL#6205, WL#8109)。这个功能可以让用户自由的选择表和表空间之间的映射,例如,表空间的创建和这个表空间应该含有什么样的表。这也让在同一个表空间的用户或客户对所有的表分组,因此在文件系统的一个单独的文件内持有他们所有的数据。我们也为通用表空间实现了元数据锁 (MDL)(WL#7957)。这主要是为了满足 InnoDB 中新的普通表空间,也为了已有的 NDB 集群通用表空间。

InnoDB 临时表性能

优化普通 SQL 临时表性能是 5.7 的目标之一。首先,我们通过避免持久化临时表到磁盘时的不必要的步骤,使得临时表的创建和移除成为一个轻量级的操作。我们将临时表移动到一个单独的表空间(WL#6560) ,因此对于临时表的恢复过程就变成了一个在启动时仅仅简单的重新创建临时表的单一的无状态步骤。我们去掉了临时表中不必要的持久化(WL#6469)。临时表仅仅在连接/会话内可见,创建它们,通过服务的生命周期绑定它们。我们通过移除不必要的 UNDO 和 REDO 日志,改变缓冲和锁,从而为临时表优化了 DML(WL#6470) 。我们增加了 UNDO 日志的一个额外的类型 (WL#6915),这个类型是不可 REDO 日志和保留在一个新的单独的临时表空间。这些 non-redo-logged UNDO 日志在恢复期间不需要,仅在回滚操作是需要。

第二,我们也为临时表设定了一个特别类型,我们称之为“内在临时表”(WL#7682, WL#6711)。内在临时表和普通临时表很像,只是内在临时表使用宽松的 ACID 和 MVCC 语义。目的是为了支持内部模块的内部用例, 例如,优化器为了中间操作而要求轻型和超快速的表。那么我们就让优化器使用 InnoDB 的“内在临时表”作为内部储存(WL#6711)。最终,我们让 InnoDB 的默认引擎使用 内部临时表 。见 Krunal Bauskar 的文章“MySQL 5.7: InnoDB 内在表“。

缓冲池 —— 卸载和加载

我们改进了缓冲池卸载和加载场景(WL#6504)。目前可以卸载每个缓冲池中仅最热的 N% 页。加载操作减少了对用户活动的破坏性,因为现在的加载是在后台为客户提供服务的;也不会尝试着太据有侵略性和从服务新的客户请求中占据太多的 IO 资源。见 Tony Darnell 的文章 “MySQL 卸载和加载InnoDB 缓冲池“。

我们也通过默认和改变默认百分比到 25% 的方式改变服务器使用缓冲池加载和卸载 (WL#8317)。这也使得在 1. 支持“热”工作数据设置和 2. 关闭和启动次数之间形成好的默认平衡。

工具

服务器附带一个实用程序或脚本(工具)的设置。这是为了提供和增加更多的工具。我们也想去除“脚本”而使用 C/C++ 从而改进可移植性,覆盖更多的使用场景(一个可以运行在所有环境下的脚本)。

我们实现了一个新的 MySQL 服务器工具叫做 mysqlpump,通过 mysqldump (WL#7755)调用——但不是 100% 的兼容。这个新工具的主要特点是可以执行并行的备份和存储操作(已有的 mysqldump 将继续被支持)。

我们也扩展了 innochecksum 工具的功能(WL#6045)。目前可以指定校验值算法(innodb/crc32/none),使用指定的算法重写当前的校验值,即使当前的校验值不可用也可以重写,允许在终止程序之前指定最大不匹配校验值。innochecksum 目前也可以在多个表空间文件和相同表空间的多个文件上操作。见 Anil Toshniwal 的文章“Improving Innochecksum“。

我们重写了mysql_upgrade 工具 (WL#7308),这个工具解决许多已报告的 bug,也使得mysql_upgrade 更加的稳健和易于维护。例如,它解决了 Nicholas Bamber 报告的 Bug#65288 和Florian Weimer 报告的 Bug#71579 。

我们增加了 SSL 选项和支持 mysqlbinlog 客户端程序(WL#7198),这允许系统管理员通过安全连接执行远程 binlog 查询 (–read-from-remote-server) 。这是上一版没有 SSL 支持的 MySQL 客户端程序遗留下来的。

我们已经转化 mysql_secure_installation 脚本为 C/C++(WL#6441)。这个程序现在可以使用 C API(libmysql) 执行指定的命令直接连接到服务器。这取消了对于在文件系统中一个临时选择文件来存储用户提供的密码的需要。

为了让程序可以在所有平台上使用——特别是 Windows,也为了提供更好的用户体验,覆盖更多功能,提高安全性而重新设计程序,我们开始了转 换mysql_install_db 脚本为 C/C++ (WL#7688)。在 5.7 之后的版本里,我们决定将这个功能回归到服务器本身(见 WL#7307)。在 5.7 里 mysql_install_db 程序,可以被使用,但是不再被需要,我们计划在以后的版本里删除这个功能。

社区贡献

服务器端语句执行超时(WL#6936) :这是基于 Davi Arnaut 提交的贡献(Bug#68252)。这个功能是为顶层 SELECT 语句的执行实现了一个服务器端的时间限制。一定的时间之后,语句就会被中止而不会影响到会话(连接)或者事务上下文。见 Praveen Hulakund 的文章“服务端 SELECT 语句超时“。

多用户级锁:允许通过 GET_LOCK() 获得多个锁(WL#1159)。用户级锁经常用在访问一些资源时而表或者行级锁不适用的情况下实现互斥 。这个功能允许每个连接都拥有多用户级锁。而这个功能就源于Konstantin Osipov 的贡献(Bug#67806)。见 Dmitry Lenev 的文章“一个贡献者的故事“。

触发器

BEFORE 触发器没有为非空列执行 (WL#6030) :这个功能确保了在 SQL 语句结束后对列约束的检查。这符合 SQL 标准。在 5.6 和早期版本中,MySQL 对列约束的检查太早。见由 Peter Gulutzan 报告的Bug#6295,和 Dmitry Shulga 的文章“MySQL 的 BEFORE 触发器和非空列“.

表的多触发器(WL#3253) :这个功能为每个动作(INSERT, UPDATE, DELETE) 和时机(BEFORE or AFTER)都拥有多个触发器成为可能。这也符合 SQL 标准。见 Dmitry Shulga 的文章“为动作/时机的相同值支持表的多触发器“。

IGNORE 子句

定义和重新实现 IGNORE (WL#6614) :这个工作适当的定义了 IGNORE 子句的意思和处理,这是 MySQL 对 SQL 标准的扩展。重新实现 IGNORE 以便一致的通过对所有 SQL 语句的支持,也让 IGNORE 更加易于维护。见 Bug#30191,Bug#49539,Bug#55421,Bug#54543, Bug#54106, Bug#49534, Bug#47788, Bug#46539, 和 Bug#46425。 见 Abhishek Ranjan 的文章“改进 MySQL IGNORE 的实现“.

STRICT 模式

定义和重写 STRICT 模式 (WL#6891):我们已经让 STRICT MODE 的行为一致的通过了对所有 SQL 语句的支持。我们也让 STRICT MODE 默认的支持事务存储引擎 (WL#7764)。为了允许语句跳过(多)行而让 IGNORE 子句下调错误为警告,否则会让整个语句中止。而 STRICT MODE 却在做相反的事情——将警告升级为错误。类似于 IGNORE,STRICT MODE 也没有提前做一个清晰而一致的定义。因此,实现就出现很多这样的 Bug,像Bug#42910, Bug#5929, Bug#43880, Bug#48637, Bug#5912, 和 Bug#5913。见 Abhishek Ranjan 的文章“在 MySQL 中改进 STRICT MODE “。

错误报告和日志

介绍一个在5.7版本中独立的错误代码(WL#8206):在5.7版本中,它为新的服务器错误消息实现了一个单独的范围的数值。这些代码目前是连续编号的,从1000开始。我们的客户端使用的错误代码范围是2000。问题是第一个区域的错误代码已经累积到1974,这意味着这两个范围将会重叠,这样就很难区分是服务器端的错误还是客户端的错误。现在新的5.7版本的服务器将会从3000开始。

错误报告——栈诊断域(WL#6406) :它实现了以SQL标准定义的栈诊断域。获得诊断(GET DIAGNOSTICS)声明已经扩展了获得【栈】诊断(GET  [STACKED] DIAGNOSTICS)。

错误报告 —— 大多数语句都应该清除诊断区(WL#5928) : 这让 MySQL 符合清空诊断区域的 SQL 标准,也解决了 Bug#35296, Bug#43012, 和 Bug#49634。

错误日志 —— 允许冗余控制(WL#6661, WL#6755) :这让 DBA 知道,当写错误日志(ERROR/WARNING/NOTE),MySQL 服务器应该怎样进行冗余控制。这也支持了多种时间戳格式(UTC 时间戳)的打印,并废弃已有的 fprintf(stderr, …) ,在服务层使用新的内部日志 API。

为在 Unixoid 平台的 Syslog 增加本地支持 (WL#7793) :这为日志服务器输出到服务器的本地系统日志提供支持,见由 Kyle Joiner 记录的 Bug#55370。并随后有 Simon Mudd 和 Marc Alff 进行了升级,见 Tatiana 的文章“MySQL 的日志:系统日志&事件日志错误日志“.

MySQL 客户端

使用 Syslog 记录用户交互命令日志 (WL#6788) : 这个工作引入一个新的选项,–syslog,  该选项可以开关 logging 属性就像 sudo_user (或者user), mysql_user, connection_id, db_server, DB, 和在交互 session 输入的查询. 这是应一些用户的审计需求,比如要求将所有交互命令行的输入即时记录到 syslog.

客户端协议追踪(WL#6226)
: 这项目工作在客户端代码包中添加了钩子用来追踪协议事件,如向服务端发包,接收服务端返回和心跳鉴定. 这提供了一个机制可以从客户端的视角收集客户端和服务端的连接性能。

客户端-服务器协议

为了(WL#8077)的转义,就得知道字符串类型,因此扩展了mysql_real_escape_string():我们为函数mysql_real_escape_string_quote()增加了一个“引用类型”的参数。这是为了明确单引用字符串和双引用字符串之间的区别。但这破坏了ABI,因此它不会回归到5.6。

扩展了现在的OK包:为了让服务端发送额外的信息而扩展的客户端-服务器协议的OK包,例如,服务器状态改变. 服务器现在默认的发送关于SET character_set和USE database命令的信息。这个避免了这样的状况,例如,SET NAMES big5之后服务器假定客户端将会发送big5编码的数据,然而客户端仍然使用latin1编码.

Session-Specific 的状态标志 (WL#6885) :这个标志可以让客户端通知服务端会话状态的改变。这个功能的一种用法是检查是否可以迁移一个用户的会话环境到一个负载均衡内或集群环境内的另一个物理连接。

GIS: InnoDB 空间索引

我们已经在InnoDB 内实现了空间(R-tree) 索引(WL#6968,  WL#6968,  WL#6745) : InnoDB空间索引可以被用于所有已有的为MyISAM空间索引开放句法规则。另外,InnoDB 空间索引支持完整的事务,ACID和MVCC 特性(以及隔离层)。空间索引采用了谓词锁的方式防止幻想问题。

我们已经增加一个新的InnoDB内部类型:DATA_GEOMETRY,我们将所有的MySQL的GEOMETRY 数据都映射到这个新的内部数据类型(WL#6455)。我也已经扩展了CHECK TABLE,目的是为了CHECK TABLE 能够判断任何空间索引是否是有效的(WL#7740)。母校CHECK TABLE 检查R-tree结构的有效性并确保入口数量匹配群集的索引。见 Jimmy Yang的文章“InnoDB Spatial Indexes in 5.7.4 LAB release“.


GIS:几何功能和格式

经过各种开源的几何引擎的仔细评估后,我们决定用 Boost.Geometry 代替我们原来的 GIS 算法。对于那些从源代码中构建 MYSQL,去阅读我们添加的新的 CMake options 是非常重要的。改变几何引擎并不是一个简单的任务,所以许多关于 GIS 的尝试都投入到了这个工作(WL#7220,  WL#7221,  WL#7224,  WL#7225, WL#7236, WL#7280,  WL#7420, WL#7929)中。在这过程中,我们已经修改了许多漏洞并且为许多额外的 SQL/MM 标准空间操作提供了支持作为增加的 GIS 的成就的一部分,我们已经开始清除 GIS 函数的命名空间。额外的构造函数和这些数据类型(Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon and GeometryCollection)有相同的名字并且有计算最小包围矩阵(MBRs)的功能,现在所有空间函数用标准的“ST_” (spatio-temporal)为命名前缀的规定,并且函数的名字没有那个前缀就被反对(WL#8055)。

支持两个新的导入导出格式, GeoJSON 和 geohash。这些支持已经丰存的 WKT 和 WKB。新的 GeoJSON functions ST_AsGeoJSONandST_GeomFromGeoJSON 将会解码和编码 GeoJSON 文档 (WL#7444)。新的geohash ST_Geohash,ST_LongFromGeohash,ST_LatFromGeohashandST_PointFromGeohash 会和 geohash 目前功能一样(WL#7928)。

我们还添加了一些帮助功能 (WL#8034): ST_Distance_Sphere, ST_MakeEnvelope, ST_IsValid, ST_Validate and ST_Simplify。其中 ST_Distance_Spheremay 可能是最激动人心的 。而 MySQL 的地理信息技术支持仍然只使用 2d 平面,ST_Distance_Sphere 将计算与给定半径的球体两个点(或多点)之间的距离。两个新的膜生物反应器的功能也得到了补充:MBRCoveredByandMBRCovers (WL#7541)。因为 MBR 函数在 MBR 做计算代替精确的形状,计算比ST_ functions 更快。

看看他们是怎么结合 的,参见 Matt Lord 的文章,“MySQL 5.7 and GIS, an Example。

多源复制

我们已经实现了多源复制  (WL#1697)。它允许一人从结点从多个数据源/主结点复制,但没有额外的冲突检索和处理。一个应用场景是委托一个子结点做数据聚合或备份。此前我们通过 MySQL Labs 做了第一次发布 ,当前版本考虑了当时从社区得到的大量反馈。参见 Shivji Jha’的文章“MySQL-5.7.6: Introducing Multi-source replication“。

复制 — 多线程站(MTS)

我们已经实现了内部多线程站(WL#6314)。受益于此实现 (–slave-parallel-type=LOGICAL-CLOCK) 子结点可以应用并行事务,即便在单个数据库或模式,只要他们具有不相交的读写设置,参见 Rohit 的文章“MySQL 5.7 Enhanced MTS: configuring slave for Intra-database parallelization“。

我们还实现了有序提交(顺序一致性)(WL#6813)。这将保证子结点应用多线程并行提交时在主结点上的顺序是相同的。这也意味着如果主结点没有扩展数据库的状态,从结点也不会。当应用从从结点读取时需要保证和主结点的状态一致,这是强制约束自从 WL#6314,它可以并行的从结点可以执行多个事务,多个从结点可能会修改一个数据库。

我们允许复制从结点到临时故障点后自动重试事务 (WL#6964)。在此之前,只有 non-MTS 复制从结点并尝试执行临时故障后的事务。见 Yoshinori Matsunobu 提交的 Bug#68465 。通过使用更精确的算法来确定哪些事务是非冲突的(WL#7165),最后我们改进了多线程站的性能,这使得当使用 –slave-parallel-type=LOGICAL_CLOCK 时可以并行执行多个事务,从而提高复制的性能。

半同步复制

当半同步复制功能(WL#7169)开启时,我们已经实现了一个主结点可以同步等待 N 个从结点应答而不是一个,通过选择 N 个从结点(N>1),可以增加容错的灵活性。同时改善事务的稳定性,因为事务被主结点外化后,两个结点的持续性会更好一些。此外,我们现在只在 ACK 被接收后(WL#6355)才做外化。这样,使用半复制以后可以真正的做无故障转移。如果主结点崩溃,从结点依然可以保证是最新的。此实现可以让主结点等待 ACK 发生在存储引擎准备并写入二进制日志后,向存储引擎提交之前。参见 Libing Song的文章“Loss-less Semi-Synchronous Replication on MySQL 5.7.2“。最后,我们已经通过使用单独的线程来发送和接收半同步确认(WL#6630)来减少半同步复制延迟。所以事件和 ACK 流现在可以同时发送和接收。

复制 — GTID

如前面提到的,我们提供了一种启用 GTID 的方法(WL#7083),在此过程中,允许读取和写入,并且服务器不需要同步。在此项工作之前,用户需要停止所有的更新和服务器同步并在稍后重启服务器。不管 GTID_MODE 的值为何,都要这样做(WL#7592)。除了确保一致性的操作,还有一种情况就是,你可能丢失 GTID_EXECUTED 和 GTID_PURGED 的值(细节请参考 WorkLog entry)。(本来是 WL#7083 的一部分)。还可以参考一下 Sven Sandberg 的文章:“在 MySQL 5.7.6 中不停机启用全局事务标识符 GTID“。

最后,我们实现了 GTID 的协议支持,以便于客户端感知到GTID。我们已经实现了一套机制,用于收集通过线路发送的响应包中必要的 GTID 设置(WL#6972)。同时,还在 MySQL 协议的响应包中添加了一个跟踪器(WL#6128)。这样做的目的是可以传输连接器的信息,这些信息是为实现会话一致性而收集的会话状态。

复制 — 重构

我们已经创建了一个稳定的接口,这个接口对 MySQL Group Replication 和其它服务器插件都很有用(WL#8007 和 WL#8202)。服务器插件现在可以以服务器回调的形式获知服务器的事件了。同时,我们将 MySQL 复制流中的事件反串行化分离到一个单独的模块中(WL#7440)。这次重构是为了打破服务器核心与复制框架之间的依赖关系。

其它复制特点

  • 非阻塞式 SHOW SLAVE STATUS (WL#6402) : 这项工作为 SHOW SLAVE STATUS 添加了一个非阻塞选项。新的选项使 SHOW SLAVE STATUS 与 STOP SLAVE 并行运行时是非阻塞的 (当从线程在等待进行大规模事件的 SQL 线程时,停止它可能要花费很长的时间)。
  • 给 mysqlbinlog 添加 Idempotent Mode (WL#6403) :这项工作给 MySQL 服务器提供了一种 idempotent 模式操作。在这种模式下,当从 binlog 文件中应用基于 ROW 的事件时,服务器会忽略错误。当数据库管理员想使用 mysqlbinlog 回放 binglog 时这个模式将很有用。对于没有包含全部数据的 MySQL 服务器,忽略可以预料的 duplicate-key 和 no-key-found 错误也相当有用。
  • 对于 ROW 事件给 mysqlbinlog 添加 Rewrite-DB 选项(WL#6404):这项工作为 mysqlbinlog 添加 rewrite-db 选项支持。这样一来,一个基于 ROW 的事件可以应用到一个不同的数据库/架构。例如:当从 binlog 中读取基于 ROW 的事件时用 “to_db” 替换 “from_db”。
  • Binlog_sender:不再重新分配(WL#7299):这项工作实现对移除发送缓冲非必要重分配线程转储的优化。用户可以看到,在主线程产生的每个线程转储中,CPU 使用率将明显减小。参见 Mark Callaghan 提交的 Bug#31932。
  • 将状态变量移动到复制性能架构表(WL#7817):为了满足多源复制的需求,这项工作将复制系统变量移动到性能架构表。这样就可以从每个源来监控这些变量,而不是简单地作为全局变量。
  • 使主从同步选项独立于从线程之外(WL#7796):这项工作添加了一个新的SQL函数WAIT_FOR_EXECUTED_GTID_SET,这个函数将会使主从同步选项独立于从线程之外。如果从线程没有运行WAIT_FOR_EXECUTED_GTID_SET(GTID_SET [, TIMEOUT])函数,那么从线程将会一直等待,直到成功 (0)或超时 (1)。
  • 优化被动从线程的GTIDs —— 将GTIDs存储进表中(WL#6559):这项工作添加了一个选项,可以将GTIDs存储到一个表而不是在二进制日志中。其应用场景可能是:一个从线程只用于扩展读取规模,不会成为主线程,因此对于二进制日志中事务的处理来说没有任何用处,但是,相关的GTID功能还是有可能用到的(例如启动故障转移到新的主线程)。
  • 等待更多事务进入Binlog Group Commit(BGC)队列(WL#7742):这项工作添加了引入手动延迟的新选项 –binlog_group_commit_sync_delay 和 –binlog_group_commit_sync_no_delay_count,新选项可以使二进制日志组提交过程暂停。这增加了从磁盘刷新和同步更多事务的可能性,因此减小了创建一个事务组花费的时间(组越大,同步操作越少)。正确地调优之后,在不比较主线程的吞吐量的情况下,它可以使从线程的性能提高数倍。
  • Binlogging 准备好的分布式事务(WL#6860):我们对复制添加了完整地分布式事务机制。分布式事务允许客户端参与二相提交协议。分布式事务的状态在数据库中持续准备着;这意味着一个准备好的分布式事务将会在客户端重连和服务器重启后任然存在。这项工作修复了Bug#12161。

其他改进

  • InnoDB:默认 ROW_FORMAT=DYNAMIC (WL#8307):这个引入了一个新的全局变量 innodb_default_row_format,指定默认的 ROW_FORMAT。默认设置为 DYNAMIC。可选的值有: REDUNDANT, COMPACT 和 DYNAMIC。
  • PERFORMANCE_SCHEMA,添加列 THREADS.THREAD_OS_ID (WL#8853):这个表明 “TID”,或者是线程/任务 identifier,通过底层操作系统定义。例如 Linux,对应的是 gettid()。
  • Sys Schema 进展报告(WL#8460):这个在系统模式上添加了长期运行事物的进展报告,通过把追踪工作 估计/完成 的阶段完成百分比放入到进展列表/会话 视图。
  • 报告支持 (WL#7804):这个实现了一个系统模式的步骤,允许 DBA 简单的从一个 MySQL 实例收集诊断的数据,形成调查和报告。
  • InnoDB: 实现 Information_Schema.Files (WL#7943):这个提供了数据给 INFORMATION_SCHEMA.FILES 表,所有的的 InnoDB 数据文件都在其内部的缓存。INFORMATION_SCHEMA.FILES 表包括字段来描述一个空表文件,包括一些静态统计细节。详情请看 Bug#76182。
  • 让 InnoDB 填充可设定的因素 (WL#6747):这个可以设定每个索引的 merge_threshold。直到现在,已经修复完成了 50%。如果页面填充的数据量小于 merge_threshold,比如,当通过一个 UPDATE 删除或一行或者进行缩短,InnoDB 会尝试合并到相邻的页面。这个提供了一个方式来降低 InnoDB 的覆盖硬盘脚本,也因为额外的页面合并而增加额外的工作量。
  • 支持 32k 和 64k 页面 (WL#5757):这个添加对 32k 和 64k 页面大小 (默认为 16k)的支持。更大页面大小可以帮助改善压缩率,因此可以提供更好的数据压缩。并且更大的页面大小允许更多 “on page” 或者
    “inline” 的 BLOBs 存储和大型 VARCHAR/TEXT 字段存储,因此提升 I/O 性能。
  • InnoDB 高优先级事物(WL#6835):这个实现了高优先级事物的 InnoDB,比如,事物不会在一个死锁场景被中止。这样可以更好的支持 MySQL Group Replication,一个事物不会在一个副本中中止,在另一个里面提交。
  • 确保 5.7 能从 5.6 中平滑的进行在线升级 (WL#8350):这个确保从 5.6 到 5.7 的在线升级,无需指定 –skip-grant-tables 作为中间的步骤。
  • 从 MyISAM 移动插件和服务器表到事务性存储 (WL#7160):这个使得 InnoDB 默认存储引擎用于 插件和服务器系统表 (MyISAM remains optional)。
  • DTrace 支持 (WL#7894):Server 5.6+ 包中我们添加了完整的 Dtrace 支持到 MySQL,而且支持 Oracle Linux 6+。
  • InnoDB 表 Update_time (WL#6658):这个实现了内存的 InnoDB 表 UPDATE_TIME 维护。这个功能之前在 InnoDB 中已经失效,因为用户再三要求,现在已经加上。详情请看 Bug#2681。
  • 截断 TABLE 语句,具备原子性 (WL#6501):这个使得内部 InnoDB TRUNCATE TABLE 语句具备原子性,通过使用相同空间 ID 来重新初始化原始表空间头部,物理上截断它的 .ibd 文件。
  • 完善连接 ID 处理 (WL#7293) :这个避免了任意仍然在使用的连接 IDs 复用。详情请看 Bug#44167。
  • GB 18030 中文字符集支持 (WL#4024) :这个添加了 MySQL 字符集 GB18030,支持中文国家标准 GB 18030 字符集。
  • 提供一个选项来拒绝存储引擎列表的用户表创建 (WL#8594) — 这个是 Thayumanavar Sachithanantha 提供的一个命令行选项 –disabled-storage-engines,提供给 DBA,禁用存储引擎列表,然后防止用户使用任意特定的存储引擎(错误的)。 这个支持用户有防止使用策略的用例,比如,MyISAM 和其环境。
  • Super-read-only 也可以锁定超级用户 (WL#6799) — 这个是 Todd Farmer 引入的新选项 –super_read_only,可以实现 –read_only 选项。当 –super_read_only 设置为 ON (自动设置 –read_only 为 ON) 时,服务器也会变为 READ-ONLY,即使拥有超级特权的管理员都会受到限制。

本文文字及图片出自 mysqlserverteam.com

余下全文(1/3)
分享这篇文章:

请关注我们:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注