MySQL NDB Cluster 8.0 发行说明  /  MySQL NDB Cluster 8.0.29 的变化(2022-04-26,全面上市)

MySQL NDB Cluster 8.0.29 的变化(2022-04-26,全面上市)

MySQL NDB Cluster 8.0.29 是 NDB 8.0 的新版本,它基于 MySQL Server 8.0,包括 NDB存储引擎 8.0 版中的功能,并修复了之前 NDB Cluster 版本中最近发现的错误。

获取 NDB Cluster 8.0。  NDB Cluster 8.0 源代码和二进制文件可以从 https://mysql.net.cn/downloads/cluster/获得。

有关 NDB Cluster 8.0 中所做更改的概述,请参阅 NDB Cluster 中的新增功能

此版本还合并了以前 NDB Cluster 版本中所做的所有错误修复和更改,以及通过 MySQL 8.0.29 在主线 MySQL 8.0 中添加的所有错误修复和功能更改(请参阅MySQL 8.0.29 中的更改(2022-04- 26,一般可用性))。

重要的

此版本不再可供下载。它被删除是因为一个严重的问题,该问题可能导致 InnoDB添加了列的表中的数据被错误地解释。请改为升级到 MySQL Cluster 8.0.30。

编译笔记

  • NDB由于数组越界错误,无法使用 GCC 11 构建。(缺陷号 33459671)

  • 删除了使用 GCC 9-Wstringop-truncation 编译时出现的一些警告NDB并抑制了此类警告。还从头文件中删除了不需要的包含ndb_global.h。(缺陷号 32233543)

ndbinfo 信息数据库

性能模式注释

  • ndbcluster现在可以在性能模式中看到插件线程。threads 和表显示了所有这setup_threads三个线程:二进制日志记录线程 ( ndb_binlogthread)、索引统计线程 ( ndb_index_statthread) 和元数据线程 ( ndb_metadatathread)。

    这使得获取这些线程的线程 ID 和线程操作系统 ID 成为可能,以用于查询这些和其他性能模式表。

    有关更多信息和示例,请参阅 ndbcluster 插件线程

