{
    "componentChunkName": "component---src-templates-blog-blog-detail-tsx",
    "path": "/blog/tidb-6.6-release",
    "result": {"pageContext":{"blog":{"id":"Blogs_461","title":"TiDB 6.6 版本发布","tags":["TiDB","Release"],"category":{"name":"公司动态"},"summary":"我们很高兴地宣布，TiDB 6.6 版本已经发布了。在这个版本中，TiDB 一如既往地沿着更省心、更便捷、更快的方向前进。","body":"我们很高兴地宣布，TiDB 6.6 版本已经发布了。在这个版本中，TiDB 一如既往地沿着更省心、更便捷、更快的方向前进。\n\n## 更省心  \n\n### 资源组  \n\n在省心运维的主题下，新版本包含了重要的实验特性资源组功能。通过 TiDB 中的资源控制，一个应用的会话使用资源受设定的上限所限制。如果其工作负载变大，它的资源分配就会受到限制，以防止拖慢其他应用。这使得 TiDB 将更合适用于多租户的场景：  \n\n- 用户可以将多个小型或中型应用程序合并到一个TiDB集群中，从而降低整体TCO，同时仍然保证用于不同目的的资源。\n- 用户能够在工作时间安全地运行批处理作业。批处理任务消耗的资源可以包含在特定的资源组中。\n- 所有 Staging 环境都可以共享一个具有托管资源限制的TiDB集群，甚至可以与生产环境一起共享。\n\n用户可以为不同租户定义资源组，每个资源组包含了虚拟资源量，并且用户可以设定资源组是否可以在资源闲置时超额使用资源。  \n\n例如一个典型的资源组设定可以是这样的：\n\n| Resource Group  | RU limit<br>（资源上限）  | Burstable<br>（是否可超额使用）  | 特征  |\n|:----------|:----------|:----------|:----------|\n| Payment    | 4000    | YES    | 支付业务，需要确保资源供给，且在高峰时刻可以占用其他组的资源。    |\n| User Configuration    | 2000    | NO    | 用户信息管理，资源需求少于支付，且响应延迟需求低于支付，也无明显高峰低谷。    |\n| Nightly Batch    | 1000    | NO    | 夜间跑批业务，需要确保其不会过多占用资源。    |  \n\n\n```\nCREATE RESOURCE GROUP payment  RU_PER_SEC=4000 BURSTABLE;\nCREATE RESOURCE GROUP user_conf  RU_PER_SEC=2000;\nCREATE RESOURCE GROUP nightly_batch  RU_PER_SEC=1000;\n```\n\n随着资源组功能的加入，用户不再需要为诸多大大小小的业务和用户划分独立的 TiDB 集群（这样做在 SaaS 场景下甚至是不可能的），这不但节省了开销，也大大简化了运维管理。更进一步，将不同相关业务归于统一集群，也使得跨业务数据互通变得异常简单，无论是打造数据中台，还是架构微服务，都更方便省心。  \n\n### 从历史创建执行计划绑定  \n\nSQL 绑定是保持执行计划正确和稳定的重要方法。在关键业务中，用户往往希望执行计划保持稳定，不会因为数据变更等诱因而变化，因为突变的执行计划可能意味着查询效率大幅下降，资源使用飙升，以及严重的事故。在以往版本中，应对计划突变比较麻烦，哪怕已经明确最优计划是什么，用户也必须自己组装带有提示的计划，并在其之上创建绑定：\n\n```\nCREATE BINDING for\n    SELECT id, name, score FROM table1 WHERE id = 1 AND name = 'tidb';\nUSING\n    SELECT /*+ use_index(@sel_1 table1, idx_id) */ * FROM table1 WHERE id = 1 AND name = 'tidb';\n```\n\n在新版中，用户可以在 TiDB Dashboard 中找到最优的执行计划并绑定（也可使用命令行完成类似工作）：\n\n![在 TiDB Dashboard 中找到最优的执行计划并绑定.mp4](https://img1.www.pingcap.com/prod/Ti_DB_Dashboard_60f71ebbd4.mp4)\n\n\n## 更简单易用\n\n### 外键支持  \n\n在新版本中，TiDB 支持了外键。外键是 TiDB 一直缺失的 MySQL 兼容功能，在以往版本中 TiDB 可以理解外键约束的语法，但无法施加约束，这使得部分用户需要依赖应用代码去实现相应逻辑，这为使用增添了诸多麻烦，也引入了丢失数据完整性的风险。在新版本中，TiDB 终于支持了外键约束。用户可以通过为一张表定义外键的方式引用其他表的主键，从而达到强制约束两张表之间的数据完整性和一致性。例如，你可以为订单数据中的客户信息定义指向客户表的外键，这样在进行数据变更的同时，数据库会保证每个订单都确有对应的用户存在。\n\n### 多值索引\n\n新版中，TiDB 加入了实验特性多值索引（Multi-Valued Index）。多值索引有些类似搜索引擎的倒排索引，它允许用户针对数据中的 JSON 数组进行索引。例如单一客户信息的可能包含多个送货邮编，于是应用程序使用 JSON 数组字段进行保存。在以往版本中，TiDB 的索引仅仅能对单一值进行索引，因此在这个场景下，如果需要以邮编进行索引查找，你必须将邮编数组展开复制成多行（每行确保只有一个邮编），否则只能进行全表扫描，这无疑费心又难于管理。在新版本中，你可以为 JSON 中的数组字段创建多值索引：\n\n`ALTER TABLE customers ADD INDEX zips( (CAST(cust_profile->'$.zipcode' AS VARCHAR(10) ARRAY)) );`\n\n并在查询条件中搜索所有送货地址在某个邮编的用户，这样就能使用多值索引快速检索返回结果：\n\n`SELECT  * FROM customers WHERE ('200040' MEMBER OF (cust_profile->'$.zipcode'));`\n\n## 更快  \n\n### TiKV 和 TiFlash 引擎加速\n\n在新版中，TiKV 迎来了巨大的优化变更。  \n\n首先是实验特性 Partitioned-Raft-KV 存储引擎，以往同一个 TiKV 节点使用一个 RocksDB 存储数据，无论数据量多大，有多少 Region 和表；在 TiDB 6.6 中，TiKV 可以让单一 Region 更大（默认 10 GB），并使用独立的 RocksDB 实例，这将大大减少 LSM Tree 的深度，降低写入的压力，并提升性能。根据测试，写入吞吐提升可达 273%，集群扩缩容可提速 5 倍。\n\n|   | 写吞吐  | 扩容  | 缩容  |\n|:----------|:----------|:----------|:----------|\n| 单 RocksDB    | ~60MB/s    | 0.73GB/min    | 2.86GB/min    |\n| Partitioned-Raft-KV    | ~224MB/s (+273%)    | 3.6GB/min (+500%)  | 13.7GB/min (+480%)   |\n\n其次，TiKV 在新版中可以通过协处理器攒批的方式减少诸如读取索引等操作带来的大量 RPC 调用，在通过索引读取百万以上规模行的场景下，可提速一倍以上。  \n\n再来说说 TiDB 的分析引擎 TiFlash。  \n\nTiFlash 的最基础能力是，支持计算时让数据在不同节点之间交换。为了完成计算，有时分析引擎节点之间需要交换大量数据，例如执行大表的关联时，需要将两张表分别按照关联键进行哈希并相互分发。这种情况下，网卡有时候会成为性能瓶颈。在新版中，分析引擎支持了将数据进行压缩后再分发的能力，这使得 TiDB 针对标准 TPC-H 测试下的性能有 12%-32% 的提升，以及超过 50% 的网络带宽节省。  \n\n与此同时，TiDB 分析引擎在新版中支持了 Stale Read。当用户不追求严格读取实时数据的前提下，使用该功能读取历史数据可带来 30% 左右的性能提升。  \n\n### DM 支持物理导入模式  \n\n新版本中，DM 的全数据（存量数据）迁移能力集成了TiDB Lightning 的物理导入模式。相较于以往的逻辑模式导入数据，新版本中 DM 的迁移性能提升高达 10 倍，大大缩短了数据量大的场景下的迁移时间；现在，要迁移超过 1 TB 的数据，你只需要在 DM 任务中设置参数即可实现高达 500 GB/小时的存量数据迁移性能。用户再也无需额外配置 TiDB Lightning 迁移存量数据以加快导入速度，大大简化了使用：\n\n`import-mode：\"physical\"`\n\n## 总结  \n\n以上是 TiDB 6.6 所带来的重要功能概览，除此之外，新版本共发布了 32 个新特性，37 个增强以及 80 个问题修复，希望了解详情可参考 TiDB 6.6 [Release Notes](https://docs.pingcap.com/zh/tidb/v6.6/release-6.6.0)。\n\n<div class=\"is-flex is-flex-direction-row is-justify-content-center\">\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"/product-community/\"\n       style=\"background-color: #4fc172;\">\n      下载 TiDB 社区版\n    </a>\n  </div>\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"https://pingcap.com.cn\"\n       style=\"background-color: #3a40e1;\">\n      了解 TiDB 企业版\n    </a>\n  </div>\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"https://tidbcloud.com/free-trial?utm_source=website-zh&utm_medium=referral&utm_campaign=blog-tidb-6.6-release\"\n       referrerpolicy=\"no-referrer-when-downgrade\" style=\"background-color: #3a40e1;\">\n      免费试用 TiDB Cloud\n    </a>\n    <div style=\"font-size:12px; text-align:center\">适用于中国出海企业和开发者</div>\n  </div>\n</div>","date":"2023-02-20","author":"马晓宇","fillInMethod":"writeDirectly","customUrl":"tidb-6.6-release","file":null,"relatedBlogs":[{"relatedBlog":{"body":"在 2023 伊始，我们很高兴向大家宣布，TiDB 6.5 LTS 版本已经发布了。这是 TiDB V6 的第二个长期支持版（上一个是 [TiDB 6.1](/blog/tidb-6.1-release)），除了携带了诸多备受期待的新特性，同时也将得到 TiDB 开发社区的长期维护，是推荐企业级用户采用的最新版本。\n\n![TiDB 6.5 LTS.png](https://img1.www.pingcap.com/prod/Ti_DB_6_5_LTS_83af544cd2.png)\n\n<div class=\"is-flex is-flex-direction-row is-justify-content-center\">\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"/product-community/\"\n       style=\"background-color: #4fc172;\">\n      下载 TiDB 社区版\n    </a>\n  </div>\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"https://pingcap.com.cn\"\n       style=\"background-color: #3a40e1;\">\n      了解 TiDB 企业版\n    </a>\n  </div>\n  <div class=\"is-flex is-flex-direction-column\">\n    <a target=\"_blank\" class=\"button is-link mx-5\"\n       href=\"https://tidbcloud.com/free-trial?utm_source=website-zh&utm_medium=referral&utm_campaign=blog-tidb-6.5-release\"\n       referrerpolicy=\"no-referrer-when-downgrade\" style=\"background-color: #3a40e1;\">\n      免费试用 TiDB Cloud\n    </a>\n    <div style=\"font-size:12px; text-align:center\">适用于中国出海企业和开发者</div>\n  </div>\n</div>\n\n在这个版本中，TiDB 专注于如下几个主题：\n\n- **产品易用性进一步提升**\n- **内核不断打磨，更加成熟**\n- **多样化的灾备能力**\n- **应用开发者生态构建**\n\n相信长期关注我们的朋友已经发现，这些主题似曾相识。的确如此，TiDB 近年的发展几乎都围绕着它们开展。我们期望 TiDB 成为**更易用，对开发者更友好，且更成熟的企业级数据库**，而这个追求也并没有尽头。\n\n## 产品易用性进一步提升\n\n大家也许不止一次听说过，易用性之于 TiDB 是非常关键的理念。毕竟，TiDB 伊始是为了解决分库分表带来的麻烦，这也使得易用性在 TiDB 研发过程中贯穿始终。在新版本中，我们提供了更多的让用户解放心智的能力。\n\n### AND 运算下的索引归并读取\n\n对于数据服务和洞察场景，用户往往会基于诸多查询条件的组合进行数据筛选。例如在物流场景中，用户可能会根据下单日，仓库 ID，转运人，送达日，目标地址等等不同维度进行筛选再分析。而这些条件单独来看，并不一定具备很好的选择性，只有组合起来才能将数据限定在一个小范围。如果条件的组合不多，我们尚可使用特定的组合索引覆盖，但很可能在这类场景中，组合以数十记，完全无法为每个组合都创建特定索引。在新版本中，TiDB 支持根据 AND 条件组合同时选中多组索引，并计算它们的交集再读取实际表数据。这种能力，使得用户可以仅仅为单列创建少量索引，以达到更好的选择性以及更优的性能。\n\n![Screen Shot 2023-01-03 at 00.50.14.png](https://img1.www.pingcap.com/prod/Screen_Shot_2023_01_03_at_00_50_14_365a0cbe7e.png)\n\n### 集群闪回\n\n有时候，用户会希望整个集群快速恢复到之前的某个时间点。例如，由于游戏服务器新版本数据设定问题，将一把绝世好剑设定为 1 元，造成新版发布后一小时内人手一把。若仅仅如此也就算了，开发者可以很容易回收或这个道具，但这种事故还有次生灾害，例如稀有 Boss 被滥杀，稀有掉落随之泛滥，整个游戏内容崩坏。这时候作为游戏设计师，你可能会希望时间能回到犯错之前的那一刻，让你修正那个令人追悔莫及的错误。在新版本中，TiDB 就提供了这个能力，它支持用简单一条命令向 GC 时间内的任意时间点进行全集群闪回，就像下面这样。\n\n```sql\nFLASHBACK CLUSTER TO TIMESTAMP '2022-09-28 17:24:16'; \n```\n\n我们当然希望这不会是一个常见的状况，但这并不表示需要闪回的时机千年难遇：闪回能力也可用于日常操作，例如将测试环境恢复到测试开始前的状态，以供反复使用。\n\n### 完整的大事务自动拆分支持\n\n在前序版本中，我们支持了针对删除的大事务自动拆分支持。而在新版本中，TiDB 完整支持了针对插入和修改的大事务拆分。在以往版本中，TiDB 用户经常要面对的一个问题就是，一些大规模的数据变更维护操作，例如过期数据删除，大范围数据修订，或者根据查询结果回写数据等操作，会遇到超过 TiDB 单条事务上限的问题，这是由于 TiDB 单一事务需要由单一 TiDB Server 作为提交方而带来的限制，这时候用户往往不得不手动想办法拆小事务以绕过该限制。但在实际使用中，上述类型的数据变更未必真的需要作为单一事务确保原子性，例如数据淘汰和数据修订，只要最终执行完成，哪怕事务被拆开多次执行也并不会影响使用。在 TiDB 6.5 中，我们提供了将大事务自动拆分的能力，例如按照 t1.id 以 10000 条为大小分批数据更新，可以简单使用如下语句完成：\n\n```sql\nBATCH ON t1.id LIMIT 10000 update t1 join t2 on t1.a=t2.a set t1.a=t1.a*1000;\n```\n\n更详细的说明请[参考文档](https://docs.pingcap.com/zh/tidb/stable/non-transactional-dml)。\n\n### TiFlash 结果物化（实验特性）\n\nTiFlash 在过往版本中有一个很大的缺憾是无法在读写事务中使用：经常用户希望将 TiFlash 的计算结果进行回写以供高并发读取（类似物化效果）。从 v6.5.0 起，TiFlash 支持通过 INSERT SELECT 语句回写结果进行物化，节省系统资源并提高响应速度。\n\n```sql\nINSERT INTO top_payments SELECT MAX(amount) FROM payments;\n```\n\n在执行上述 INSERT INTO SELECT 语句时，TiDB 可以将 SELECT 子查询下推到 TiFlash 以提供高速分析计算，并将返回结果通过 INSERT INTO 可以保存到指定的 TiDB 表中。值得一提的是，该功能结合前述大事务拆分可以实现大量结果集物化。\n\n### 高性能全局单调递增 AUTO_INCREMENT 列\n\nTiDB 作为一款分布式数据库，以往在使用 AUTO INCREMENT 列创建主键时，仅保证在每个 TiDB 实例中序列递增，而跨 TiDB 实例则无法保证。但实际使用中，用户仍然经常会遇到需要严格单调递增主键的时候，例如以主键隐式代表时间维度，确定事件发生顺序。在 6.4 版本中，我们加入了高性能的全局单调递增主键的支持，以兼容 MySQL 的行为。该模式下，TiDB 将采取中心化的主键分配以确保单调递增，即使跨 TiDB 实例访问，ID 也不会出现回退，且针对其的写入也可轻松达到数万的 TPS。\n\n### 使用 TTL (Time to Live) 来周期性地删除过期数据（实验特性）\n\n维护数据的生命周期在 TB 以上规模下并不是很容易的事情：由于数据规模大，寻找并清理过期的数据往往需要消耗相当的算力，有时用户为了更快清理数据甚至被迫使用分区表，以删除分区的方式来进行快速清理。更麻烦的是，用户需要维护特定的任务以不断定期淘汰数据。在新版本中，TiDB 提供了 Time to Live (TTL) 能力，使得用户可以设定行级别的生命周期控制策略。通过为表设置 TTL 属性，TiDB 可以周期性地自动检查并清理表中的过期数据。当开启时，TTL 会以表为单位，并发地分发不同的任务到不同的 TiDB 实例节点上，进行并行删除处理，且不影响集群性能。更详细的说明请[参考文档](https://docs.pingcap.com/zh/tidb/stable/time-to-live)。\n\n## 内核关键特性打磨和增强\n\nTiDB 包含繁多的特性集合，但其中有些仍需不断打磨，例如 JSON 虽然已获支持许久，但实际能力却尚需完善。在新版本中，我们针对重要特性集合用力打磨，以期提供给用户更「丝滑」的体验，让 TiDB 的重大特性以更完善的方式呈现在用户面前，也让 TiDB 演进方式更稳重更有质量。\n\n**首先是 DDL 加强**。支持在线 DDL 是 TiDB 的核心优势之一，在过往一年中，我们加入了对并行 DDL 的支持，使得以往在 SaaS 等多租户场景因 DDL 串行执行互相阻塞导致的 DDL 语句间执行效率低的问题得以解决，通过引入 Metadata Lock 基本消除了 DDL 干扰 DML 的情况。在新的 6.5 版本中，TiDB 支持了类似 Lightning 注入 SST 的设计，针对需要追溯的历史数据直接使用 SST 构建的方式进行生成，大幅提高了 DDL 的构建速度，最快可达 **10 倍提升**。\n\n如下图所示，以 TiDB 6.1 版本为基准值，新版除了取得了数量级的提速，且对比 CockroachDB v22.2 和当前版的 AWS Aurora 也快 2-3 倍。\n\n![Screen Shot 2023-01-03 at 10.15.34.png](https://img1.www.pingcap.com/prod/Screen_Shot_2023_01_03_at_10_15_34_49df47db5a.png)\n\n**其次是 JSON 的支持打磨**。JSON 对于需要灵活数据结构的场景非常重要，因此在移动端，游戏开发等场景中广泛使用。从 6.2 版本以来，TiDB 陆续引入了完整的 MySQL 5.7 兼容函数，针对 JSON 的表达式索引支持，更多的生态工具兼容。新版本支持将 JSON 函数 \"->\"、\"->>\"、\"JSON_EXTRACT()\" 下推至 TiFlash，可以提高 JSON 类型数据的分析效率，拓展 TiDB 实时分析的应用场景。\n\n**再者是 TiDB 全局内存控制**。自 v6.5.0 起，TiDB 全局内存控制已能够跟踪到 TiDB 中主要的内存消耗。当单个会话的内存消耗达到系统变量 `tidb_mem_quota_query` 所定义的阈值时，将会触发系统变量 `tidb_mem_oom_action` 所定义的行为 (默认为 `CANCEL`，即取消操作)。当全局内存消耗达到 `tidb_server_memory_limit` 所定义的预设值时，TiDB 会尝试 GC 或取消 SQL 操作等方法限制内存使用，保证 TiDB 的稳定性，对内存的使用效率也更加高效。 \n\n**最后是降低累积的悲观锁对性能的影响**。 在一部分交易系统，尤其是银行业务中，客户应用会在悲观事务中利用 select for update 先锁定一条记录，从而达到对数据一致性的保护，减少事务中后续操作失败的可能，比如\n\n```sql\nBEGIN;\nSELECT c FROM sbtest1 WHERE id = 100 FOR UPDATE; \nUPDATE sbtest1 SET k = k + 1 WHERE k = ?; \nCOMMIT;\n```\n\n而在 TiDB 中，对一行记录反复的 select for update，会造成这条记录的查询性能下降。 在 v6.5.0 中，我们对这部分机制进行了优化， 通过记录连续的锁标记，降低了累积的悲观锁对查询性能的影响，QPS 可大幅提升 10 倍以上。\n\n## 多样化的灾备能力\n\n在过往版本中，TiDB 主要依赖 BR 进行静态的备份恢复，而在 6.2 之后的新版中，TiDB 提供了 PITR 能力，使得数据库可以更灵活地恢复到任意时间点。\n\nTiDB PITR（Point-in-Time Recovery）是结合了 BR 和变更捕获（Change Data Capture）两种能力的灾备特性。以往 BR 的静态灾备只能将数据恢复到备份的时间点，如果要更提供针对更新和更多时间点的恢复，则相应需要提高备份频率。这不但会加重备份对在线业务的负担，也需要更多存储成本。使用 PITR 则可以摆脱这个烦恼，用户无需不断进行全量备份，而是可经由一个全量备份结合增量共同完成针对任意时间点的数据恢复。\n\n![Screen Shot 2023-01-03 at 01.48.32.png](https://img1.www.pingcap.com/prod/Screen_Shot_2023_01_03_at_01_48_32_f41d588441.png)\n\n经过半年左右的持续改进，在新版本中，我们减少了 PITR 备份文件大小和数量，加强了稳定性，提升了性能。 例如：确保在绝大多数异常场景下 RPO < 5mins, 单个 TiKV 的备份速度达到100MB/s等。\n\n与此同时，在 6.5 版本中，TiCDC 的吞吐获得了得了至数倍的提升。通过对 TiCDC 内部的设计和实现的不断优化，针对数据复制场景，当下游为 Kafka 集群时，针对大单表场景的吞吐量得到了极大的提升，单个 TiCDC 节点可以支持35k row/s QPS，吞吐量可以达到 50MB/s，并将延迟控制在 2 秒左右，而内存使用量只有之前版本的50%左右。 针对跨区域主备集群容灾场景，TiCDC 单个节点的吞吐量可以达到 30MB/s，并且其延迟也可以稳定在 2 秒左右，稳定性大幅度提高。\n\n其次，在6.5 版本中，DM 正式发布了在数据迁移过程中的增量数据持续校验功能，该特性只对新增或变更的数据进行校验，而不是对整个数据集进行校验，在确保数据迁移过程的准确性和可靠性的同时，大大减少数据校验的时间和资源消耗。尤其是在迁移一些重要系统时，该特性可以让数据迁移过程更加安全。\n\n除此以外，新版本支持了在下游集群使用水位线进行一致性读取的能力：在新版本中，TiCDC 可以在向下游写入时提供特殊的时间戳，而下游集群则可以自动使用该时间戳进行一致性读取而无需担心读到的事务不完整。这使得下游集群在需要严苛事务保证的场景下，也可以良好承担读流量分流的职责。\n\n![Screen Shot 2023-01-03 at 02.04.38.png](https://img1.www.pingcap.com/prod/Screen_Shot_2023_01_03_at_02_04_38_3012a4bd0d.png)\n\n## 应用开发者生态构建\n\n在以往版本中，TiDB 更强调 DBA 的使用体验。但在近期的更新中，你也许已经发现我们逐渐开始聚焦 DBA 以外的应用开发者体验。在新版中，我们强化了应用开发所需的生态环境构建，例如这半年来 TiDB 通过增加对 Savepoint，User Level Lock，Multiple Schema Change 等功能的支持，完善了针对常见应用框架 django，prisma 等的支持。与此同时，我们也引入了更多上下游生态厂商的战略合作：Vercel，Hashicorp，Retool 等。在 6.5 版本中，TiCDC 增加了针对向 Object Storage 写入的支持。对象存储是一种面向云的存储服务，具有高可扩展性、高可用性、低成本等优势。使用 TiCDC 将数据同步到对象存储，可以帮助用户实现数据的长期存储、数据的跨区域复制等目的。另外，这使得 TiDB 在云环境下能直接打通向数仓和数据湖环境的通路。更好的生态支持，将使得开发者在使用 TiDB 构建应用时，拥有更多选择，也更简便。\n\n## 总结\n\n作为 TiDB 版本 6 的第二个长期支持版，TiDB 6.5 已经发布。我们希望借助这个版本为更多用户提供更易用且更成熟的企业级数据库。更详细的变更情况请参阅 [Release Notes](https://docs.pingcap.com/zh/tidb/stable/release-6.5.0)。欢迎各位和我们一起开启新的[奇妙旅程](https://docs.pingcap.com/zh/tidb/stable/quick-start-with-tidb)。","author":"马晓宇","category":2,"customUrl":"tidb-6.5-release","fillInMethod":"writeDirectly","id":451,"summary":"在 2023 伊始，我们很高兴向大家宣布，TiDB 6.5 LTS 版本已经发布了。","tags":["TiDB","Release"],"title":"TiDB 6.5 LTS 版本发布"}},{"relatedBlog":{"body":"TiDB 6.5 LTS 版本已经发布了。这是 TiDB V6 的第二个长期支持版，携带了诸多备受期待的新特性：**产品易用性进一步提升、内核不断打磨，更加成熟、多样化的灾备能力、加强应用开发者生态构建**……\n\nTiDB 6.5 新特性解析系列文章由 PingCAP 产研团队重磅打造，从原理分析、技术实现、和产品体验几个层面展示了 6.5 版本的多项功能优化，**旨在帮助读者更简单、更全面的体验 6.5 版本**。\n\n本文为系列文章的第一篇，介绍了 TiFlash 在高并发场景下的稳定性和资源利用率的优化原理。\n\n## 缘起\n\n最近的某天，我们测试 TiFlash 在高并发查询场景下的稳定性时，发现 TiFlash 终于可以长时间稳定将 CPU 完全打满，这意味着我们能充分的利用 CPU 资源。回想一年多前，我们还在为高并发查询下的 OOM（out-of memory）、OOT（out-of thread）、CPU 使用率不高等各种问题而绞尽脑汁。是时候来回顾一下我们做了哪些事情，让量变引起质变。\n\n![1.png](https://img1.www.pingcap.com/prod/1_7a99a35a4c.png)\n<center>👆 CPU 使用率打满</center>\n\n我们都知道，对于分析型的查询来说，有时候一个请求就能将机器的 CPU 资源打满。所以，大部分 OLAP 系统在设计和实现的时候，很少考虑系统在高查询并发下的表现——早期的 TiFlash 也没在这方面考虑太多。\n\n早期的 TiFlash 的资源管理比较初级——没有高效的线程管理机制、缺少健壮的查询任务调度器、每个查询的内存使用没有任何限制、最新写入的数据存储和管理也有较大优化空间。这些优化措施的缺位，导致早期的 TiFlash 在高并发查询场景下表现不佳，经常无法将 CPU 使用率打满，稍有不慎还可能出现 OOM 或 OOT。\n\n过去一年里，针对 TiFlash 在高并发场景下的稳定性和资源利用率这个问题，我们在存储和计算上都做了不少尝试和努力。如今回头看，有了上面的结果，也算是达到了一个小里程碑。\n\n## DynamicThreadPool\n\nTiFlash 最开始的线程管理非常简单粗暴：请求到来时，按需创建新线程；请求结束之后，自动销毁线程。在这种模式下，我们发现：对于一些逻辑比较复杂，但是数据量不大的查询，无论怎么增加查询的并发，TiFlash 的整机 CPU 使用率都远远不能打满。\n\n![2.png](https://img1.www.pingcap.com/prod/2_1f33daf820.png)\n<center>👆 CPU 使用率始终保持在 75% 以下</center>\n\n经过一系列的研究之后，我们终于定位到问题的根本原因：高并发下，TiFlash 会频繁地创建线程和释放线程。在 Linux 内核中，线程在创建和释放的时候，都会抢同一把全局互斥锁，从而在高并发线程创建和释放时, 这些线程会发生排队、阻塞的现象，进而导致应用的计算工作也被阻塞，而且并发越多，这个问题越严重，所以 CPU 使用率不会随着并发增加而增加。具体分析可以参考文章：[深入解析 TiFlash丨多并发下线程创建、释放的阻塞问题](https://cn.pingcap.com/blog/deep-interpreting-of-tiflash?utm_source=wechat&utm_medium=social)。\n\n解决这个问题的直接思路是使用线程池，减少线程创建和释放的频率。但是，我们目前的查询任务使用线程的模式是非抢占的，对于固定大小的线程池，由于系统中没有全局的调度器，会有死锁的风险。为此，我们引入了 DynamicThreadPool 这一特性。\n\n在 DynamicThreadPool 中，线程分为两类：\n\n1. 固定线程：固定数量的线程，生命期与整个线程池相同。\n2. 动态线程：运行过程中随着负载升高而创建，会自行在冷却后销毁。\n\n每当有新任务需要执行时，DynamicThreadPool 会按以下顺序查找可用线程：\n\n1. 空闲的固定线程。\n2. 空闲的动态线程。\n3. 当没有可用线程时，创建新的动态线程服务当前任务。\n\n所有空闲的动态线程会组成一个 LIFO 的链表，每个动态线程在处理完一个任务后都会将自身插入到链表头部，这样下次调度时会被优先使用，从而达到尽可能复用最近使用过的动态线程的目的。链表尾部的动态线程会在超过一个时间阈值没有收到新任务之后判断自身已冷却，自行退出。\n\n## MinTSOScheduler\n\n由于 DynamicThreadPool 没有限制线程的数量，在遇到高并发查询时，TiFlash 仍然有可能会遇到无法分配出线程（OOT）的问题。为了解决此问题，我们必须控制 TiFlash 中同时使用的线程数量。\n\n为了控制同时使用的计算线程数量，同时避免死锁，我们为 TiFlash 引入了名为 MinTSOScheduler 的查询任务调度器——一个完全分布式的调度器，它仅依赖 TiFlash 节点自身的信息。\n\n![3.png](https://img1.www.pingcap.com/prod/3_d04c476b42.png)\n<center>👆 MinTSOScheduler 的基本原理</center>\n\nMinTSOScheduler 的基本原理是：保证 TiFlash 节点上最小的 start_ts 对应的所有 MPPTask 能正常运行。因为全局最小的 start_ts 在各个节点上必然也是最小的 start_ts，所以 MinTSOScheduer 能够保证全局至少有一个查询能顺利运行从而保证整个系统不会有死锁。而对于非最小 start_ts 的 MPPTask，则根据当前系统的线程使用情况来决定是否可以运行，所以也能达到控制系统线程使用量的目的。\n\n## MemoryTracker\n\nDynamicThreadPool 和 MinTSOScheduler 基本上解决了线程频繁创建和销毁、线程使用数量不受控制两大问题。对于一个运行高并发查询的环境，还有一个重要的问题要解决——减少查询之间的相互干扰。\n\n实践中，我们发现最重要的一点就是要避免其中某一个查询忽然消耗掉大量内存，导致整个节点 OOM。为了避免某个大查询导致的 OOM，我们显著增强了 MemoryTracker 跟踪和记录每个 MPPTask 使用的内存的精确度。当内存使用超过限制时，可以强行中止请求，避免 OOM 影响其它请求。\n\n## PageStorage\n\nPageStorage 是 TiFlash 中的一个存储的抽象层，类似对象存储。它主要是为了存储一些较小的数据块，如最新数据和 TiFlash 存储引擎的元数据。所以，PageStorage 主要面向新写入数据的高频读写设计。v6.1 及之前 TiFlash 使用的是 PageStorage 的 v2 版本（简称 PSv2）。\n\n经过一系列的迭代和业务打磨，我们发现 PSv2 存在一些问题亟需改进：\n\n1. 在一些写入负载，特别是 append-only 负载下，容易触发激进的 GC 策略对硬盘数据进行重写。重写数据时引起较大的写放大，以及内存的周期性快速上涨，造成系统不稳定。同时也会挤占前台写入和查询线程 CPU。\n2. 在 snapshot 释放时进行内存中的垃圾回收，其中涉及较多内存小对象的拷贝。在高并发写入和查询的场景下，snapshot 释放的过程与读写任务挤占 CPU。\n\n这些问题在大部分写入和查询并发较低的 OLAP 场景下，对系统的影响有限。但是，TiFlash 作为 TiDB 的 HTAP 架构中重要的一环，经常需要面对高并发的写入和查询。为此，我们重新设计并实现了全新的 PageStorage （简称 PSv3）以应对更严苛的 HTAP 负载需求。\n\n![4.png](https://img1.www.pingcap.com/prod/4_2f02641873.png)\n<center>👆 PSv3 架构图</center>\n\n上图是 PSv3 的整体架构。其中，橙色块代表接口，绿色块代表在硬盘上存储的组件，蓝色块代表在内存中的组件。\n\n- WALStore 中维护数据（page）在 BlobFile 中位置，内存中的 PageDirectory 实现了 MVCC 支持。\n- 数据保存在 BlobFile 中，如果其中的数据反复重写，会造成 CPU 以及 IO 资源的浪费。我们通过 SpaceMap 记录了 BlobFile 上的数据块使用情况（空闲或占用）。删除数据时，只需要更新一下标记。写入数据时，可以直接从 SpaceMap 查找符合要求的空闲块直接写入。大部分情况下，BlobFile 可以直接复用被删除的空闲数据块，避免数据重写的发生，最大程度地减少了垃圾回收的需求，从而显著减少 CPU 和内存空间使用。\n- 由于有 SpaceMap 的存在，写线程在 SpaceMap 中分配好数据块位置之后，多个写线程的 IO 操作可以并发执行。在复用空间时 BlobFile 文件大小不变，可以减少了文件元数据的 sync 操作。TiFlash 整体的写延迟降低，进而减少等待数据一致性的 wait index 阻塞时间，提升查询线程的 CPU 利用率。\n- 让读写线程 snapshot 创建和释放时的操作更高效，内存对象的整理的时间从释放 snapshot 时改为在后台线程进行回收，减少了对前台读写任务的影响，从而提升了查询线程的 CPU 利用率。\n\n## 总结\n\n| DynamicThreadPool | MinTSOScheduler | PageStorageV3 | CPU 最大使用率 |\n| --- | --- | --- | --- |\n| enable | enable | enable | 100% |\n| disable | disable | enbale | 75% |\n| enable | disable | enable | 90% |\n| enable | enable | disable | 75% |\n| disable | enable | enable | 85% |\n\n上面这个表格总结了本文介绍的这几个提升 TiFlash 稳定性和 CPU 使用率的关键特性的组合情况，可以看出：\n\n- DynamicThreadPool 解决了频繁创建和销毁线程带来的开销；PageStorage v3 大大降低了 GC 和 snapshot 的开销，提升了高并发写入和查询的稳定性。这两者对提升 CPU 利用率有明显的效果。\n- MinTSOScheduler 调度器限制了查询使用线程的数量，避免了出现分配不出线程的情况，可以有效防止高并发请求导致的 OOM、OOT。\n- 而 MemoryTracker（内存限制）通过主动 cancel 掉部分请求来防止整个进程 OOM，可以有效避免一个大查询导致整个节点不可用（OOM）的情况发生。\n\n除此之外，过去一年，TiFlash 在性能和功能方面也做了不少优化，感兴趣的朋友可以关注我们的 github 代码和官方文档。以上全部改动可以在 TiDB v6.5 LTS 版本中体验到，欢迎尝试。","author":"林金河，颜秋阳","category":1,"customUrl":"new-features-of-tidb-6.5-1","fillInMethod":"writeDirectly","id":455,"summary":"TiDB 6.5 新特性解析系列文章由 PingCAP 产研团队重磅打造，从原理分析、技术实现、和产品体验几个层面展示了 6.5 版本的多项功能优化，旨在帮助读者更简单、更全面的体验 6.5 版本。本文介绍了 TiFlash 在高并发场景下的稳定性和资源利用率的优化原理。","tags":["TiDB","TiFlash"],"title":"TiDB 6.5 新特性解析丨过去一年，我们是如何让 TiFlash 高效又稳定地榨干 CPU？"}}]}}},
    "staticQueryHashes": ["1327623483","1820662718","3081853212","3430003955","3649515864","4265596160","63159454"]}