{
    "componentChunkName": "component---src-templates-blog-blog-detail-tsx",
    "path": "/blog/from-disk-snapshot-to-backup-recovery",
    "result": {"pageContext":{"blog":{"id":"Blogs_470","title":"TiDB 6.5 新特性解析丨他山之石，可以攻玉：从磁盘快照到备份恢复","tags":["TiDB","备份恢复"],"category":{"name":"产品技术解读"},"summary":"本文分享了 TiDB 运用 AWS EBS 快照技术实现备份恢复功能的原理和实践，以及如何解决传统数据库备份恢复特性无法克服的问题，让备份恢复特性向前迈进了坚实的一步。","body":"## 导读\n\n现在，数据库已成为众多企业信息系统的核心，数据库的备份恢复能力至关重要。对于 TiDB 这样的分布式数据库而言，数据库存储数据量不断增加，备份恢复也面临着更多挑战。\n\nAmazon Web Services (AWS) EBS 快照是一种数据备份技术，用于将 EBS 卷上的数据快速备份到云端。他山之石，可以攻玉，本文分享了 TiDB 运用 AWS EBS 快照技术实现备份恢复功能的原理和实践，以及如何解决传统数据库备份恢复特性无法克服的问题，让备份恢复特性向前迈进了坚实的一步。\n\n## 备份恢复技术介绍\n\n备份恢复对数据库产品来说是至关重要的，因为数据库是许多企业信息系统的核心部分，如果数据库出现问题或者数据丢失，将会对企业造成极大的损失。因此，备份恢复技术是用来保护数据库数据，确保在意外情况发生时能够尽快恢复数据库的正常运行。\n\n传统数据库的备份恢复技术通常分为备份和恢复两部分。其中包含了全备和增量备份。全备就是将数据库的所有数据和日志文件都备份到一个指定的目录或者存储设备中。增量备份则是只备份数据库在上一次备份之后发生变化的数据和日志文件。\n\n恢复技术则是将数据库恢复到一个指定的时间点的过程。通常，恢复技术需要将备份的数据和日志文件按照时间顺序进行恢复，以便保证数据库的一致性。\n\n传统数据库备份恢复技术的主要优点是简单易用，但是也有很多问题，其中最主要的问题就是：\n\n1. 备份过程中可能会对数据库造成一定的影响\n2. 恢复时间也会受到数据量的影响，导致恢复时间较长（RTO 通常以小时甚至天为单位）\n\n在数据库技术进入到分布式数据库时代后，随着数据库数据量的不断上升，上面的问题对用户的影响越来越大。\n\n## AWS EBS 快照技术介绍\n\nAmazon Web Services (AWS) EBS 快照是一种数据备份技术，用于将 EBS 卷上的数据快速备份到云端。EBS 卷是 Amazon Elastic Block Store (EBS) 的一种存储设备，可以将其作为 Amazon Elastic Compute Cloud (EC2) 实例的持久化存储。\n\nEBS 快照是一种增量备份技术，只备份在上一次备份之后发生变化的数据。因此，EBS 快照备份速度很快，并且备份的数据量也较小。\n\nEBS 快照可以保存在 Amazon Simple Storage Service (S3) 中，可以在 S3 中的任何区域内进行存储。EBS 快照可以用来创建新的 EBS 卷，也可以用来创建 Amazon Machine Image (AMI)。\n\nEBS 快照是一种非常有用的数据备份技术，可以帮助企业保护其重要数据，并且在数据丢失或损坏时进行快速恢复。\n\n## TiDB 如何利用 AWS EBS 快照技术进行数据库备份恢复\n\n![TiDB 如何利用 AWS EBS 快照技术进行数据库备份恢复.png](https://img1.www.pingcap.com/prod/Ti_DB_AWS_EBS_0ee2d9d954.png)\n\n作为采用 raft 协议的 shared-nothing 架构的分布式数据库产品的典型代表，新一代的 TiDB 备份恢复特性创新性地利用了 EBS 快照技术，解决了传统数据库备份恢复特性无法克服的问题，让备份恢复特性向前迈进了坚实的一步。\n\nTiDB 将数据存储在 EBS 卷上，当需要进行备份的时候，通过 TiDB Operator 向 backup contorller 发出备份的命令，产生相应的 Backup Worker，产生 TiKV 节点所对应的 EBS 卷的快照并保存到 S3 中。在恢复的时候，则通过备份时保存在 S3 上的元数据和 EBS 卷快照来将集群恢复到新的集群。\n\n由于 EBS 快照是一种磁盘快照技术，只能够保证 EBS 自己的一致性，却无法保证数据库层面的一致性。而且在数据库事务层的处理上，同一个事务的数据，在经过 MVCC 版本编码以及 Raft 层处理后，数据落盘到不同的 TiKV 的 EBS 卷上，这些卷之间的一致性是 EBS 快照无法保证的。\n\n无论在备份还是恢复过程中，如何确保备份的数据是一致的，以及如何将数据库基于 EBS 快照恢复到用户指定的时间点，并确保数据的一致性，是一个很大的挑战。\n\n幸运的是，TiKV 维护了 region 级别的 resolved_ts，用来代表某一个 region leader 上最大能读到的一致性完整事务的时间，即 resolved_ts = max(resolved_ts, min(lock_cf.StartTS))。resolved_ts 能够保证任意时刻能读到当前 region 最大数据一致性的 ts. 同时 TiKV 会计算当前节点所有 region leader 上最小的 resolved_ts, 并主动汇报给 PD。PD 汇总集群所有 TiKV 一致性 TiKV resolved_ts, 得到集群级别 min_resolved_ts。\n\n### 备份阶段\n\n![备份阶段.png](https://img1.www.pingcap.com/prod/_9e0b75dbf2.png)\n\n在备份阶段，BR 工具会首先从 PD 获得集群的全局一致性 min_resolved_ts ，之后停止副本的调度和 GC，并行调用 AWS 卷快照服务产生 TiKV 节点 EBS 卷快照并保存备份的元数据，之后恢复副本调度并记录元信息，最后备份结束。\n\n### 恢复阶段\n\n![恢复阶段.png](https://img1.www.pingcap.com/prod/_7914f3c14b.png)\n\nBR 工具在接受到恢复请求之后，restore worker 会获取备份的元数据，其中包含集群拓扑信息以及备份时数据一致性的 min_resolved_ts。之后获取恢复目标集群的拓扑信息，以便确保是否开始恢复。Restore worker 会首先恢复集群的 PD 组件，之后根据备份的元数据挂载 TiKV 节点对应的 EBS 快照，接下来根据元数据中的一致性 min_resolved_ts 将集群恢复到一致的状态。\n\n### 测试数据\n\n在以下的内容中，我们会展示一组数据来说明该特性在备份和恢复方面的性能。\n\n**备份阶段**\n\n首先，EBS 卷快照备份阶段包含创建备份任务、停止调度、停止 GC、获取备份时间 backup_ts 以及卷快照, 其时间占比如下：\n\n![EBS 卷快照备份时间占比.png](https://img1.www.pingcap.com/prod/EBS_e003e8e9b5.png)\n\n由于创建 EBS 卷快照是并行的，因此整个备份的时间取决于耗时最久数据卷快照创建时间，与集群规模无关。下面的表格描述了 EBS 卷中数据该变量与备份时间的关系。\n\n![EBS 卷中数据变量与备份时间示意图.png](https://img1.www.pingcap.com/prod/EBS_801bbc5867.png)\n\n经过测试，备份过程对集群的 QPS 影响低于 3%。\n\n**恢复阶段**\n\n对于恢复阶段，由于 EBS 快照的恢复是并发执行的，整体恢复时间取决于恢复最慢的 TiKV 节点，与集群规模也没有很大的关系。基于我们的测试，对于一个 21TB 规模的 TiDB 集群（每个 TiKV 节点采用 1TB 的 EBS 卷）， 可以在 15 分钟左右完成恢复。下面的表格包含了恢复过程中各个阶段的耗时：\n\n![恢复过程中各个阶段的耗时.png](https://img1.www.pingcap.com/prod/_fc6839d1b1.png)\n\n对于各个恢复阶段的详细解释和更多测试数据，请参考 TiDB 文档：基于 EBS 卷快照备份恢复的性能介绍\n\n## 未来规划\n\n接下来，TiDB 的备份恢复特性会沿着基于存储快照技术这个方向继续发展，支持更多云厂商的磁盘快照能力，并以此为基础，发展出更多的高级备份恢复特性。","date":"2023-03-14","author":"高斌","fillInMethod":"writeDirectly","customUrl":"from-disk-snapshot-to-backup-recovery","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？"}},{"relatedBlog":{"body":"## 基于时间点恢复（PiTR）技术介绍\n\n对于数据库产品而言，基于时间点的恢复是非常重要的基础能力，它允许用户根据需要，将数据库恢复到特定时间点，以帮助客户的数据库免受意外损坏或错误操作的影响。例如，数据库在某个时间点之后的数据遭受了意外的删除或损坏，则可以使用 PiTR 功能将数据库恢复到该时间点之前的状态，从而避免丢失重要数据。\n\n由于 TiDB 数据库，每一次的数据改变都会产生对应的分布式日志，其中记录了数据库每一次变更的信息，包括事务 ID、时间戳和变更的具体内容。\n\n当用户启用 PiTR 功能后，TiDB 会定期将分布式变更日志保存到外部存储（例如：AWS S3，Azure BloB 或 NFS 等）。如果在某个时间点之后的数据被意外删除或遭受了损坏，则可以使用 BR 工具将之前的数据库备份恢复回来，通过应用保存在外部存储上的数据改变到用户指定的时间点，从而达到定点恢复的目的。\n\n![1.png](https://img1.www.pingcap.com/prod/1_b8e9104e19.png)\n\n上面的图示描述了 PiTR 特性的架构：当用户启动了日志备份之后，BR 工具会向 PD 注册一个备份任务。同时，某个 TiDB 节点会被选择成为日志备份的协调者，定期与 PD 进行交互，以便计算全局备份 checkpoint ts。同时，每个 TiKV 节点会运行定期向 PD 上报本节点的备份任务状态，并将数据变更日志发送到指定的外部存储上。  \n\n对于恢复过程，当用户发起了基于时间点的恢复命令之后，BR 工具会读取备份的元数据信息，并通知所有的 TiKV 节点启动恢复工作，TiKV 节点上的 Restore worker 会读取定点之前的变更日志并将其应用集群中，就可以得到指定时间点的 TiDB 集群。\n\n## PiTR 特性的工作机制\n\n接下来，我们进一步看一下日志备份和恢复过程的工作机制。\n\n下面的流程图说明了日志备份的主要工作机制\n\n![2.png](https://img1.www.pingcap.com/prod/2_13fab76e8c.png)\n\n其中主要的交互流程如下：\n\n1.BR 接收备份命令 br log start\n\n解析日志备份任务的日志备份起始时间点和备份存储地址，并向 PD 注册日志备份任务 (log backup task)。\n\n2.TiKV 定期监测新建/更新的日志备份任务\n\n每个 TiKV 节点的日志备份 observer 监听 PD 中创建与更新日志备份任务，然后备份该节点上在备份时间范围内的变更数据日志。\n\n3.TiKV 节点备份 KV 变更日志，并将本地备份进度上报到 TiDB\n\nTiKV 节点中 observer 服务会持续地备份 KV 变更日志，联合从 PD 查询到的 global-checkpoint-ts 来生成备份元数据信息，并定期将日志备份数据和元信息上传到存储中，同时 observer 服务还会防止未备份完成的 MVCC 数据被 PD 回收。\n\n4.TiDB 节点计算并持久化全局备份进度。\n\nTiDB 协调者节点轮询所有 TiKV 节点，获取各个 Region 的备份进度 ，并根据各个节点的备份进度计算出整体日志备份的进度，然后上报给 PD。\n\n对于恢复的过程，可以参考下面的流程图了解其工作机制\n\n![3.png](https://img1.www.pingcap.com/prod/3_d93b3b7629.png)\n\n当用户发起“br restore <timespot>” 命令后，BR 工具会对全量数据和日志数据备份地址、需要恢复到的时间点，需要恢复的数据库对象等信息进行校验，确保信息有效后，开始进行恢复。BR 首先会将全量数据进行恢复，之后读取存在的日志备份数据，计算需要恢复的日志备份数据，并访问 PD 获得需要恢复的 Region 和 KV range 相关的信息，创建恢复日志请求，发送给对应的 TiKV 节点。 TiKV 节点在接收到恢复请求后，启动 restore worker，并从备份介质中下载相应的备份数据到本地，并将需要回复的数据改变恢复到对应的 region 当中。在恢复完成之后，将恢复的执行的结果返回给 BR 工具。\n\n## TiDB 对 PiTR 的优化\n\n从上面的工作机制可以看到， 无论是日志备份还是恢复，其过程都是比较复杂的，所以 TiDB 在PiTR 发布之后，一直对这个特性进行优化，不断的提升 PiTR 的技术指标，稳定性和性能。\n\n例如， 在最初的版本中日志备份会产生大量的小文件，给用户在使用期间带来很多的问题。在最新版本中，我们将日志备份文件聚合成为多个大小至少为128M的文件，很好的解决了这个问题。\n\n对于大规模的 TiDB 集群，其全量备份往往需要运行很长时间，如果不支持断点续传功能的话，当备份过程中出现一些异常情况，导致备份任务中断的话，对用户来说是非常令人绝望的。在 6.5.0 版本中，我们支持了备份的断点续传能力，并且优化了备份的性能，目前单个 TiKV 的数据备份性能可以达到 100MB/s，日志备份对源集群的性能影响可以控制在 5% 左右，这些优化都极大的提升了大规模集群备份的用户体验和备份的成功率。 \n\n由于备份恢复通常都会被用户作为数据安全的最后一道防线，PiTR 的 RPO 和 RTO 指标也是很多用户所关心的。 我们在 PiTR 的稳定性上也做了很多的优化，其中包括：\n\n- 通过优化 BR 与 PD 和 TiKV 的通信机制，在绝大多数 TiDB 集群异常场景和 TiKV 滚动重启场景，PiTR 都可以保证 RPO 小于 5 分钟\n- 通过优化恢复性能，让 PiTR 在应用日志阶段的性能达到30 GB/h，从而降低降低 RTO 时间。 \n \n对于更多的备份恢复性能指标，请参考“[TiDB 备份与恢复概述](https://docs.pingcap.com/zh/tidb/dev/backup-and-restore-overview)” 文档。\n\n## 未来规划\n\n接下来，我们会对 PiTR 这个特性进行更多的优化，不断的提升这个特性的稳定性和性能。并探索备份恢复的更多可能性，将 TiDB 的备份恢复特性打造成稳定可靠的高性能备份恢复解决方案。","author":"高斌","category":1,"customUrl":"optimization-of-tidb-based-on-the-pitr","fillInMethod":"writeDirectly","id":467,"summary":"对于数据库产品而言，基于时间点的恢复是非常重要的基础能力，它允许用户根据需要，将数据库恢复到特定时间点，以帮助客户的数据库免受意外损坏或错误操作的影响。例如，数据库在某个时间点之后的数据遭受了意外的删除或损坏，则可以使用 PiTR 功能将数据库恢复到该时间点之前的状态，从而避免丢失重要数据。","tags":["TiDB","PiTR"],"title":"坚如磐石： TiDB 基于时间点的恢复特性优化之路"}},{"relatedBlog":{"body":"随着业务规模和单表容量的增大，DDL 变更这样普遍的运维操作耗时时间越来越长，给 DBA、研发、业务同学都带来了困扰。在 TiDB 6.5 版本中，在线 DDL 的性能提升 10 倍，可以让用户更加快速平稳地执行 DDL 操作，有效地提升业务发展速度。\n\n本文由 PingCAP 架构师和产研团队撰写，介绍 TiDB Fast DDL 的性能实现数量级提升的原理，并给出 TiDB Cloud 与 Aurora、CockroachDB 以及 TiDB 和 OceanBase 的 Online DDL 的性能测试对比报告，欢迎大家试用并反馈。我们将始终如一地迭代演进，期待未来用户执行 DDL 操作像执行简单查询一样淡定坦然。\n\n## 业务需求\n\n根据业务需求对表结构进行变更是个普遍的运维操作，常见的 DDL 操作包括给表新增列、或给某些列添加二级索引等。在过去的几年中，我们观察到，当业务规模越来越大，用户的单表容量也越来越大，而单次添加索引的操作耗时越来越长，甚至达到了天级，这种操作潜藏的风险让用户不得不焦躁地反复和研发、DBA 同学沟通确认，严重影响了业务的发展速度。此外，不少用户有同时变更多张表的诉求，排队的 DDL 变更让用户更加担忧。在为用户 case by case 解决了很多 DDL 带来的问题的同时我们也在不断的思考和讨论：集群规模越来越大，云上客户越来越多，究竟应该如何让客户少为 DDL 担忧，能够随时执行 DDL。\n\n## 优化演进\n\n“天下武功唯快不破”，解决 DDL 带来的问题，本质上只需要做到一点：降低 DDL 的执行耗时。如果 DDL 可以在指定时间窗口内快速完成，那么 DDL 带来的诸多问题都将迎刃而解。于是我们提出了性能优化先行、兼容性和资源管控跟随的整体解决方案。相比之前版本，TiDB v6.5.0 支持多表 DDL 并行执行、支持 [Fast DDL](https://docs.pingcap.com/tidb/dev/system-variables#tidb_ddl_enable_fast_reorg-new-in-v630) 在线添加索引提速 10x、支持单一 SQL 语句增删改多个列或索引、并支持轻量级 MDL 元数据锁彻底地解决了 DDL 变更过程中 DML 可能遇到的 `information schema is changed` 的问题。\n\n接下来我们重点介绍 TiDB 的 [Fast DDL](https://docs.pingcap.com/tidb/dev/system-variables#tidb_ddl_enable_fast_reorg-new-in-v630) 是如何实现在线添加索引的性能提升 10 倍的。我们通过分析发现，原生 Online DDL 方案中处理最慢的地方是扫描全表创建索引数据的阶段，而创建索引数据的最大性能瓶颈点是按照事务批量回填索引的方式，因此我们考虑从全量数据的索引创建模式、数据传输、并行导入三方面进行改造。\n\n**1 转变索引创建模式**\n\n![1.png](https://img1.www.pingcap.com/prod/1_8d2f3d67e5.png)\n\n上图左侧展示了原生 Online DDL 方案中，创建索引的流程分为两部分：首先扫描全表数据，之后根据扫描的数据构造索引 KV 对，按照 `tidb_ddl_reorg_batch_size` 设置的大小分批次以事务方式提交索引记录到 TiKV。该方式存在两方面的性能开销：\n\n1. 索引记录在事务两阶段提交的时间开销：因为每个索引事务提交的数据 batch-size 通常在 256 或者更小，当索引记录比较多的时候，索引以事务方式提交回 TiKV 的总事务提交时间是非常可观的。\n2. 索引事务和用户事务提交冲突时回滚和重试的开销：原生方案在索引记录回填阶段采用事务方式提交数据，当该方式提交的索引记录与用户业务提交的索引记录存在冲突更新时，将触发用户事务或者索引回填事务回滚和重试，从而影响性能。\n\n我们将原生方式中事务批量写入模式改进为文件批量导入的模式，如上图右侧所示：首先仍是扫描全表数据，之后根据扫描的数据构造索引 KV 对并存入 TiDB 的本地存储，在 TiDB 对于 KV 进行排序后，最终以 [Ingest](https://docs.pingcap.com/zh/tidb/dev/tidb-lightning-glossary#ingest) 方式将索引记录写入 TiKV。新方案消除了两阶段事务的提交时间开销以及索引回填事务与用户事务提交冲突回滚的开销。\n\n**2 优化数据传输**\n\n针对索引创建阶段的数据传输，我们做了极致的优化：原生方案中我们需要将每一行表记录返回到 TiDB，选出其中的索引需要的列，构造成为索引的 KV；新方案中，在 TiKV 层返回数据回 TiDB 之前我们先将索引需要的列取出，只返回创建索引真正需要的列，极大的降低了数据传输的总量，从而减少了整体创建索引的总时间。\n\n**3 实现并行导入**\n\n最后，我们通过并行导入的方式将索引记录以 Ingest 方式导入到 TiKV，并行导入提升了数据写回 TiKV 的效率，但同时也给 TiKV 在线处理负载带来了一定压力。我们正在研发系列流控手段，让并行导入能够既充分利用 TiKV 的空闲带宽，同时不给 TiKV 正常处理负载带来过大压力。\n \n## 性能测试\n\n### 使用说明\n\nTiDB v6.5.0 版本上默认开启了 Fast DDL 功能，我们可以通过参数开启或者关闭该功能，开启该功能之后可以通过参数 tidb_ddl_reorg_worker_cnt 控制并发度从而控制 DDL 的速度； TiDB On-Premise 的集群则允许用户灵活调整系统参数 tidb_ddl_disk_quota 和 TiDB 的配置文件参数 --temp-dir 来控制存储临时文件空间的大小，从而进一步控制 DDL 的速度；TiDB Cloud 集群则已经是云上最优配置。\n\n|   参数  |  Scope   |  Type   |   Default  |  Description   |\n| --- | --- | --- | --- | --- |\n|  `tidb_ddl_enable_fast_reorg`   |  GLOBAL   |  Boolean   |  `ON`   |   控制是否开启添加索引加速功能，来提升创建索引回填过程的速度。  |\n|  `tidb_ddl_reorg_worker_cnt`   |   GLOBAL  |   Integer  |  4   |   设置 DDL 操作 `re-organize` 阶段的并发度。  |\n|   `tidb_ddl_disk_quota`  |   GLOBAL  |  Interger   |  107374182400   |  控制创建索引回填过程中使用到的本地存储空间大小，默认为 100 GB。   |\n\n### TiDB Cloud\n\n以 Sysbench 基准测试为例，在最常见的创建索引场景下，我们对比了 TiDB v6.1.0、Aurora、CockroachDB v22.2、TiDB v6.5.0 在云上费用相近时，不同数据量的表在 `INT` 数据类型的字段 `k` 上创建二级索引时 DDL 执行效率的提升比例。\n\n| 数据库    | 版本    |   集群配置  |  费用 ( $/hour )   |\n| --- | --- | --- | --- |\n|   TiDB  |   v6.1.0 /  v6.5.0  |   TiDB:  ( 16c Core + 32GB ) * 2 ；TiKV:  ( 16c Core + 64GB + 1TB) * 9   |   21.32  |\n|  Aurora   |   v3.02.2  |   db.r5.8xlarge * 2   |   21  |\n|  CockroachDB   |   v22.2  |  ( 16c Core + 60GB + 1TB ) * 6   |  21.17   |\n\n- 空闲负载时，TiDB v6.5.0 在线加索引性能约是 TiDB v6.1.0 LTS 版本的 10 倍，CockroachDB v22.2 的 3 倍，Aurora 的 2.7 倍。\n\n![4.png](https://img1.www.pingcap.com/prod/4_f36f88c238.png)\n\n- Sysbench OLTP_READ_WRITE 负载模式，集群 QPS 约 10K时，TiDB v6.5.0 在线添加索引的性能约是 TiDB v6.1.0 LTS 版本的 8 ~ 13 倍， CockroachDB v22.2 的 3 倍；考虑到 Aurora 在线 DDL 会自动强制终止只读实例上的相关查询，多数客户通常使用 gh-ost / pt-osc / osc 在 Aurora 做 Schema 变更操作，因此就不再和 Aurora 对比带负载的性能测试结果。\n\n![5.png](https://img1.www.pingcap.com/prod/5_6455eff1b1.png)\n\n- 空闲负载时，并行参数 `tidb_ddl_reorg_worker_cnt` 参数分别设置为 1、2、4、8 和 16 时，TiDB 在不同数据量的表中开启 FAST DDL 时在线添加索引的性能提升比例如下图所示：\n\n![6.png](https://img1.www.pingcap.com/prod/6_634250331f.png)\n\n### TiDB On-Premise\n\n仍以Sysbench 基准测试为例，在相同物理配置的集群上，我们对比了 TiDB 和 OceanBase 两款数据库最新版本下，不同数据量的表在 `INT` 数据类型的字段 `k` 上创建二级索引时 DDL 执行效率。\n\n| 数据库    | 版本    | 集群配置    |\n| --- | --- | --- |\n|   TiDB  |   v6.5.0  |  ( 18 Core 2.60GHz *2, 512 GB Mem, 3.84 TB NVME * 2 ) * 3；部署模式：TiDB、TiKV、PD 混合部署，NUMA 绑定   |\n|  OceanBase   |  4.0 CE   |   ( 18 Core 2.60GHz *2, 512 GB Mem, 3.84 TB NVME * 2 ) * 3；部署模式：Clog 和 Data 使用各自独立的 NVME 磁盘，租户配置 69 个 CPU，210GB 内存  |\n\nOceanBase 可以通过 `/*+ PARALLEL(N) */` 来控制创建索引的并发度：\n\n```sql\n-- OceanBase 使用并发度3在线创建索引\nCREATE /*+ PARALLEL(3) */ INDEX k_1 ON sbtest.sbtest1(k);\n```\n\n如前文所述，TiDB 则可以通过 `tidb_ddl_reorg_worker_cnt` 参数来控制 DDL 的并发度：\n\n```sql\n-- TiDB 调整 DDL 操作的并发度为3\nSET GLOBAL tidb_ddl_reorg_worker_cnt=3；\n```\n\n- 空闲负载时，采用相同的并发度（分别设置并发度为 3、6、9 ）在线添加索引，TiDB 需要的时间明显少于 OceanBase，尤其是在 OceanBase 默认并发度 3 时，TiDB 比 OceanBase 快将近 1 倍。\n\n![8.png](https://img1.www.pingcap.com/prod/8_7804f6175e.png)\n\n- Sysbench OLTP_READ_WRITE  负载模式，集群 QPS 约 60K，采用相同的并发度（分别设置并发度为 3、6、9 ）在线添加索引，TiDB 和 OceanBase 的在线加索引耗时基本持平，互有优势：OceanBase 默认并发度配置下，TiDB 加索引速度略快；随着并发度的提升，OceanBase 的 DDL 速度提升略快。\n\n![9.png](https://img1.www.pingcap.com/prod/9_3b6dd94bd6.png)\n\n## 使用限制\n\nTiDB 的 Fast DDL 当前仍存在如下 3 点限制，我们预计在 2023 年末发布的 LTS 版本解除这部分限制：\n- 目前 Fast DDL 功能仅支持支持创建二级索引操作。\n- 多表同时并行执行 DDL 任务时，考虑到并发的资源限制，仅有 1 个 DDL 任务启用 Fast DDL。\n- 当前 Fast DDL 功能与 [PITR (Point-in-time recovery)](https://docs.pingcap.com/zh/tidb/dev/br-pitr-guide) 功能不兼容，在使用 Fast DDL 功能时，需要手动做一次全量备份任务，确保 PITR 的备份基础数据的完整。\n\n## 未来展望\n\nDDL 操作是数据库管理操作中最繁重的一种，而性能优化先行、资源管控跟随的整体解决方案能够切实解决 DDL 的繁重弊端。下个 LTS 版本的在线 DDL 的性能将 v6.5.0 基础上再提升一个数量级，并覆盖更多的 DDL 操作；结合资源管控和 TiDB Cloud 云上的弹性伸缩能力，TiDB Cloud 将提供更加全面、弹性、平滑、高速的多表并行 Fast DDL。相信经过未来若干版本的迭代，未来用户执行 DDL 操作可以像执行简单查询一样淡定坦然。欢迎各位和我们一起开启新的[奇妙旅程](https://cn.pingcap.com/product/#SelectProduct)。\n\n![TiDB v6.5.0-index-acceleration.mp4](https://img1.www.pingcap.com/prod/Ti_DB_v6_5_0_index_acceleration_ef46e0ec26.mp4)","author":"黄潇 Bear. C 谢腾进 庄培培 胡海峰 ","category":1,"customUrl":"10-times-online-ddl-performance-improvement","fillInMethod":"writeDirectly","id":462,"summary":"“天下武功唯快不破”，解决 DDL 带来的问题，本质上只需要做到一点：降低 DDL 的执行耗时。","tags":["TiDB","在线 DDL"],"title":"天下武功唯快不破：在线 DDL 性能提升 10 倍"}}]}}},
    "staticQueryHashes": ["1327623483","1820662718","3081853212","3430003955","3649515864","4265596160","63159454"]}