添加或更改的功能

  • NDB Cluster API: NDB API 现在实现了 List::clear()一种从列表中清除所有数据的方法。listEvents()这使得使用 Dictionary 方法、 listIndexes()和 重用现有列表变得更加简单 listObjects()

    此外,List 析构函数已被修改,现在它会 clear()在尝试从被销毁的列表中删除任何元素或属性之前调用。(缺陷号 33676070)

  • 客户端接收线程只有在高负载时才启用,判断高负载的标准是在轮询队列(接收队列)中等待的客户端数量大于 min_active_clients_recv_thread(默认值:) 8

    这是确定高负载的糟糕指标,因为单个客户端(例如处理传入复制事件的二进制日志注入器线程)本身也可能会遇到高负载。推送连接查询也是如此(其中接收到非常大批量的传入TRANSID_AI信号)。

    我们更改接收线程,使其现在在轮询队列中休眠而不是完全停用,因此它现在始终可用于处理传入信号,即使客户端负载不高。(缺陷号 33752914)

  • 现在可以 使用带有此版本中添加的 选项的ndb_restore从备份 中恢复ndb_apply_status表 。在某些情况下,此信息可用于新设置新的复制链接。 NDB--with-apply-status

    --with-apply-status恢复 ndb_apply_status表中除server_id值为 的行之外的所有行0;用于 --restore-epoch恢复此行。

    要使用该--with-apply-status选项,您还必须--restore-data 在调用ndb_restore时提供。

    更多信息参见 --with-apply-status参考手册中对该选项的描述,以及 ndb_apply_status表。(错误#32604161,错误#33594652)

  • 以前,当用户查询试图打开 NDB一个缺少(或损坏)索引的表时,MySQL 服务器会引发NDB错误 Index not found。现在,当进行此类尝试时,将按此处所述进行处理: 4243

    • 如果查询没有使用有问题的索引,则查询会成功,不会出现错误或警告。

    • 如果查询尝试使用丢失或损坏的索引,则查询将被拒绝并发出警告 NDB索引 idx在 NDB 中不可用。使用“ALTER TABLE tblALTER INDEX idxINVISIBLE”来防止 MySQL 尝试访问它,或使用“ndb_restore - -rebuild-indexes" 来重建它)和一个错误(ER_NOT_KEYFILE)。

    此更改的基本原理是,违反约束或丢失数据有时会导致无法恢复NDB表上的索引,在这种情况下,运行 ndb_restore with --disable-indexes可以在没有索引的情况下恢复数据。通过此更改,一旦数据从备份中恢复,就可以使用 SQL 修复任何损坏的数据并重建索引。(漏洞#28584066)

修正错误

  • 重要更改:服务器选项 支持的最大值 --ndb-batch-size已从31536000增加到 2147483648(2 GB)。(缺陷号 21040523)

  • 性能: 在分析多线程数据节点 ( ndbmtd ) 执行包含大量插入的事务时,发现超过 50% 的 CPU 时间花在了内部方法 Dblqh::findTransaction()上。结果发现,当通过该方法查找到的哈希列表中有很多属于未提交事务的操作时,哈希桶会溢出,导致在哈希桶中查找会消耗过多的CPU周期。

    为了解决这个问题,我们将哈希桶的数量固定为 4095,并根据最大操作数缩放哈希桶的大小,以便现在只有相对较少的项目应该放在同一个桶中。(缺陷号 33803541)

    参考资料:另请参阅:Bug #33803487。

  • 性能: 在同一事务中向空表或小表中插入大量行时,插入行的速率迅速下降到初始速率的 50% 以下;随后,发现大约 50% 的 CPU 时间花在了 上Dbacc::getElement(),确定的根本原因是调整用于存储元素的结构大小的时间 DBACC,随着在同一事务中插入更多行而增长,并缩小提交后。

    我们通过检查是否需要在插入或删除元素后立即调整大小来解决此问题。这也处理随后拒绝插入。(缺陷号 33803487)

    参考资料:另请参阅:错误 #33803541。

  • 性能:EventBufData_hash::search()由于以下问题, 搜索事件缓冲区数据哈希(使用内部方法)花费了大量时间

    • 当哈希桶列表可能变得非常大时,桶的数量在高负载下被证明太低了。

    • 哈希桶是使用链表实现的。遍历一个长链表可能非常低效。

    我们通过使用向量 ( std::vector) 而不是链表,并通过使包含哈希桶集的数组可扩展来解决这些问题。(缺陷号 33796754)

  • 性能: 内部函数computeXorChecksum() 的实现非常小心,以帮助编译器生成最佳代码,但发现它消耗过多的 CPU 资源,并且性能不如更简单的实现。XOR这个函数现在用一个循环对数组的结果进行总结来重新实现(缺陷号 33757412)

  • Microsoft Windows: 数据CompressedLCP节点配置参数对 Windows 平台没有影响。

    笔记

    升级到此版本时,Windows 用户应验证设置CompressedLCP;如果它之前已启用,您可能会在升级后、负载下、作为节点重启的一部分恢复数据时,或在这两种情况下遇到 I/O 线程 CPU 使用率增加的情况。如果不需要此行为,请禁用 CompressedLCP.

    (缺陷号 33727690)

  • Microsoft Windows: 内部函数 Win32AsyncFile::rmrfReq()并不总是检查ERROR_FILE_NOT_FOUNDERROR_PATH_NOT_FOUND这两种情况可能出现的情况。(缺陷号 33727647)

  • Microsoft Windows: 更正了在 Windows 平台上处理文件时出现的几个小问题。(缺陷号 33727629)

  • NDB 复制: 在表上执行某些模式操作时 NDB,包括那些涉及复制ALTER TABLE中的纪元列mysql.ndb_apply_status更新为 0,尽管这应该只发生在源自存储引擎而非存储引擎的事务中 NDBCLUSTER

    为了解决这个问题,我们现在(仅)在从与前一个服务器 ID 相同的服务器 ID 写入一行时更新二进制日志位置ndb_apply_status,但在应用模式操作时不会覆盖当前纪元。(漏洞 #14139386)

  • NDB Cluster API: 使用内部 API 方法生成的哈希键 NdbBlob::getBlobKeyHash()忽略了键的最高有效字节。这不必要地导致 NDB API blob 哈希列表中的分布不均匀,从而导致对比较键值的需求增加,从而增加了 CPU 使用率。(缺陷号 33803583)

    参考资料:另请参阅:Bug #33783274。

  • NDB Cluster API: 删除了一个不必要的断言,该断言在遍历 Dictionary::listEvents(). (缺陷号 33630835)

  • 使用 GCC 11 在 Ubuntu 21.10 上构建,以 -Werror=maybe-uninitialized停止。(缺陷号 33976268)

  • 在某些情况下,NDB没有正确处理数据节点的节点 ID。(缺陷号 33916404)

  • 在某些情况下,NDB没有正确验证数据节点的所有节点 ID。(缺陷号 33896409)

  • 在某些情况下,数组索引没有得到正确处理。(错误#33896389,错误#33896399,错误#33916134)

  • 在某些情况下,整数没有得到正确处理。(缺陷号 33896356)

  • 作为 NDB 8.0.23 中为实现配置参数所做工作的一部分,ndbmtd 支持的LQHAutomaticThreadConfig 和 TC 线程的最大数量分别从 129 个增加到 332 个和 160 个。这对几个 NDB 内核块实现的方法的性能产生了不利影响,这些方法在调度程序即将暂停当前块线程的执行时完成打包信号的发送。这是由于尽管数组的大小增加了,但仍继续简单地迭代此类线程的数组。我们通过使用位掩码来跟踪整个数组旁边的线程状态来解决这个问题。(缺陷号 33856371)execSEND_PACKED()

  • 在对 blob 列进行操作时,NDB必须添加额外的操作来读写 blob 头列和 blob 部分行。这些操作在事务执行时自动添加到事务操作列表的尾部。

    L要在给定操作之前插入新操作,必须从头开始遍历操作列表,直到找到所需的操作,成本与前面操作列表 的长度成正比。这大约是 ,随着更多的操作被添加到列表中而增加;当批量定义大量修改blob的操作时,这个遍历成本是为每个操作支付的。这对读取和写入 blob 时的性能有显着影响。 L2 / 2

    我们通过在定义 blob 操作时使用列表拼接 NdbTransaction::execute()来消除这种不必要的遍历来解决这个问题。(缺陷号 33797931)

  • 块线程调度程序频繁调用 update_sched_config()以更新其调度策略。这涉及检查用于在节点的内部块线程之间发送信号的作业缓冲区队列的填充程度。当这些队列即将填满时,线程调度程序会 max_signals为下一轮分配一个较小的值,以减轻作业缓冲区的压力。当达到最小空闲阈值时,调度程序在等待消费者线程释放一些作业缓冲区时让出 CPU。

    NDB 8.0.18 中针对上一个问题的修复引入了一种机制,即使达到了这个较低的阈值,也允许主线程继续执行;在某些情况下,主线程消耗了所有作业缓冲区,包括保留的缓冲区,导致数据节点因资源耗尽而意外关闭。(错误#33792362,错误#33872577)

    参考:这个问题是 Bug #29887068 的回归。

  • ThreadConfig 使用参数(例如, ) 设置具有一个 LDM 线程和一个查询线程的集群ThreadConfig=ldm={cpubind=1},query={cpubind=2}会导致数据节点意外关闭。

    这是由于在没有显式分配主线程或请求线程时,内部线程变量被分配了错误的值。现在,我们确保在这种情况下,如预期的那样,为这些分配了第一个接收线程的线程号。(漏洞#33791270)

  • NdbEventBuffer非字符数据的哈希键生成重复使用了相同的 256 个哈希键;此外,在计算散列键时忽略零长度的字符串。(缺陷号 33783274)

  • 基于 EventBytesRecvdCount事件计数器的 NDB API 统计信息的收集产生了过多的开销。现在这个计数器使用一个在事件缓冲区被填充时聚合的值来更新,而不是在一个单独的函数调用中遍历所有事件缓冲区数据。

    有关详细信息,请参阅 NDB API 统计计数器和变量。(缺陷号 33778923)

  • 内部方法 THRConfig::reorganize_ldm_bindings()行为异常,在某些情况下更改线程绑定后 AutomaticThreadConfig 已经将线程绑定到正确的 CPU。我们通过删除该方法来解决此问题,在解析配置数据或添加线程时不再使用它。(缺陷号 33764260)

  • 接收线程 ID 在内部方法中进行了硬编码, TransporterFacade::raise_thread_prio()因此它始终会提高接收线程的优先级,即使是从发送线程调用时也是如此。(缺陷号 33752983)

  • NDBNDB 8.0.28 中的修复解决了各种组件 使用的代码问题,包括Ndb_index_stat检查数据节点是否启动并运行的代码。在具有多个 SQL 节点的集群中,这导致尝试在表上创建表事件的索引统计线程之间的竞争条件频率增加ndb_index_stat_head;也就是说,两个 SQL 节点可能会同时尝试创建事件,而失败的 SQL 节点会引发 Error 746 Event name already exists。由于这个错误,二进制日志线程最终等待索引统计线程发出其自身设置已完成的信号,因此第二个 SQL 节点超时--ndb-wait-setup几秒钟后 无法创建索引统计系统表。(缺陷号 33728909)

    参考:这个问题是 Bug #32019119 的回归。

  • 在写入错误时, ndbxfrm打印的消息引用了源文件而不是目标文件。(缺陷号 33727551)

  • 复杂的嵌套连接被拒绝,错误 FirstInner/Upper has to be an ancestor or a sibling,这是由用于在 SPJ API 中定义推送连接的内部 NdbQueryOperation接口抛出的,表明接口的连接嵌套依赖关系是没有正确定义。

    显示问题的查询具有连接嵌套结构 t2, t1, (t3, (t5, t4))。两个连接条件都没有对 table 有任何引用t5t4显式依赖 t3,但每个都有隐式依赖, t3因为它们位于 table 的同一个嵌套中t3

    准备推送连接时,通过将它们添加到每个表的位掩码来NDB跟踪表和连接嵌套之间所有必需的表依赖关系。m_ancestor对于嵌套级别的依赖项,它们都应该添加到相关嵌套中的第一个表中。当计算特定表的相关依赖关系时,它们包括连接条件中明确引用的所有表的集合,加上由于连接嵌套而导致的任何隐式依赖关系嵌套表是其成员,受限于引用的最上面的表加入条件。

    对于这个特定的连接查询,我们没有正确地考虑到最近的上层嵌套(以 开头的嵌套 t3)中可能没有任何对表的引用;在这种情况下,我们依赖于所有嵌套,直到包含引用的最上面的表的嵌套。我们通过引入一个 while 循环来解决这个问题,在这个循环中我们添加祖先嵌套依赖关系,直到我们到达这个最上面的表。(缺陷号 33670002)

  • 当内部使用的临时内存池 ( TransientPool) NDB增长到 256 MB 以上时,随后尝试缩小池会导致错误,最终导致数据节点意外关闭。(缺陷号 33647601)

  • NDB在查询有关分区的统计信息之前 ,请检查是否已建立连接。(缺陷号 33643512)

  • PRIMARY没有为ndb_sql_metadata表创建有序索引时,由于缺少索引,存储授权的应用程序无法继续。

    我们通过用模式事务包装关联语句来保护实用程序表(包括 ndb_sql_metadata)的创建来解决此问题 CREATE TABLE,从而通过回滚处理对语句的拒绝。此外,如果新创建的表未正确创建,则将其删除。这些更改避免留下仅部分创建的表,以便下一次创建实用程序表的尝试从流程的开头开始。(缺陷号 33634453)

  • NDBconfig.ini接受全局配置中数字参数值后的任意(且无效)字符串 。例如,可以使用OverloadLimit=10 "M12L"or OverloadLimit=10 M(其中包含一个空格)并将其解释为 OverloadLimit=10M.

    也可以使用纯字母后缀代替预期的数值,例如 OverloadLimit=M,并将其解释为零。对于首字母为 MySQL 标准修饰符之一的任意字符串,也会发生 K这种M情况 G;因此, OverloadLimit=MAX_UINT也具有设置OverloadLimit为零的效果。

    现在,数字参数值只接受后缀K, MG中的一个,并且它必须紧跟在数值之后,中间没有空格字符或引号。换句话说,要设置 OverloadLimit为 10 兆字节,您必须使用OverloadLimit=10000000OverloadLimit=10M或 之一OverloadLimit=10000K

    笔记

    为了保持可用性,您应该检查您的 config.ini文件中是否有任何设置不符合由于此更改而强制执行的规则,并在升级之前更正它们。否则,集群可能无法随后启动,直到您纠正问题。

    (缺陷号 33589961)

  • AutomaticThreadConfig 在少于 8 个可用 CPU 的情况下 启用 会导致数据节点意外关闭。(缺陷号 33588734)

  • 从 . _ buddy.cpp _ (缺陷号 33575155)buddy.hppstorage/ndb/src/common/transporter/

  • 存储授权机制现在将会话NDB变量设置 print_identified_with_as_hextrue,以便存储在 ndb_sql_metadata表中的密码哈希值被格式化为十六进制值,而不是被格式化为字符串。(缺陷号 33542052)

  • 二进制日志线程事件处理包括可选的高详细日志记录,当启用并且连接NDB丢失时,会产生过多的日志消息,如下所示:

    datetime 2 [Note] [MY-010866] [Server] NDB Binlog: cluster failure for epoch 55/0.
    datetime 2 [Note] [MY-010866] [Server] NDB Binlog: cluster failure for epoch 55/0.

    此类重复的日志消息对诊断错误没有多大帮助,已被删除。这会在这种情况下留下类似的日志消息,来自模式分发事件操作拆卸的处理。(缺陷号 33492244)

  • NDB从历史上看,许多不同的方法已被用于以可移植的方式对代码库中 的各种相互依赖性和假设执行编译时检查。由于标准static_assert() 函数现在始终可用,因此 NDB_STATIC_ASSERTSTATIC_ASSERT宏已被直接使用static_assert(). (缺陷号 33466577)

  • 当内部AbstractQueryPlan接口确定用于特定表的访问类型时,它试图解决一个优化器问题,该问题 ref是为表指定的访问类型,后来证明可以通过eq_ref. 解决方法引入了一个新问题,有时会确定 eq_ref对实际需要 ref访问的表的访问权限;此外,之前的修复没有考虑到UNIQUE USING HASH 需要eq_ref全表扫描访问的索引,即使 MySQL 优化器将其视为 ref访问。

    我们通过首先删除变通办法(已通过对上一个问题的适当修复而过时),然后引入散列索引的设置eq_reffull_table_scan访问来解决此问题。(漏洞#33451256)

    参考资料:这个问题是 Bug #28965762 的回归。

  • 当推送连接准备好但未执行时, Ndb_pushed_queries_dropped 状态变量会增加。现在,除此之外, NDB现在发出警告Prepared pushed join could not be executed...传递给ER_GET_ERRMSG. (缺陷号 33449000)

  • ndbd 的弃用-r选项 已被删除。此外,此更改还从 ndbd的输出中删除了无关的文本。(缺陷号 33362935) --help

    参考资料:另请参阅:Bug #31565810。

  • ndb_import有时无法正确解析.csv包含 Windows/DOS 样式 (\r\n) 换行符的文件。(缺陷号 32006725)

  • ndb_import工具处理隐藏的主键,NDB当表没有显式主键时定义。这导致在插入包含NULL 自动递增主键列的行时出错,即使同一行已被接受 LOAD DATA INFILE

    我们通过添加对导入具有NULL自动增量主键列中的一个或多个实例的表的支持来解决此问题。这包括检查一张表是否只有一个自动增量列;如果此列可以为空,则由ndb_import重新定义为 (缺陷号 30799495)NOT NULLNULLNDB

  • 当检测到节点故障时,与该节点位于同一节点组中的幸存节点会尝试将任何缓冲的更改数据重新发送给事件订阅者。在没有未完成的 epoch 交付的情况下,即未确认的 GCI 列表为空,幸存的节点错误地假设该列表永远不会为空。(缺陷号 30509416)

  • 当为外键执行父表的复制ALTER TABLE并且 SQL 节点在完成之前终止时,在所有子表上仍然存在一个带有(附加的,临时的)外键的无关临时表。此问题的一个后果是无法恢复使用 mysqldump --no-data制作的备份。

    为了解决这个问题,现在只要mysqld进程连接(或重新连接)到集群,NDB就会执行临时表的清理。(错误#24935788,错误#29892252)

  • 在 Mac OS X for ARM 上出现总线错误后,数据节点意外关闭。我们通过将调用移动到 NdbCondition_Signal()(in AsyncIoThread.cpp) 来解决此问题,使其在执行之前执行NdbMutex_Unlock()- 即,进入互斥锁,以便发出信号的条件不会在执行期间丢失。(错误#105522,错误#33559219)

  • DblqhMain.cpp中,内部execSCAN_FRAGREQ()函数中缺少返回值导致数据节点在插入非致命错误时意外关闭。此外, !seize_op_rec(tcConnectptr)从未实际检查过同一函数中存在的条件。(错误#105051、错误#33401830、错误#33671869)

  • 可以同时 设置 、 和 中的任何一个 MaxNoOfFiredTriggersMaxNoOfLocalScans尽管 这是不允许的。 MaxNoOfLocalOperationsTransactionMemory

    此外,不可能设置任何 MaxNoOfConcurrentTransactionsMaxNoOfConcurrentOperationsMaxNoOfConcurrentScans 与 并发TransactionMemory,尽管没有理由阻止这种情况。

    在这两种情况下,并发设置行为现在与TransactionMemory 参数的文档相匹配。(错误#102509,错误#32474988)

  • 当重做日志部分无法立即接受操作的日志条目时,操作(准备、提交或中止)将排队,或(仅准备)可选地中止。默认情况下,操作是排队的。

    作为解耦本地数据管理器和重做日志部分的一部分,此机制在 8.0.23 中进行了修改,并引入了回归,使排队的操作可以保持在排队状态,直到日志部分上的所有活动都停止。当发生这种情况时,操作可以保持排队直到DBTC宣布它们超时并中止它们。(漏洞 #102502,漏洞 #32478380)