diff --git a/best-practices/tidb-best-practices.md b/best-practices/tidb-best-practices.md index 0b8260b2f111..13402b7f9bf4 100644 --- a/best-practices/tidb-best-practices.md +++ b/best-practices/tidb-best-practices.md @@ -1,197 +1,197 @@ ---- -title: TiDB 最佳实践 ---- - -# TiDB 最佳实践 - -本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/OLTP 优化技巧,特别是一些 TiDB 专有的优化开关。 - -建议先阅读讲解 TiDB 原理的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),再来看这篇文章。 - -## 前言 - -数据库是一个通用的基础组件,在开发过程中会考虑到多种目标场景,在具体的业务场景中,需要根据业务的实际情况对数据的参数或者使用方式进行调整。 - -TiDB 是一个兼容 MySQL 协议和语法的分布式数据库,但是由于其内部实现,特别是支持分布式存储以及分布式事务,使得一些使用方法和 MySQL 有所区别。 - -## 基本概念 - -TiDB 的最佳实践与其实现原理密切相关,建议读者先了解一些基本的实现机制,包括 Raft、分布式事务、数据分片、负载均衡、SQL 到 KV 的映射方案、二级索引的实现方法、分布式执行引擎。下面会做一点简单的介绍,更详细的信息可以参考 PingCAP 公众号以及知乎专栏的一些文章。 - -### Raft - -Raft 是一种一致性协议,能提供强一致的数据复制保证,TiDB 最底层用 Raft 来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。 - -相比 Master-Slave 方式的同步,同样是保存三副本,Raft 的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。 - -### 分布式事务 - -TiDB 提供完整的分布式事务,事务模型是在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上做了一些优化。具体的实现可以参考[《Percolator 和 TiDB 事务算法》](https://pingcap.com/blog-cn/percolator-and-txn/)这篇文章。本文档只讨论以下几点: - -+ 乐观锁 - - TiDB 的乐观事务模型,只有在真正提交的时候,才会做冲突检测。如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。在冲突严重的场景下,推荐使用悲观锁,或在系统架构层面解决问题,比如将计数器放在 Redis 中。 - -+ 悲观锁 - - TiDB 的悲观事务模式,悲观事务的行为和 MySQL 基本一致,在执行阶段就会上锁,先到先得,避免冲突情况下的重试,可以保证有较多冲突的事务的成功率。悲观锁同时解决了希望通过 `select for update` 对数据提前锁定的场景。但如果业务场景本身冲突较少,乐观锁的性能会更有优势。 - -+ 事务大小限制 - - 由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制: - - - 单个事务包含的 SQL 语句不超过 5000 条(默认) - - 单条 KV entry 不超过 6MB(默认) - - KV entry 的总大小不超过 10G - - 在 Google 的 Cloud Spanner 上面,也有[类似的限制](https://cloud.google.com/spanner/docs/limits)。 - -### 数据分片 - -TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key 的范围,从 `StartKey` 到 `EndKey` 的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。这部分用户不需要担心。 - -### 负载均衡 - -PD 会根据整个 TiKV 集群的状态,对集群的负载进行调度。调度是以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。 - -### SQL on KV - -TiDB 自动将 SQL 结构映射为 KV 结构。具体的可以参考[《三篇文章了解 TiDB 技术内幕 - 说计算》](https://pingcap.com/blog-cn/tidb-internal-2/)这篇文档。简单来说,TiDB 执行了以下操作: - -+ 一行数据映射为一个 KV,Key 以 `TableID` 构造前缀,以行 ID 为后缀 -+ 一条索引映射为一个 KV,Key 以 `TableID+IndexID` 构造前缀,以索引值构造后缀 - -可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key 空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会在很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。同样,如果所有的数据读取操作也都集中在很小的一个范围内(比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。 - -### 二级索引 - -TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。 - -+ 二级索引是否越多越好 - - 二级索引能加速查询,但是要注意新增一个索引是有副作用的。上一节介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。 - -+ 对哪些列建索引比较合适 - - 上文提到,索引很重要但不是越多越好,因此需要根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引: - - - 区分度比较大的列,通过索引能显著地减少过滤后的行数 - - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面 - - 这里举一个例子,假设常用的查询是 `select * from t where c1 = 10 and c2 = 100 and c3 > 10`, 那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。 - -+ 通过索引查询和直接扫描 Table 的区别 - - TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。 - - 如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。 - - 以下情况不会涉及到两次访问的问题: - - - 索引中的列已经满足了查询需求。比如 Table `t` 上面的列 `c` 有索引,查询是 `select c from t where c > 10;`,这个时候,只需要访问索引,就可以拿到所需要的全部数据。这种情况称之为覆盖索引 (Covering Index)。所以如果很关注查询性能,可以将部分不需要过滤但是需要在查询结果中返回的列放入索引中,构造成组合索引,比如这个例子:`select c1, c2 from t where c1 > 10;`,要优化这个查询可以创建组合索引 `Index c12 (c1, c2)`。 - - 表的 Primary Key 是整数类型。在这种情况下,TiDB 会将 Primary Key 的值当做行 ID,所以如果查询条件是在 PK 上面,那么可以直接构造出行 ID 的范围,直接扫描 Table 数据,获取结果。 - -+ 查询并发度 - - 数据分散在很多 Region 上,所以 TiDB 在做查询的时候会并发进行,默认的并发度比较保守,因为过高的并发度会消耗大量的系统资源,且对于 OLTP 类型的查询,往往不会涉及到大量的数据,较低的并发度已经可以满足需求。对于 OLAP 类型的 Query,往往需要较高的并发度。所以 TiDB 支持通过 System Variable 来调整查询并发度。 - - - [tidb_distsql_scan_concurrency](/system-variables.md#tidb_distsql_scan_concurrency) - - 在进行扫描数据的时候的并发度,这里包括扫描 Table 以及索引数据。 - - - [tidb_index_lookup_size](/system-variables.md#tidb_index_lookup_size) - - 如果是需要访问索引获取行 ID 之后再访问 Table 数据,那么每次会把一批行 ID 作为一次请求去访问 Table 数据,这个参数可以设置 Batch 的大小,较大的 Batch 会使得延迟增加,较小的 Batch 可能会造成更多的查询次数。这个参数的合适大小与查询涉及的数据量有关。一般不需要调整。 - - - [tidb_index_lookup_concurrency](/system-variables.md#tidb_index_lookup_concurrency) - - 如果是需要访问索引获取行 ID 之后再访问 Table 数据,每次通过行 ID 获取数据时候的并发度通过这个参数调节。 - -+ 通过索引保证结果顺序 - - 索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 [tidb_index_serial_scan_concurrency](/system-variables.md#tidb_index_serial_scan_concurrency) 变量进行并发度调整。 - -+ 逆序索引 - - 目前 TiDB 支持对索引进行逆序 Scan,目前速度比顺序 Scan 慢一些,通常情况下慢 20%,在数据频繁修改造成版本较多的情况下,会慢的更多。如果可能,建议避免对索引的逆序 Scan。 - -## 场景与实践 - -上一节我们讨论了一些 TiDB 基本的实现机制及其对使用带来的影响,本节我们从具体的使用场景出发,谈一些更为具体的操作实践。我们以从部署到支撑业务这条链路为序,进行讨论。 - -### 部署 - -在部署之前请务必阅读 [TiDB 部署建议以及对硬件的需求](/hardware-and-software-requirements.md)。 - -推荐通过 [TiUP](/production-deployment-using-tiup.md) 部署 TiDB 集群,这个工具可以部署、停止、销毁、升级整个集群,非常方便易用。非常不推荐手动部署,后期的维护和升级会很麻烦。 - -### 导入数据 - -为了提高导入数据期间的写入性能,可以对 TiKV 的参数进行调优,具体的文档查看 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 - -### 写入 - -上面提到了 TiDB 对单个事务的大小有限制,这层限制是在 KV 层面,反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。 - -> **注意:** -> -> 对事务的大小限制,要考虑 TiDB 做编码以及事务额外 Key 的开销,在使用的时候,**建议每个事务的行数不超过 200 行,且单行数据小于 100k**,否则可能性能不佳。 - -建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。 - -在删除大量数据的时候,建议使用 `Delete from t where xx limit 5000;` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件。 - -如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 清理掉),影响后面的 `Delete` 语句。如果有可能,建议把 `Where` 条件细化。举个例子,假设要删除 2017-05-26 当天的所有数据,那么可以这样做: - -```SQL -for i from 0 to 23: - while affected_rows > 0: - delete from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000; - affected_rows = select affected_rows() -``` - -上面是一段伪代码,意思就是要把大块的数据拆成小块删除,以避免删除过程中前面的 Delete 语句影响后面的 Delete 语句。 - -### 查询 - -看业务的查询需求以及具体的语句,可以参考 [TiDB 专用系统变量和语法](/system-variables.md)这篇文档。可以通过 SET 语句控制 SQL 执行的并发度,另外通过 Hint 控制 Join 物理算子选择。 - -另外 MySQL 标准的索引选择 Hint 语法,也可以用,通过 `Use Index/Ignore Index hint` 控制优化器选择索引。 - -如果是个 OLTP 和 OLAP 混合类型的业务,可以把 TP 请求和 AP 请求发送到不同的 tidb-server 上,这样能够减小 AP 业务对于 TP 业务的影响。 承载 AP 业务的 tidb-server 推荐使用高配的机器,比如 CPU 核数比较多,内存比较大。 - -但彻底的隔离 OLTP 和 OLAP,推荐将 OLAP 的业务跑在 TiFlash 上。TiFlash 是列存引擎,在 OLAP 的分析查询场景上,性能极具亮点,TiFlash 可以在存储层上做到物理隔离,并可做到一致性读取。 - -### 监控和日志 - -Metrics 系统是了解系统状态的最佳方法,建议所有的用户都部署监控系统。 - -TiDB [使用 Grafana + Prometheus 监控系统状态](/tidb-monitoring-framework.md)。如果使用 TiUP 部署集群,那么会自动部署和配置监控系统。 - -监控系统中的监控项很多,大部分是给 TiDB 开发者查看的内容,如果没有对源代码比较深入的了解,并没有必要了解这些监控项。我们会精简出一些和业务相关或者是系统关键组件状态相关的监控项,放在一个独立的 `overview` 面板中,供用户使用。 - -除了监控之外,查看日志也是了解系统状态的常用方法。TiDB 的三个组件 tidb-server/tikv-server/pd-server 都有一个 `--log-file` 的参数。如果启动的时候设置了这个参数,那么日志会保存着参数所设置的文件的位置,另外会自动的按天对 Log 文件做归档。如果没有设置 `--log-file` 参数,日志会输出在 `stderr` 中。 - -从 4.0 版本开始,从解决易用性的角度出发,提供了 [TiDB Dashboard](/dashboard/dashboard-intro.md) UI 系统,通过浏览器访问 `http://PD_IP:PD_PORT/dashboard` 即可打开 TiDB Dashboard。TiDB Dashboard 可以提供集群状态、性能分析、流量可视化、SQL 诊断、日志搜索等功能。 - -### 文档 - -了解一个系统或者解决使用中的问题最好的方法是阅读文档,明白实现原理。TiDB 有大量的官方文档,希望大家在遇到问题的时候能先尝试通过文档或者搜索 Issue list 寻找解决方案。官方文档查看 [docs-cn](https://github.com/pingcap/docs-cn)。如果希望阅读英文文档,可以查看 [docs](https://github.com/pingcap/docs)。 - -其中的 [FAQ](/faq/tidb-faq.md) 和[故障诊断](/troubleshoot-tidb-cluster.md)章节建议大家仔细阅读。另外 TiDB 还有一些不错的工具,也有配套的文档,具体的见各项工具的 GitHub 页面。 - -除了文档之外,还有很多不错的文章介绍 TiDB 的各项技术细节内幕,大家可以关注下面这些文章发布渠道: - -+ 公众号:微信搜索 PingCAP -+ 知乎专栏:[TiDB 的后花园](https://zhuanlan.zhihu.com/newsql) -+ [官方博客](https://pingcap.com/blog-cn/) - -## TiDB 的最佳适用场景 - -简单来说,TiDB 适合具备下面这些特点的场景: - -+ 数据量大,单机保存不下 -+ 不希望做 Sharding 或者懒得做 Sharding -+ 访问模式上没有明显的热点 -+ 需要事务、需要强一致、需要灾备 -+ 希望 Real-Time HTAP,减少存储链路 +--- +title: TiDB 最佳实践 +--- + +# TiDB 最佳实践 + +本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/OLTP 优化技巧,特别是一些 TiDB 专有的优化开关。 + +建议先阅读讲解 TiDB 原理的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),再来看这篇文章。 + +## 前言 + +数据库是一个通用的基础组件,在开发过程中会考虑到多种目标场景,在具体的业务场景中,需要根据业务的实际情况对数据的参数或者使用方式进行调整。 + +TiDB 是一个兼容 MySQL 协议和语法的分布式数据库,但是由于其内部实现,特别是支持分布式存储以及分布式事务,使得一些使用方法和 MySQL 有所区别。 + +## 基本概念 + +TiDB 的最佳实践与其实现原理密切相关,建议读者先了解一些基本的实现机制,包括 Raft、分布式事务、数据分片、负载均衡、SQL 到 KV 的映射方案、二级索引的实现方法、分布式执行引擎。下面会做一点简单的介绍,更详细的信息可以参考 PingCAP 公众号以及知乎专栏的一些文章。 + +### Raft + +Raft 是一种一致性协议,能提供强一致的数据复制保证,TiDB 最底层用 Raft 来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。 + +相比 Master-Slave 方式的同步,同样是保存三副本,Raft 的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。 + +### 分布式事务 + +TiDB 提供完整的分布式事务,事务模型是在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上做了一些优化。具体的实现可以参考[《Percolator 和 TiDB 事务算法》](https://pingcap.com/blog-cn/percolator-and-txn/)这篇文章。本文档只讨论以下几点: + ++ 乐观锁 + + TiDB 的乐观事务模型,只有在真正提交的时候,才会做冲突检测。如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。在冲突严重的场景下,推荐使用悲观锁,或在系统架构层面解决问题,比如将计数器放在 Redis 中。 + ++ 悲观锁 + + TiDB 的悲观事务模式,悲观事务的行为和 MySQL 基本一致,在执行阶段就会上锁,先到先得,避免冲突情况下的重试,可以保证有较多冲突的事务的成功率。悲观锁同时解决了希望通过 `select for update` 对数据提前锁定的场景。但如果业务场景本身冲突较少,乐观锁的性能会更有优势。 + ++ 事务大小限制 + + 由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制: + + - 单个事务包含的 SQL 语句不超过 5000 条(默认) + - 单条 KV entry 不超过 6MB(默认) + - KV entry 的总大小不超过 10G + + 在 Google 的 Cloud Spanner 上面,也有[类似的限制](https://cloud.google.com/spanner/docs/limits)。 + +### 数据分片 + +TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key 的范围,从 `StartKey` 到 `EndKey` 的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。这部分用户不需要担心。 + +### 负载均衡 + +PD 会根据整个 TiKV 集群的状态,对集群的负载进行调度。调度是以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。 + +### SQL on KV + +TiDB 自动将 SQL 结构映射为 KV 结构。具体的可以参考[《三篇文章了解 TiDB 技术内幕 - 说计算》](https://pingcap.com/blog-cn/tidb-internal-2/)这篇文档。简单来说,TiDB 执行了以下操作: + ++ 一行数据映射为一个 KV,Key 以 `TableID` 构造前缀,以行 ID 为后缀 ++ 一条索引映射为一个 KV,Key 以 `TableID+IndexID` 构造前缀,以索引值构造后缀 + +可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key 空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会在很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。同样,如果所有的数据读取操作也都集中在很小的一个范围内(比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。 + +### 二级索引 + +TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。 + ++ 二级索引是否越多越好 + + 二级索引能加速查询,但是要注意新增一个索引是有副作用的。上一节介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。 + ++ 对哪些列建索引比较合适 + + 上文提到,索引很重要但不是越多越好,因此需要根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引: + + - 区分度比较大的列,通过索引能显著地减少过滤后的行数 + - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面 + + 这里举一个例子,假设常用的查询是 `select * from t where c1 = 10 and c2 = 100 and c3 > 10`, 那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。 + ++ 通过索引查询和直接扫描 Table 的区别 + + TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。 + + 如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。 + + 以下情况不会涉及到两次访问的问题: + + - 索引中的列已经满足了查询需求。比如 Table `t` 上面的列 `c` 有索引,查询是 `select c from t where c > 10;`,这个时候,只需要访问索引,就可以拿到所需要的全部数据。这种情况称之为覆盖索引 (Covering Index)。所以如果很关注查询性能,可以将部分不需要过滤但是需要在查询结果中返回的列放入索引中,构造成组合索引,比如这个例子:`select c1, c2 from t where c1 > 10;`,要优化这个查询可以创建组合索引 `Index c12 (c1, c2)`。 + - 表的 Primary Key 是整数类型。在这种情况下,TiDB 会将 Primary Key 的值当做行 ID,所以如果查询条件是在 PK 上面,那么可以直接构造出行 ID 的范围,直接扫描 Table 数据,获取结果。 + ++ 查询并发度 + + 数据分散在很多 Region 上,所以 TiDB 在做查询的时候会并发进行,默认的并发度比较保守,因为过高的并发度会消耗大量的系统资源,且对于 OLTP 类型的查询,往往不会涉及到大量的数据,较低的并发度已经可以满足需求。对于 OLAP 类型的 Query,往往需要较高的并发度。所以 TiDB 支持通过 System Variable 来调整查询并发度。 + + - [tidb_distsql_scan_concurrency](/system-variables.md#tidb_distsql_scan_concurrency) + + 在进行扫描数据的时候的并发度,这里包括扫描 Table 以及索引数据。 + + - [tidb_index_lookup_size](/system-variables.md#tidb_index_lookup_size) + + 如果是需要访问索引获取行 ID 之后再访问 Table 数据,那么每次会把一批行 ID 作为一次请求去访问 Table 数据,这个参数可以设置 Batch 的大小,较大的 Batch 会使得延迟增加,较小的 Batch 可能会造成更多的查询次数。这个参数的合适大小与查询涉及的数据量有关。一般不需要调整。 + + - [tidb_index_lookup_concurrency](/system-variables.md#tidb_index_lookup_concurrency) + + 如果是需要访问索引获取行 ID 之后再访问 Table 数据,每次通过行 ID 获取数据时候的并发度通过这个参数调节。 + ++ 通过索引保证结果顺序 + + 索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 [tidb_index_serial_scan_concurrency](/system-variables.md#tidb_index_serial_scan_concurrency) 变量进行并发度调整。 + ++ 逆序索引 + + 目前 TiDB 支持对索引进行逆序 Scan,目前速度比顺序 Scan 慢一些,通常情况下慢 20%,在数据频繁修改造成版本较多的情况下,会慢的更多。如果可能,建议避免对索引的逆序 Scan。 + +## 场景与实践 + +上一节我们讨论了一些 TiDB 基本的实现机制及其对使用带来的影响,本节我们从具体的使用场景出发,谈一些更为具体的操作实践。我们以从部署到支撑业务这条链路为序,进行讨论。 + +### 部署 + +在部署之前请务必阅读 [TiDB 部署建议以及对硬件的需求](/hardware-and-software-requirements.md)。 + +推荐通过 [TiUP](/production-deployment-using-tiup.md) 部署 TiDB 集群,这个工具可以部署、停止、销毁、升级整个集群,非常方便易用。非常不推荐手动部署,后期的维护和升级会很麻烦。 + +### 导入数据 + +为了提高导入数据期间的写入性能,可以对 TiKV 的参数进行调优,具体的文档查看 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 + +### 写入 + +上面提到了 TiDB 对单个事务的大小有限制,这层限制是在 KV 层面,反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。 + +> **注意:** +> +> 对事务的大小限制,要考虑 TiDB 做编码以及事务额外 Key 的开销,在使用的时候,**建议每个事务的行数不超过 200 行,且单行数据小于 100k**,否则可能性能不佳。 + +建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。 + +在删除大量数据的时候,建议使用 `Delete from t where xx limit 5000;` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件。 + +如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 清理掉),影响后面的 `Delete` 语句。如果有可能,建议把 `Where` 条件细化。举个例子,假设要删除 2017-05-26 当天的所有数据,那么可以这样做: + +```SQL +for i from 0 to 23: + while affected_rows > 0: + delete from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000; + affected_rows = select affected_rows() +``` + +上面是一段伪代码,意思就是要把大块的数据拆成小块删除,以避免删除过程中前面的 Delete 语句影响后面的 Delete 语句。 + +### 查询 + +看业务的查询需求以及具体的语句,可以参考 [TiDB 专用系统变量和语法](/system-variables.md)这篇文档。可以通过 SET 语句控制 SQL 执行的并发度,另外通过 Hint 控制 Join 物理算子选择。 + +另外 MySQL 标准的索引选择 Hint 语法,也可以用,通过 `Use Index/Ignore Index hint` 控制优化器选择索引。 + +如果是个 OLTP 和 OLAP 混合类型的业务,可以把 TP 请求和 AP 请求发送到不同的 tidb-server 上,这样能够减小 AP 业务对于 TP 业务的影响。 承载 AP 业务的 tidb-server 推荐使用高配的机器,比如 CPU 核数比较多,内存比较大。 + +但彻底的隔离 OLTP 和 OLAP,推荐将 OLAP 的业务跑在 TiFlash 上。TiFlash 是列存引擎,在 OLAP 的分析查询场景上,性能极具亮点,TiFlash 可以在存储层上做到物理隔离,并可做到一致性读取。 + +### 监控和日志 + +Metrics 系统是了解系统状态的最佳方法,建议所有的用户都部署监控系统。 + +TiDB [使用 Grafana + Prometheus 监控系统状态](/tidb-monitoring-framework.md)。如果使用 TiUP 部署集群,那么会自动部署和配置监控系统。 + +监控系统中的监控项很多,大部分是给 TiDB 开发者查看的内容,如果没有对源代码比较深入的了解,并没有必要了解这些监控项。我们会精简出一些和业务相关或者是系统关键组件状态相关的监控项,放在一个独立的 `overview` 面板中,供用户使用。 + +除了监控之外,查看日志也是了解系统状态的常用方法。TiDB 的三个组件 tidb-server/tikv-server/pd-server 都有一个 `--log-file` 的参数。如果启动的时候设置了这个参数,那么日志会保存着参数所设置的文件的位置,另外会自动的按天对 Log 文件做归档。如果没有设置 `--log-file` 参数,日志会输出在 `stderr` 中。 + +从 4.0 版本开始,从解决易用性的角度出发,提供了 [TiDB Dashboard](/dashboard/dashboard-intro.md) UI 系统,通过浏览器访问 `http://PD_IP:PD_PORT/dashboard` 即可打开 TiDB Dashboard。TiDB Dashboard 可以提供集群状态、性能分析、流量可视化、SQL 诊断、日志搜索等功能。 + +### 文档 + +了解一个系统或者解决使用中的问题最好的方法是阅读文档,明白实现原理。TiDB 有大量的官方文档,希望大家在遇到问题的时候能先尝试通过文档或者搜索 Issue list 寻找解决方案。官方文档查看 [docs-cn](https://github.com/pingcap/docs-cn)。如果希望阅读英文文档,可以查看 [docs](https://github.com/pingcap/docs)。 + +其中的 [FAQ](/faq/tidb-faq.md) 和[故障诊断](/troubleshoot-tidb-cluster.md)章节建议大家仔细阅读。另外 TiDB 还有一些不错的工具,也有配套的文档,具体的见各项工具的 GitHub 页面。 + +除了文档之外,还有很多不错的文章介绍 TiDB 的各项技术细节内幕,大家可以关注下面这些文章发布渠道: + ++ 公众号:微信搜索 PingCAP ++ 知乎专栏:[TiDB 的后花园](https://zhuanlan.zhihu.com/newsql) ++ [官方博客](https://pingcap.com/blog-cn/) + +## TiDB 的最佳适用场景 + +简单来说,TiDB 适合具备下面这些特点的场景: + ++ 数据量大,单机保存不下 ++ 不希望做 Sharding 或者懒得做 Sharding ++ 访问模式上没有明显的热点 ++ 需要事务、需要强一致、需要灾备 ++ 希望 Real-Time HTAP,减少存储链路 diff --git a/blocklist-control-plan.md b/blocklist-control-plan.md index 66255c9adf66..ffb21cc7837f 100644 --- a/blocklist-control-plan.md +++ b/blocklist-control-plan.md @@ -72,14 +72,30 @@ summary: 了解优化规则与表达式下推的黑名单。 ### 已支持下推的表达式 -| 表达式分类 | 具体操作 | -| :-------------- | :------------------------------------- | -| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | -| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | <, <=, =, != (`<>`), >, >=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | -| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, *, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | -| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_ifnull) | -| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-type),<br/> [JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract),<br/> [JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote),<br/> [JSON_OBJECT(key, val[, key, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object),<br/> [JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array),<br/> [JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge),<br/> [JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set),<br/> [JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert),<br/> [JSON_REPLACE(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace),<br/> [JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove) | -| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 表达式分类 | 具体操作 | ++:========================================================================+:==============================================================================================================================================================================================================================================================================================================================================================================================================+ +| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | \<, \<=, =, != (`<>`), \>, \>=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, \*, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_ifnull) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-type), | +| | [JSON_EXTRACT(json_doc, path\[, path\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract), | +| | [JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote), | +| | [JSON_OBJECT(key, val\[, key, val\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object), | +| | [JSON_ARRAY(\[val\[, val\] ...\])](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array), | +| | [JSON_MERGE(json_doc, json_doc\[, json_doc\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge), | +| | [JSON_SET(json_doc, path, val\[, path, val\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set), | +| | [JSON_INSERT(json_doc, path, val\[, path, val\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert), | +| | [JSON_REPLACE(json_doc, path, val\[, path, val\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace), | +| | [JSON_REMOVE(json_doc, path\[, path\] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ### 禁止特定表达式下推 diff --git a/connectors-and-apis.md b/connectors-and-apis.md index 754d8d50f31d..e5e0c6db1bd9 100644 --- a/connectors-and-apis.md +++ b/connectors-and-apis.md @@ -40,40 +40,73 @@ Oracle 官方提供了以下 API,TiDB 可以兼容所有这些 API。 第三方 API 非 Oracle 官方提供,下表列出了常用的第三方 API: -| Environment | API | Type | Notes | -| -------------- | ---------------------------------------- | -------------------------------- | ---------------------------------------- | -| Ada | GNU Ada MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for GNU Ada](http://gnade.sourceforge.net/) | -| C | C API | `libmysqlclient` | See [MySQL C API](https://dev.mysql.com/doc/refman/5.7/en/c-api-info.html). | -| C++ | Connector/C++ | `libmysqlclient` | See [MySQL Connector/C++ Developer Guide](https://dev.mysql.com/doc/connector-cpp/en/). | -| | MySQL++ | `libmysqlclient` | See [MySQL++ Web site](http://tangentsoft.net/mysql++/doc/). | -| | MySQL wrapped | `libmysqlclient` | See [MySQL wrapped](http://www.alhem.net/project/mysql/). | -| Go | go-sql-driver | Native Driver | See [Mysql Go API](https://github.com/go-sql-driver/mysql) | -| Cocoa | MySQL-Cocoa | `libmysqlclient` | Compatible with the Objective-C Cocoa environment. See <http://mysql-cocoa.sourceforge.net/> | -| D | MySQL for D | `libmysqlclient` | See [MySQL for D](https://github.com/mysql-d/mysql-native). | -| Eiffel | Eiffel MySQL | `libmysqlclient` | See [Section 27.14, “MySQL Eiffel Wrapper”](https://dev.mysql.com/doc/refman/5.7/en/apis-eiffel.html). | -| Erlang | `erlang-mysql-driver` | `libmysqlclient` | See [`erlang-mysql-driver`.](http://code.google.com/p/erlang-mysql-driver/) | -| Haskell | Haskell MySQL Bindings | Native Driver | See [Brian O'Sullivan's pure Haskell MySQL bindings](http://www.serpentine.com/blog/software/mysql/). | -| | `hsql-mysql` | `libmysqlclient` | See [MySQL driver for Haskell](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hsql-mysql-1.7). | -| Java/JDBC | Connector/J | Native Driver | See [MySQL Connector/J 8.0 Developer Guide](https://dev.mysql.com/doc/connector-j/8.0/en/). 说明:目前 MySQL Connector/J 有一个 [critical bug](https://bugs.mysql.com/bug.php?id=106252),可能会导致 v6.0.4 至 v8.0 版本的 MySQL Connector/J 连接较早版本的 MySQL server 或兼容 MySQL 协议的服务器时,出现卡住的问题。该 bug 预计会在后续版本修复。请关注 [MySQL Connector/J 8.0 Release Notes](https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/) 后续的更新。| -| Lua | LuaSQL | `libmysqlclient` | See [LuaSQL](http://keplerproject.github.io/luasql/manual.html). | -| .NET/Mono | Connector/Net | Native Driver | See [MySQL Connector/Net Developer Guide](https://dev.mysql.com/doc/connector-net/en/). | -| Objective Caml | OBjective Caml MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for Objective Caml](http://raevnos.pennmush.org/code/ocaml-mysql/). | -| Octave | Database bindings for GNU Octave | `libmysqlclient` | See [Database bindings for GNU Octave](http://octave.sourceforge.net/database/index.html). | -| ODBC | Connector/ODBC | `libmysqlclient` | See [MySQL Connector/ODBC Developer Guide](https://dev.mysql.com/doc/connector-odbc/en/). | -| Perl | `DBI`/`DBD::mysql` | `libmysqlclient` | See [Section 27.10, “MySQL Perl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-perl.html). | -| | `Net::MySQL` | Native Driver | See [`Net::MySQL`](http://search.cpan.org/dist/Net-MySQL/MySQL.pm) at CPAN | -| PHP | `mysql`, `ext/mysql`interface (deprecated) | `libmysqlclient` | See [Original MySQL API](https://dev.mysql.com/doc/apis-php/en/apis-php-mysql.html). | -| | `mysqli`, `ext/mysqli`interface | `libmysqlclient` | See [MySQL Improved Extension](https://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.html). | -| | `PDO_MYSQL` | `libmysqlclient` | See [MySQL Functions (PDO_MYSQL)](https://dev.mysql.com/doc/apis-php/en/apis-php-pdo-mysql.html). | -| | PDO mysqlnd | Native Driver | | -| Python | Connector/Python | Native Driver | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | -| Python | Connector/Python C Extension | `libmysqlclient` | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | -| | MySQLdb | `libmysqlclient` | See [Section 27.11, “MySQL Python API”](https://dev.mysql.com/doc/refman/5.7/en/apis-python.html). | -| Ruby | MySQL/Ruby | `libmysqlclient` | Uses `libmysqlclient`. See [Section 27.12.1, “The MySQL/Ruby API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-mysqlruby.html). | -| | Ruby/MySQL | Native Driver | See [Section 27.12.2, “The Ruby/MySQL API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-rubymysql.html). | -| Scheme | `Myscsh` | `libmysqlclient` | See [`Myscsh`](https://github.com/aehrisch/myscsh). | -| SPL | `sql_mysql` | `libmysqlclient` | See [`sql_mysql` for SPL](http://www.clifford.at/spl/spldoc/sql_mysql.html). | -| Tcl | MySQLtcl | `libmysqlclient` | See [Section 27.13, “MySQL Tcl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-tcl.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Environment | API | Type | Notes | ++================+============================================+==================+======================================================================================================================================================================================================================================================================================================================================================================================================================================================================+ +| Ada | GNU Ada MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for GNU Ada](http://gnade.sourceforge.net/) | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| C | C API | `libmysqlclient` | See [MySQL C API](https://dev.mysql.com/doc/refman/5.7/en/c-api-info.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| C++ | Connector/C++ | `libmysqlclient` | See [MySQL Connector/C++ Developer Guide](https://dev.mysql.com/doc/connector-cpp/en/). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | MySQL++ | `libmysqlclient` | See [MySQL++ Web site](http://tangentsoft.net/mysql++/doc/). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | MySQL wrapped | `libmysqlclient` | See [MySQL wrapped](http://www.alhem.net/project/mysql/). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Go | go-sql-driver | Native Driver | See [Mysql Go API](https://github.com/go-sql-driver/mysql) | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Cocoa | MySQL-Cocoa | `libmysqlclient` | Compatible with the Objective-C Cocoa environment. See <http://mysql-cocoa.sourceforge.net/> | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| D | MySQL for D | `libmysqlclient` | See [MySQL for D](https://github.com/mysql-d/mysql-native). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Eiffel | Eiffel MySQL | `libmysqlclient` | See [Section 27.14, “MySQL Eiffel Wrapper”](https://dev.mysql.com/doc/refman/5.7/en/apis-eiffel.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Erlang | `erlang-mysql-driver` | `libmysqlclient` | See [`erlang-mysql-driver`.](http://code.google.com/p/erlang-mysql-driver/) | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Haskell | Haskell MySQL Bindings | Native Driver | See [Brian O'Sullivan's pure Haskell MySQL bindings](http://www.serpentine.com/blog/software/mysql/). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | `hsql-mysql` | `libmysqlclient` | See [MySQL driver for Haskell](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hsql-mysql-1.7). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Java/JDBC | Connector/J | Native Driver | See [MySQL Connector/J 8.0 Developer Guide](https://dev.mysql.com/doc/connector-j/8.0/en/). 说明:目前 MySQL Connector/J 有一个 [critical bug](https://bugs.mysql.com/bug.php?id=106252),可能会导致 v6.0.4 至 v8.0 版本的 MySQL Connector/J 连接较早版本的 MySQL server 或兼容 MySQL 协议的服务器时,出现卡住的问题。该 bug 预计会在后续版本修复。请关注 [MySQL Connector/J 8.0 Release Notes](https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/) 后续的更新。 | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Lua | LuaSQL | `libmysqlclient` | See [LuaSQL](http://keplerproject.github.io/luasql/manual.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| .NET/Mono | Connector/Net | Native Driver | See [MySQL Connector/Net Developer Guide](https://dev.mysql.com/doc/connector-net/en/). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Objective Caml | OBjective Caml MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for Objective Caml](http://raevnos.pennmush.org/code/ocaml-mysql/). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Octave | Database bindings for GNU Octave | `libmysqlclient` | See [Database bindings for GNU Octave](http://octave.sourceforge.net/database/index.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ODBC | Connector/ODBC | `libmysqlclient` | See [MySQL Connector/ODBC Developer Guide](https://dev.mysql.com/doc/connector-odbc/en/). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Perl | `DBI`/`DBD::mysql` | `libmysqlclient` | See [Section 27.10, “MySQL Perl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-perl.html). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | `Net::MySQL` | Native Driver | See [`Net::MySQL`](http://search.cpan.org/dist/Net-MySQL/MySQL.pm) at CPAN | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| PHP | `mysql`, `ext/mysql`interface (deprecated) | `libmysqlclient` | See [Original MySQL API](https://dev.mysql.com/doc/apis-php/en/apis-php-mysql.html). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | `mysqli`, `ext/mysqli`interface | `libmysqlclient` | See [MySQL Improved Extension](https://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.html). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | `PDO_MYSQL` | `libmysqlclient` | See [MySQL Functions (PDO_MYSQL)](https://dev.mysql.com/doc/apis-php/en/apis-php-pdo-mysql.html). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | PDO mysqlnd | Native Driver | | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Python | Connector/Python | Native Driver | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Python | Connector/Python C Extension | `libmysqlclient` | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | MySQLdb | `libmysqlclient` | See [Section 27.11, “MySQL Python API”](https://dev.mysql.com/doc/refman/5.7/en/apis-python.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Ruby | MySQL/Ruby | `libmysqlclient` | Uses `libmysqlclient`. See [Section 27.12.1, “The MySQL/Ruby API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-mysqlruby.html). | +| +--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Ruby/MySQL | Native Driver | See [Section 27.12.2, “The Ruby/MySQL API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-rubymysql.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Scheme | `Myscsh` | `libmysqlclient` | See [`Myscsh`](https://github.com/aehrisch/myscsh). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| SPL | `sql_mysql` | `libmysqlclient` | See [`sql_mysql` for SPL](http://www.clifford.at/spl/spldoc/sql_mysql.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Tcl | MySQLtcl | `libmysqlclient` | See [Section 27.13, “MySQL Tcl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-tcl.html). | ++----------------+--------------------------------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ## TiDB 支持的连接器版本 diff --git a/dumpling-overview.md b/dumpling-overview.md index b692cd09756e..e1b1ae4e8f3e 100644 --- a/dumpling-overview.md +++ b/dumpling-overview.md @@ -337,43 +337,88 @@ SET GLOBAL tidb_gc_life_time = '10m'; ## Dumpling 主要选项表 -| 主要选项 | 用途 | 默认值 | -| --------| --- | --- | -| -V 或 --version | 输出 Dumpling 版本并直接退出 | -| -B 或 --database | 导出指定数据库 | -| -T 或 --tables-list | 导出指定数据表 | -| -f 或 --filter | 导出能匹配模式的表,语法可参考 [table-filter](/table-filter.md) | `[\*.\*,!/^(mysql|sys|INFORMATION_SCHEMA|PERFORMANCE_SCHEMA|METRICS_SCHEMA|INSPECTION_SCHEMA)$/.\*]`(导出除系统库外的所有库表) | -| --case-sensitive | table-filter 是否大小写敏感 | false,大小写不敏感 | -| -h 或 --host| 连接的数据库主机的地址 | "127.0.0.1" | -| -t 或 --threads | 备份并发线程数| 4 | -| -r 或 --rows | 将 table 划分成 row 行数据,一般针对大表操作并发生成多个文件。当上游为 TiDB 且版本为 v3.0 或更新版本时,该参数大于 0 表示使用 TiDB region 信息划分表内并发,具体取值将不再生效。 | -| -L 或 --logfile | 日志输出地址,为空时会输出到控制台 | "" | -| --loglevel | 日志级别 {debug,info,warn,error,dpanic,panic,fatal} | "info" | -| --logfmt | 日志输出格式 {text,json} | "text" | -| -d 或 --no-data | 不导出数据,适用于只导出 schema 场景 | -| --no-header | 导出 csv 格式的 table 数据,不生成 header | -| -W 或 --no-views| 不导出 view | true | -| -m 或 --no-schemas | 不导出 schema,只导出数据 | -| -s 或--statement-size | 控制 `INSERT` SQL 语句的大小,单位 bytes | -| -F 或 --filesize | 将 table 数据划分出来的文件大小,需指明单位(如 `128B`, `64KiB`, `32MiB`, `1.5GiB`) | -| --filetype| 导出文件类型(csv/sql) | "sql" | -| -o 或 --output | 导出本地文件路径或[外部存储 URL](/br/backup-and-restore-storages.md) | "./export-${time}" | -| -S 或 --sql | 根据指定的 sql 导出数据,该选项不支持并发导出 | -| --consistency | flush: dump 前用 FTWRL <br/> snapshot: 通过 TSO 来指定 dump 某个快照时间点的 TiDB 数据 <br/> lock: 对需要 dump 的所有表执行 `lock tables read` 命令 <br/> none: 不加锁 dump,无法保证一致性 <br/> auto: 对 MySQL 使用 --consistency flush;对 TiDB 使用 --consistency snapshot | "auto" | -| --snapshot | snapshot tso,只在 consistency=snapshot 下生效 | -| --where | 对备份的数据表通过 where 条件指定范围 | -| -p 或 --password | 连接的数据库主机的密码 | -| -P 或 --port | 连接的数据库主机的端口 | 4000 | -| -u 或 --user | 连接的数据库主机的用户名 | "root" | -| --dump-empty-database | 导出空数据库的建库语句 | true | -| --ca | 用于 TLS 连接的 certificate authority 文件的地址 | -| --cert | 用于 TLS 连接的 client certificate 文件的地址 | -| --key | 用于 TLS 连接的 client private key 文件的地址 | -| --csv-delimiter | csv 文件中字符类型变量的定界符 | '"' | -| --csv-separator | csv 文件中各值的分隔符,如果数据中可能有逗号,建议源文件导出时分隔符使用非常见组合字符| ','| -| --csv-null-value | csv 文件空值的表示 | "\\N" | -| --escape-backslash | 使用反斜杠 (`\`) 来转义导出文件中的特殊字符 | true | -| --output-filename-template | 以 [golang template](https://golang.org/pkg/text/template/#hdr-Arguments) 格式表示的数据文件名格式 <br/> 支持 `{{.DB}}`、`{{.Table}}`、`{{.Index}}` 三个参数 <br/> 分别表示数据文件的库名、表名、分块 ID | '{{.DB}}.{{.Table}}.{{.Index}}' | -| --status-addr | Dumpling 的服务地址,包含了 Prometheus 拉取 metrics 信息及 pprof 调试的地址 | ":8281" | -| --tidb-mem-quota-query | 单条 dumpling 命令导出 SQL 语句的内存限制,单位为 byte。对于 v4.0.10 或以上版本,若不设置该参数,默认使用 TiDB 中的 `mem-quota-query` 配置项值作为内存限制值。对于 v4.0.10 以下版本,该参数值默认为 32 GB | 34359738368 | -| --params | 为需导出的数据库连接指定 session 变量,可接受的格式: "character_set_client=latin1,character_set_connection=latin1" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 主要选项 | 用途 | 默认值 | ++============================+===========================================================================================================================================================================================================+===========================================================================================================================================================+ +| -V 或 --version | 输出 Dumpling 版本并直接退出 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -B 或 --database | 导出指定数据库 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -T 或 --tables-list | 导出指定数据表 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -f 或 --filter | 导出能匹配模式的表,语法可参考 [table-filter](/table-filter.md) | `[\*.\*,!/^(mysql|sys|INFORMATION_SCHEMA|PERFORMANCE_SCHEMA|METRICS_SCHEMA|INSPECTION_SCHEMA)$/.\*]`(导出除系统库外的所有库表) | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --case-sensitive | table-filter 是否大小写敏感 | false,大小写不敏感 | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -h 或 --host | 连接的数据库主机的地址 | "127.0.0.1" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -t 或 --threads | 备份并发线程数 | 4 | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -r 或 --rows | 将 table 划分成 row 行数据,一般针对大表操作并发生成多个文件。当上游为 TiDB 且版本为 v3.0 或更新版本时,该参数大于 0 表示使用 TiDB region 信息划分表内并发,具体取值将不再生效。 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -L 或 --logfile | 日志输出地址,为空时会输出到控制台 | "" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --loglevel | 日志级别 {debug,info,warn,error,dpanic,panic,fatal} | "info" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --logfmt | 日志输出格式 {text,json} | "text" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -d 或 --no-data | 不导出数据,适用于只导出 schema 场景 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --no-header | 导出 csv 格式的 table 数据,不生成 header | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -W 或 --no-views | 不导出 view | true | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -m 或 --no-schemas | 不导出 schema,只导出数据 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -s 或--statement-size | 控制 `INSERT` SQL 语句的大小,单位 bytes | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -F 或 --filesize | 将 table 数据划分出来的文件大小,需指明单位(如 `128B`, `64KiB`, `32MiB`, `1.5GiB`) | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --filetype | 导出文件类型(csv/sql) | "sql" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -o 或 --output | 导出本地文件路径或[外部存储 URL](/br/backup-and-restore-storages.md) | "./export-\${time}" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -S 或 --sql | 根据指定的 sql 导出数据,该选项不支持并发导出 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --consistency | flush: dump 前用 FTWRL | "auto" | +| | snapshot: 通过 TSO 来指定 dump 某个快照时间点的 TiDB 数据 | | +| | lock: 对需要 dump 的所有表执行 `lock tables read` 命令 | | +| | none: 不加锁 dump,无法保证一致性 | | +| | auto: 对 MySQL 使用 --consistency flush;对 TiDB 使用 --consistency snapshot | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --snapshot | snapshot tso,只在 consistency=snapshot 下生效 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --where | 对备份的数据表通过 where 条件指定范围 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -p 或 --password | 连接的数据库主机的密码 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -P 或 --port | 连接的数据库主机的端口 | 4000 | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -u 或 --user | 连接的数据库主机的用户名 | "root" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --dump-empty-database | 导出空数据库的建库语句 | true | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --ca | 用于 TLS 连接的 certificate authority 文件的地址 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --cert | 用于 TLS 连接的 client certificate 文件的地址 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --key | 用于 TLS 连接的 client private key 文件的地址 | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --csv-delimiter | csv 文件中字符类型变量的定界符 | '"' | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --csv-separator | csv 文件中各值的分隔符,如果数据中可能有逗号,建议源文件导出时分隔符使用非常见组合字符 | ',' | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --csv-null-value | csv 文件空值的表示 | "\\N" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --escape-backslash | 使用反斜杠 (`\`) 来转义导出文件中的特殊字符 | true | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --output-filename-template | 以 [golang template](https://golang.org/pkg/text/template/#hdr-Arguments) 格式表示的数据文件名格式 | '{{.DB}}.{{.Table}}.{{.Index}}' | +| | 支持 `{{.DB}}`、`{{.Table}}`、`{{.Index}}` 三个参数 | | +| | 分别表示数据文件的库名、表名、分块 ID | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --status-addr | Dumpling 的服务地址,包含了 Prometheus 拉取 metrics 信息及 pprof 调试的地址 | ":8281" | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --tidb-mem-quota-query | 单条 dumpling 命令导出 SQL 语句的内存限制,单位为 byte。对于 v4.0.10 或以上版本,若不设置该参数,默认使用 TiDB 中的 `mem-quota-query` 配置项值作为内存限制值。对于 v4.0.10 以下版本,该参数值默认为 32 GB | 34359738368 | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +| --params | 为需导出的数据库连接指定 session 变量,可接受的格式: "character_set_client=latin1,character_set_connection=latin1" | | ++----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/ecosystem-tool-user-case.md b/ecosystem-tool-user-case.md index 98a6305f7203..76123bc1975d 100644 --- a/ecosystem-tool-user-case.md +++ b/ecosystem-tool-user-case.md @@ -1,46 +1,46 @@ ---- -title: TiDB 工具适用场景 -summary: 本文档介绍 TiDB 工具的常见适用场景与工具选择。 ---- - -# TiDB 工具适用场景 - -本文档从生态工具的适用场景出发,介绍部分常见场景下的生态工具选择。 - -## 在物理机或虚拟机上部署运维 TiDB - -当需要在物理机或虚拟机上部署运维 TiDB 时,你可以先安装 [TiUP](/tiup/tiup-overview.md),再通过 TiUP 管理 TiDB 的众多组件,如 TiDB、PD、TiKV 等。 - -## 在 Kubernetes 上部署运维 TiDB - -当需要在 Kubernetes 上部署运维 TiDB 时,你可以先创建 Kubernetes 集群,部署[TiDB Operator](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable),然后使用 TiDB Operator 部署运维 TiDB 集群。 - -## 从 CSV 导入数据到 TiDB - -当需要将其他工具导出的格式兼容的 CSV files 导入到 TiDB 时,可使用 [TiDB Lightning](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md)。 - -## 从 MySQL/Aurora 导入全量数据 - -当需要从 MySQL/Aurora 导入全量数据时,可先使用 [Dumpling](/dumpling-overview.md) 将数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 TiDB 集群。 - -## 从 MySQL/Aurora 迁移数据 - -当既需要从 MySQL/Aurora 导入全量数据,又需要迁移增量数据时,可使用 [TiDB Data Migration (DM)](https://docs.pingcap.com/zh/tidb-data-migration/v2.0/overview) 完成[全量数据和增量数据的迁移](https://docs.pingcap.com/zh/tidb-data-migration/v2.0/migrate-from-mysql-aurora)。 - -如果全量数据量较大(TB 级别),则可先使用 [Dumpling](/dumpling-overview.md) 与 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 完成全量数据的迁移,再使用 DM 完成增量数据的迁移。 - -## TiDB 集群备份与恢复 - -当需要对 TiDB 集群进行备份或在之后对 TiDB 集群进行恢复时,可使用 [BR](/br/backup-and-restore-tool.md)。 - -另外,BR 也可以对 TiDB 的数据进行[增量备份](/br/use-br-command-line-tool.md#增量备份)和[增量恢复](/br/use-br-command-line-tool.md#增量恢复)。 - -## 迁出数据到 TiDB - -当需要将 TiDB 集群的数据迁出到其他 TiDB 集群时,可使用 [Dumpling](/dumpling-overview.md) 从 TiDB 将全量数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 TiDB。 - -如果还需要执行增量数据的迁移,则可使用 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md)。 - -## TiDB 增量数据订阅 - -当需要订阅 TiDB 增量数据的变更时,可使用 [TiDB Binlog](/tidb-binlog/binlog-consumer-client.md)。 +--- +title: TiDB 工具适用场景 +summary: 本文档介绍 TiDB 工具的常见适用场景与工具选择。 +--- + +# TiDB 工具适用场景 + +本文档从生态工具的适用场景出发,介绍部分常见场景下的生态工具选择。 + +## 在物理机或虚拟机上部署运维 TiDB + +当需要在物理机或虚拟机上部署运维 TiDB 时,你可以先安装 [TiUP](/tiup/tiup-overview.md),再通过 TiUP 管理 TiDB 的众多组件,如 TiDB、PD、TiKV 等。 + +## 在 Kubernetes 上部署运维 TiDB + +当需要在 Kubernetes 上部署运维 TiDB 时,你可以先创建 Kubernetes 集群,部署[TiDB Operator](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable),然后使用 TiDB Operator 部署运维 TiDB 集群。 + +## 从 CSV 导入数据到 TiDB + +当需要将其他工具导出的格式兼容的 CSV files 导入到 TiDB 时,可使用 [TiDB Lightning](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md)。 + +## 从 MySQL/Aurora 导入全量数据 + +当需要从 MySQL/Aurora 导入全量数据时,可先使用 [Dumpling](/dumpling-overview.md) 将数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 TiDB 集群。 + +## 从 MySQL/Aurora 迁移数据 + +当既需要从 MySQL/Aurora 导入全量数据,又需要迁移增量数据时,可使用 [TiDB Data Migration (DM)](https://docs.pingcap.com/zh/tidb-data-migration/v2.0/overview) 完成[全量数据和增量数据的迁移](https://docs.pingcap.com/zh/tidb-data-migration/v2.0/migrate-from-mysql-aurora)。 + +如果全量数据量较大(TB 级别),则可先使用 [Dumpling](/dumpling-overview.md) 与 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 完成全量数据的迁移,再使用 DM 完成增量数据的迁移。 + +## TiDB 集群备份与恢复 + +当需要对 TiDB 集群进行备份或在之后对 TiDB 集群进行恢复时,可使用 [BR](/br/backup-and-restore-tool.md)。 + +另外,BR 也可以对 TiDB 的数据进行[增量备份](/br/use-br-command-line-tool.md#增量备份)和[增量恢复](/br/use-br-command-line-tool.md#增量恢复)。 + +## 迁出数据到 TiDB + +当需要将 TiDB 集群的数据迁出到其他 TiDB 集群时,可使用 [Dumpling](/dumpling-overview.md) 从 TiDB 将全量数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 TiDB。 + +如果还需要执行增量数据的迁移,则可使用 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md)。 + +## TiDB 增量数据订阅 + +当需要订阅 TiDB 增量数据的变更时,可使用 [TiDB Binlog](/tidb-binlog/binlog-consumer-client.md)。 diff --git a/faq/high-reliability-faq.md b/faq/high-reliability-faq.md index 79b80aee5ad8..74bf9942e768 100644 --- a/faq/high-reliability-faq.md +++ b/faq/high-reliability-faq.md @@ -1,35 +1,35 @@ ---- -title: 高可靠常见问题 -summary: 介绍高可靠相关的常见问题。 ---- - -# 高可靠常见问题 - -本文档介绍高可靠相关的常见问题。 - -## 我们的安全漏洞扫描工具对 MySQL version 有要求,TiDB 是否支持修改 server 版本号呢? - -TiDB 在 v3.0.8 后支持修改 server 版本号,可以通过配置文件中的 [`server-version`](/tidb-configuration-file.md#server-version) 配置项进行修改。在使用 TiUP 部署集群时,可以通过 `tiup cluster edit-config <cluster-name>` 修改配置文件中以下部分来设置合适的版本号: - -``` -server_configs: - tidb: - server-version: 'YOUR_VERSION_STRING' -``` - -并通过 `tiup cluster reload <cluster-name> -R tidb` 命令使得以上修改生效,以避免出现安全漏洞扫描不通过的问题。 - -## TiDB 支持哪些认证协议,过程是怎样的? - -这一层跟 MySQL 一样,走的 SASL 认证协议,用于用户登录认证,对密码的处理流程。 - -客户端连接 TiDB 的时候,走的是 challenge-response(挑战-应答)的认证模式,过程如下: - -1. 客户端连接服务器; -2. 服务器发送随机字符串 `challenge` 给客户端; -3. 客户端发送 `username` + `response` 给服务器; -4. 服务器验证 `response`。 - -## 如何修改用户名密码和权限? - -TiDB 作为分布式数据库,在 TiDB 中修改用户密码建议使用 `set password for 'root'@'%' = '0101001';` 或 `alter` 方法,不推荐使用 `update mysql.user` 的方法进行,这种方法可能会造成其它节点刷新不及时的情况。修改权限也一样,都建议采用官方的标准语法。详情可参考 [TiDB 用户账户管理](/user-account-management.md)。 +--- +title: 高可靠常见问题 +summary: 介绍高可靠相关的常见问题。 +--- + +# 高可靠常见问题 + +本文档介绍高可靠相关的常见问题。 + +## 我们的安全漏洞扫描工具对 MySQL version 有要求,TiDB 是否支持修改 server 版本号呢? + +TiDB 在 v3.0.8 后支持修改 server 版本号,可以通过配置文件中的 [`server-version`](/tidb-configuration-file.md#server-version) 配置项进行修改。在使用 TiUP 部署集群时,可以通过 `tiup cluster edit-config <cluster-name>` 修改配置文件中以下部分来设置合适的版本号: + +``` +server_configs: + tidb: + server-version: 'YOUR_VERSION_STRING' +``` + +并通过 `tiup cluster reload <cluster-name> -R tidb` 命令使得以上修改生效,以避免出现安全漏洞扫描不通过的问题。 + +## TiDB 支持哪些认证协议,过程是怎样的? + +这一层跟 MySQL 一样,走的 SASL 认证协议,用于用户登录认证,对密码的处理流程。 + +客户端连接 TiDB 的时候,走的是 challenge-response(挑战-应答)的认证模式,过程如下: + +1. 客户端连接服务器; +2. 服务器发送随机字符串 `challenge` 给客户端; +3. 客户端发送 `username` + `response` 给服务器; +4. 服务器验证 `response`。 + +## 如何修改用户名密码和权限? + +TiDB 作为分布式数据库,在 TiDB 中修改用户密码建议使用 `set password for 'root'@'%' = '0101001';` 或 `alter` 方法,不推荐使用 `update mysql.user` 的方法进行,这种方法可能会造成其它节点刷新不及时的情况。修改权限也一样,都建议采用官方的标准语法。详情可参考 [TiDB 用户账户管理](/user-account-management.md)。 diff --git a/faq/sql-faq.md b/faq/sql-faq.md index 0887e0fffd53..fcd8a6af13d1 100644 --- a/faq/sql-faq.md +++ b/faq/sql-faq.md @@ -1,287 +1,287 @@ ---- -title: SQL 操作常见问题 -summary: 介绍 SQL 操作相关的常见问题。 ---- - -# SQL 操作常见问题 - -本文档介绍 TiDB 中常见的 SQL 操作问题。 - -## TiDB 对哪些 MySQL variables 兼容? - -详细可参考[系统变量](/system-variables.md)。 - -## 省略 `ORDER BY` 条件时 TiDB 中返回结果的顺序与 MySQL 中的不一致 - -这不是 bug。返回结果的顺序视不同情况而定,不保证顺序统一。 - -MySQL 中,返回结果的顺序可能较为固定,因为查询是通过单线程执行的。但升级到新版本后,查询计划也可能变化。无论是否期待返回结果有序,都推荐使用 `ORDER BY` 条件。 - -[ISO/IEC 9075:1992, Database Language SQL- July 30, 1992](http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt) 对此有如下表述: - -> If an `<order by clause>` is not specified, then the table specified by the `<cursor specification>` is T and the ordering of rows in T is implementation-dependent.(如果未指定 `<order by 条件>`,通过 `<cursor specification>` 指定的表为 T,那么 T 表中的行顺序视执行情况而定。) - -以下两条查询的结果都是合法的: - -```sql -> select * from t; -+------+------+ -| a | b | -+------+------+ -| 1 | 1 | -| 2 | 2 | -+------+------+ -2 rows in set (0.00 sec) -``` - -```sql -> select * from t; -- 不确定返回结果的顺序 -+------+------+ -| a | b | -+------+------+ -| 2 | 2 | -| 1 | 1 | -+------+------+ -2 rows in set (0.00 sec) -``` - -如果 `ORDER BY` 中使用的列不是唯一列,该语句就不确定返回结果的顺序。以下示例中,`a` 列有重复值,因此只有 `ORDER BY a, b` 能确定返回结果的顺序。 - -```sql -> select * from t order by a; -+------+------+ -| a | b | -+------+------+ -| 1 | 1 | -| 2 | 1 | -| 2 | 2 | -+------+------+ -3 rows in set (0.00 sec) -``` - -```sql -> select * from t order by a; -- 能确定 a 列的顺序,不确定 b 列的顺序 -+------+------+ -| a | b | -+------+------+ -| 1 | 1 | -| 2 | 2 | -| 2 | 1 | -+------+------+ -3 rows in set (0.00 sec) -``` - -## TiDB 是否支持 `SELECT FOR UPDATE`? - -支持。当 TiDB 使用悲观锁(自 TiDB v3.0 起默认使用)时,TiDB 中 `SELECT FOR UPDATE` 的行为与 MySQL 中的基本一致。 - -当 TiDB 使用乐观锁时,`SELECT FOR UPDATE` 不会在事务启动时对数据加锁,而是在提交事务时检查冲突。如果检查出冲突,会回滚待提交的事务。 - -## TiDB 的 codec 能保证 UTF8 的字符串是 memcomparable 的吗?我们的 key 需要支持 UTF8,有什么编码建议吗? - -TiDB 字符集默认就是 UTF8 而且目前只支持 UTF8,字符串就是 memcomparable 格式的。 - -## 一个事务中的语句数量最大是多少? - -一个事务中的语句数量,默认限制最大为 5000 条。 - -## TiDB 中,为什么出现后插入数据的自增 ID 反而小? - -TiDB 的自增 ID (`AUTO_INCREMENT`) 只保证自增且唯一,并不保证连续分配。TiDB 目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续。当多个线程并发往不同的 TiDB-server 插入数据的时候,有可能会出现后插入的数据自增 ID 小的情况。此外,TiDB 允许给整型类型的字段指定 AUTO_INCREMENT,且一个表只允许一个属性为 `AUTO_INCREMENT` 的字段。详情可参考 [CREATE TABLE 语法](/mysql-compatibility.md#自增-id)。 - -## 如何在 TiDB 中修改 `sql_mode`? - -TiDB 支持在会话或全局作用域上修改 [`sql_mode`](/system-variables.md#sql_mode) 系统变量。对全局作用域变量的更改将作用于集群中的其它服务器,并且重启后更改依然有效。因此,你无需在每台 TiDB 服务器上都更改 `sql_mode` 的值。 - -## 用 Sqoop 批量写入 TiDB 数据,虽然配置了 `--batch` 选项,但还是会遇到 `java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation` 的错误,该如何解决? - -- 在 Sqoop 中,`--batch` 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 `-Dsqoop.export.records.per.statement=10` 来解决这个问题,完整的用法如下: - - {{< copyable "shell-regular" >}} - - ```bash - sqoop export \ - -Dsqoop.export.records.per.statement=10 \ - --connect jdbc:mysql://mysql.example.com/sqoop \ - --username sqoop ${user} \ - --password ${passwd} \ - --table ${tab_name} \ - --export-dir ${dir} \ - --batch - ``` - -- 也可以选择增大 TiDB 的单个事物语句数量限制,不过此操作会导致内存增加。 - -## TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么? - -有,也支持 DDL。详细参考 [TiDB 历史数据回溯](/read-historical-data.md)。 - -## TiDB 中删除数据后会立即释放空间吗? - -DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作,TiDB 的 GC 机制会删除数据,但不会立即释放空间,而是等到后续进行 compaction 时释放空间。 - -## TiDB 是否支持 `REPLACE INTO` 语法? - -支持,例外是当前 `LOAD DATA` 不支持 `REPLACE INTO` 语法。 - -## 数据删除后查询速度为何会变慢? - -大量删除数据后,会有很多无用的 key 存在,影响查询效率。可以尝试开启 [Region Merge](/best-practices/massive-regions-best-practices.md#方法五开启-region-merge) 功能,具体看参考[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)中的删除数据部分。 - -## 对数据做删除操作之后,空间回收比较慢,如何处理? - -TiDB 采用了多版本并发控制 (MVCC),为了使并发事务能查看到早期版本的数据,删除数据不会立即回收空间,而是推迟一段时间后再进行垃圾回收 (GC)。你可以通过修改系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入)的值(默认值为 `10m0s`)配置历史数据的保留时限。 - -## `SHOW PROCESSLIST` 是否显示系统进程号? - -TiDB 的 `SHOW PROCESSLIST` 与 MySQL 的 `SHOW PROCESSLIST` 显示内容基本一样,不会显示系统进程号,而 ID 表示当前的 session ID。其中 TiDB 的 `show processlist` 和 MySQL 的 `show processlist` 区别如下: - -+ 由于 TiDB 是分布式数据库,TiDB server 实例是无状态的 SQL 解析和执行引擎(详情可参考 [TiDB 整体架构](/tidb-architecture.md)),用户使用 MySQL 客户端登录的是哪个 TiDB server ,`show processlist` 就会显示当前连接的这个 TiDB server 中执行的 session 列表,不是整个集群中运行的全部 session 列表;而 MySQL 是单机数据库,`show processlist` 列出的是当前整个 MySQL 数据库的全部执行 SQL 列表。 - -+ 在查询执行期间,TiDB 中的 `State` 列不会持续更新。由于 TiDB 支持并行查询,每个语句可能同时处于多个状态,因此很难显示为某一种状态。 - -## 在 TiDB 中如何控制或改变 SQL 提交的执行优先级? - -TiDB 支持改变 [per-session](/system-variables.md#tidb_force_priority)、[全局](/tidb-configuration-file.md#force-priority)或单个语句的优先级。优先级包括: - -- HIGH_PRIORITY:该语句为高优先级语句,TiDB 在执行阶段会优先处理这条语句 -- LOW_PRIORITY:该语句为低优先级语句,TiDB 在执行阶段会降低这条语句的优先级 - -以上两种参数可以结合 TiDB 的 DML 语言进行使用,使用方法举例如下: - -1. 通过在数据库中写 SQL 的方式来调整优先级: - - {{< copyable "sql" >}} - - ```sql - select HIGH_PRIORITY | LOW_PRIORITY count(*) from table_name; - insert HIGH_PRIORITY | LOW_PRIORITY into table_name insert_values; - delete HIGH_PRIORITY | LOW_PRIORITY from table_name; - update HIGH_PRIORITY | LOW_PRIORITY table_reference set assignment_list where where_condition; - replace HIGH_PRIORITY | LOW_PRIORITY into table_name; - ``` - -2. 全表扫会自动调整为低优先级,analyze 也是默认低优先级。 - -## 在 TiDB 中 auto analyze 的触发策略是怎样的? - -触发策略:新表达到 1000 条,并且在 1 分钟内没有写入,会自动触发。 - -当表的(修改数/当前总行数)大于 `tidb_auto_analyze_ratio` 的时候,会自动触发 `analyze` 语句。`tidb_auto_analyze_ratio` 的默认值为 0.5,即默认开启此功能。为了保险起见,在开启此功能的时候,保证了其最小值为 0.3。但是不能大于等于 `pseudo-estimate-ratio`(默认值为 0.8),否则会有一段时间使用 pseudo 统计信息,建议设置值为 0.5。 - -## 可以使用 Hints 控制优化器行为吗? - -在 TiDB 中,你可以用多种方法控制查询优化器的默认行为,包括使用 [Optimizer Hints](/optimizer-hints.md) 和 [SQL 执行计划管理 (SPM)](/sql-plan-management.md)。基本用法同 MySQL 中的一致,还包含若干 TiDB 特有的用法,示例如下:`select column_name from table_name use index(index_name)where where_condition;` - -## 触发 Information schema is changed 错误的原因? - -TiDB 在执行 SQL 语句时,会使用当时的 `schema` 来处理该 SQL 语句,而且 TiDB 支持在线异步变更 DDL。那么,在执行 DML 的时候可能有 DDL 语句也在执行,而你需要确保每个 SQL 语句在同一个 `schema` 上执行。所以当执行 DML 时,遇到正在执行中的 DDL 操作就可能会报 `Information schema is changed` 的错误。为了避免太多的 DML 语句报错,已做了一些优化。 - -现在会报此错的可能原因如下(只有第一个报错原因与表有关): - -- 执行的 DML 语句中涉及的表和集群中正在执行的 DDL 的表有相同的,那么这个 DML 语句就会报此错。 -- 这个 DML 执行时间很久,而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 1024 (此为默认值,可以通过 `tidb_max_delta_schema_count` 变量修改)。 -- 接受 DML 请求的 TiDB 长时间不能加载到 `schema information`(TiDB 与 PD 或 TiKV 之间的网络连接故障等会导致此问题),而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 100。 -- TiDB 重启后执行第一个 DDL 操作前,执行 DML 操作,并且在执行过程中遇到了第 1 个 DDL 操作(即在执行第 1 个 DDL 操作前,启动该 DML 对应的事务,且在该 DDL 变更第一个 `schema` 版本后,提交该 DML 对应的事务),那么这个 DML 会报此错。 - -> **注意:** -> -> + 目前 TiDB 未缓存所有的 `schema` 版本信息。 -> + 对于每个 DDL 操作,`schema` 版本变更的数量与对应 `schema state` 变更的次数一致。 -> + 不同的 DDL 操作版本变更次数不一样。例如,`create table` 操作会有 1 次 `schema` 版本变更;`add column` 操作有 4 次 `schema` 版本变更。 - -## 触发 Information schema is out of date 错误的原因? - -当执行 DML 时,TiDB 超过一个 DDL lease 时间(默认 45s)没能加载到最新的 schema 就可能会报 `Information schema is out of date` 的错误。遇到此错的可能原因如下: - -- 执行此 DML 的 TiDB 被 kill 后准备退出,且此 DML 对应的事务执行时间超过一个 DDL lease,在事务提交时会报这个错误。 -- TiDB 在执行此 DML 时,有一段时间内连不上 PD 或者 TiKV,导致 TiDB 超过一个 DDL lease 时间没有 load schema,或者导致 TiDB 断开与 PD 之间带 keep alive 设置的连接。 - -## 高并发情况下执行 DDL 时报错的原因? - -高并发情况下执行 DDL(比如批量建表)时,极少部分 DDL 可能会由于并发执行时 key 冲突而执行失败。 - -并发执行 DDL 时,建议将 DDL 数量保持在 20 以下,否则你需要在应用端重试失败的 DDL 语句。 - -## SQL 优化 - -### TiDB 执行计划解读 - -详细解读[理解 TiDB 执行计划](/explain-overview.md)。 - -### 统计信息收集 - -详细解读[统计信息](/statistics.md)。 - -### Count 如何加速? - -Count 就是暴力扫表,提高并发度能显著的提升速度,修改并发度可以参考 `tidb_distsql_scan_concurrency` 变量,但是也要看 CPU 和 I/O 资源。TiDB 每次查询都要访问 TiKV,在数据量小的情况下,MySQL 都在内存里,TiDB 还需要进行一次网络访问。 - -提升建议: - -- 建议提升硬件配置,可以参考[部署建议](/hardware-and-software-requirements.md)。 -- 提升并发度,默认是 10,可以提升到 50 试试,但是一般提升在 2-4 倍之间。 -- 测试大数据量的 count。 -- 调优 TiKV 配置,可以参考[性能调优](/tune-tikv-memory-performance.md)。 -- 可以参考[下推计算结果缓存](/coprocessor-cache.md)。 - -### 查看当前 DDL 的进度? - -通过 `admin show ddl` 查看当前 job 进度。操作如下: - -{{< copyable "sql" >}} - -```sql -admin show ddl; -``` - -```sql -*************************** 1. row *************************** - SCHEMA_VER: 140 - OWNER: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc -RUNNING_JOBS: ID:121, Type:add index, State:running, SchemaState:write reorganization, SchemaID:1, TableID:118, RowCount:77312, ArgLen:0, start time: 2018-12-05 16:26:10.652 +0800 CST, Err:<nil>, ErrCount:0, SnapshotVersion:404749908941733890 - SELF_ID: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc -``` - -从上面操作结果可知,当前正在处理的是 `add index` 操作。且从 `RUNNING_JOBS` 列的 `RowCount` 字段可以知道当前 `add index` 操作已经添加了 77312 行索引。 - -### 如何查看 DDL job? - -可以使用 `admin show ddl` 语句查看正在运行的 DDL 作业。 - -- `admin show ddl jobs`:用于查看当前 DDL 作业队列中的所有结果(包括正在运行以及等待运行的任务)以及已执行完成的 DDL 作业队列中的最近十条结果。 -- `admin show ddl job queries 'job_id' [, 'job_id'] ...`:用于显示 `job_id` 对应的 DDL 任务的原始 SQL 语句。此 `job_id` 只搜索正在执行中的任务以及 DDL 历史作业队列中的最近十条结果。 - -### TiDB 是否支持基于 COST 的优化 (CBO),如果支持,实现到什么程度? - -是的,TiDB 使用的是基于成本的优化器 (CBO),会对代价模型、统计信息持续优化。除此之外,TiDB 还支持 hash join、soft-merge join 等 join 算法。 - -### 如何确定某张表是否需要做 analyze ? - -可以通过 `show stats_healthy` 来查看 Healthy 字段,一般小于等于 60 的表需要做 analyze。 - -### SQL 的执行计划展开成了树,ID 的序号有什么规律吗?这棵树的执行顺序会是怎么样的? - -ID 没什么规律,只要是唯一就行。不过生成的时候,是有一个计数器,生成一个 plan 就加一,执行的顺序和序号无关。整个执行计划是一颗树,执行时从根节点开始,不断地向上返回数据。执行计划的理解,请参考[理解 TiDB 执行计划](/explain-overview.md)。 - -### TiDB 执行计划中,task cop 在一个 root 下,这个是并行的么? - -目前 TiDB 的计算任务隶属于两种不同的 task:cop task 和 root task。cop task 是指被下推到 KV 端分布式执行的计算任务,root task 是指在 TiDB 端单点执行的计算任务。 - -一般来讲 root task 的输入数据是来自于 cop task 的,但是 root task 在处理数据的时候,TiKV 上的 cop task 也可以同时处理数据,等待 TiDB 的 root task 拉取。所以从上述观点来看,他们是并行的,同时存在数据上下游关系。 - -在执行的过程中,某些时间段其实也是并行的,第一个 cop task 在处理 [100, 200] 的数据,第二个 cop task 在处理 [1, 100] 的数据。执行计划的理解,请参考[理解 TiDB 执行计划](/explain-overview.md)。 - -## 数据库优化 - -### TiDB 参数及调整 - -详情参考 [TiDB 配置参数](/command-line-flags-for-tidb-configuration.md)。 - -### 如何打散热点 - -TiDB 中以 Region 分片来管理数据库,通常来讲,TiDB 的热点指的是 Region 的读写访问热点。而 TiDB 中对于非整数主键或没有主键的表,可以通过设置 `SHARD_ROW_ID_BITS` 来适度分解 Region 分片,以达到打散 Region 热点的效果。详情可参考官网 [SHARD_ROW_ID_BITS](/shard-row-id-bits.md) 中的介绍。 - -### TiKV 性能参数调优 - -详情参考 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 +--- +title: SQL 操作常见问题 +summary: 介绍 SQL 操作相关的常见问题。 +--- + +# SQL 操作常见问题 + +本文档介绍 TiDB 中常见的 SQL 操作问题。 + +## TiDB 对哪些 MySQL variables 兼容? + +详细可参考[系统变量](/system-variables.md)。 + +## 省略 `ORDER BY` 条件时 TiDB 中返回结果的顺序与 MySQL 中的不一致 + +这不是 bug。返回结果的顺序视不同情况而定,不保证顺序统一。 + +MySQL 中,返回结果的顺序可能较为固定,因为查询是通过单线程执行的。但升级到新版本后,查询计划也可能变化。无论是否期待返回结果有序,都推荐使用 `ORDER BY` 条件。 + +[ISO/IEC 9075:1992, Database Language SQL- July 30, 1992](http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt) 对此有如下表述: + +> If an `<order by clause>` is not specified, then the table specified by the `<cursor specification>` is T and the ordering of rows in T is implementation-dependent.(如果未指定 `<order by 条件>`,通过 `<cursor specification>` 指定的表为 T,那么 T 表中的行顺序视执行情况而定。) + +以下两条查询的结果都是合法的: + +```sql +> select * from t; ++------+------+ +| a | b | ++------+------+ +| 1 | 1 | +| 2 | 2 | ++------+------+ +2 rows in set (0.00 sec) +``` + +```sql +> select * from t; -- 不确定返回结果的顺序 ++------+------+ +| a | b | ++------+------+ +| 2 | 2 | +| 1 | 1 | ++------+------+ +2 rows in set (0.00 sec) +``` + +如果 `ORDER BY` 中使用的列不是唯一列,该语句就不确定返回结果的顺序。以下示例中,`a` 列有重复值,因此只有 `ORDER BY a, b` 能确定返回结果的顺序。 + +```sql +> select * from t order by a; ++------+------+ +| a | b | ++------+------+ +| 1 | 1 | +| 2 | 1 | +| 2 | 2 | ++------+------+ +3 rows in set (0.00 sec) +``` + +```sql +> select * from t order by a; -- 能确定 a 列的顺序,不确定 b 列的顺序 ++------+------+ +| a | b | ++------+------+ +| 1 | 1 | +| 2 | 2 | +| 2 | 1 | ++------+------+ +3 rows in set (0.00 sec) +``` + +## TiDB 是否支持 `SELECT FOR UPDATE`? + +支持。当 TiDB 使用悲观锁(自 TiDB v3.0 起默认使用)时,TiDB 中 `SELECT FOR UPDATE` 的行为与 MySQL 中的基本一致。 + +当 TiDB 使用乐观锁时,`SELECT FOR UPDATE` 不会在事务启动时对数据加锁,而是在提交事务时检查冲突。如果检查出冲突,会回滚待提交的事务。 + +## TiDB 的 codec 能保证 UTF8 的字符串是 memcomparable 的吗?我们的 key 需要支持 UTF8,有什么编码建议吗? + +TiDB 字符集默认就是 UTF8 而且目前只支持 UTF8,字符串就是 memcomparable 格式的。 + +## 一个事务中的语句数量最大是多少? + +一个事务中的语句数量,默认限制最大为 5000 条。 + +## TiDB 中,为什么出现后插入数据的自增 ID 反而小? + +TiDB 的自增 ID (`AUTO_INCREMENT`) 只保证自增且唯一,并不保证连续分配。TiDB 目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续。当多个线程并发往不同的 TiDB-server 插入数据的时候,有可能会出现后插入的数据自增 ID 小的情况。此外,TiDB 允许给整型类型的字段指定 AUTO_INCREMENT,且一个表只允许一个属性为 `AUTO_INCREMENT` 的字段。详情可参考 [CREATE TABLE 语法](/mysql-compatibility.md#自增-id)。 + +## 如何在 TiDB 中修改 `sql_mode`? + +TiDB 支持在会话或全局作用域上修改 [`sql_mode`](/system-variables.md#sql_mode) 系统变量。对全局作用域变量的更改将作用于集群中的其它服务器,并且重启后更改依然有效。因此,你无需在每台 TiDB 服务器上都更改 `sql_mode` 的值。 + +## 用 Sqoop 批量写入 TiDB 数据,虽然配置了 `--batch` 选项,但还是会遇到 `java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation` 的错误,该如何解决? + +- 在 Sqoop 中,`--batch` 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 `-Dsqoop.export.records.per.statement=10` 来解决这个问题,完整的用法如下: + + {{< copyable "shell-regular" >}} + + ```bash + sqoop export \ + -Dsqoop.export.records.per.statement=10 \ + --connect jdbc:mysql://mysql.example.com/sqoop \ + --username sqoop ${user} \ + --password ${passwd} \ + --table ${tab_name} \ + --export-dir ${dir} \ + --batch + ``` + +- 也可以选择增大 TiDB 的单个事物语句数量限制,不过此操作会导致内存增加。 + +## TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么? + +有,也支持 DDL。详细参考 [TiDB 历史数据回溯](/read-historical-data.md)。 + +## TiDB 中删除数据后会立即释放空间吗? + +DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作,TiDB 的 GC 机制会删除数据,但不会立即释放空间,而是等到后续进行 compaction 时释放空间。 + +## TiDB 是否支持 `REPLACE INTO` 语法? + +支持,例外是当前 `LOAD DATA` 不支持 `REPLACE INTO` 语法。 + +## 数据删除后查询速度为何会变慢? + +大量删除数据后,会有很多无用的 key 存在,影响查询效率。可以尝试开启 [Region Merge](/best-practices/massive-regions-best-practices.md#方法五开启-region-merge) 功能,具体看参考[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)中的删除数据部分。 + +## 对数据做删除操作之后,空间回收比较慢,如何处理? + +TiDB 采用了多版本并发控制 (MVCC),为了使并发事务能查看到早期版本的数据,删除数据不会立即回收空间,而是推迟一段时间后再进行垃圾回收 (GC)。你可以通过修改系统变量 [`tidb_gc_life_time`](/system-variables.md#tidb_gc_life_time-从-v50-版本开始引入)的值(默认值为 `10m0s`)配置历史数据的保留时限。 + +## `SHOW PROCESSLIST` 是否显示系统进程号? + +TiDB 的 `SHOW PROCESSLIST` 与 MySQL 的 `SHOW PROCESSLIST` 显示内容基本一样,不会显示系统进程号,而 ID 表示当前的 session ID。其中 TiDB 的 `show processlist` 和 MySQL 的 `show processlist` 区别如下: + ++ 由于 TiDB 是分布式数据库,TiDB server 实例是无状态的 SQL 解析和执行引擎(详情可参考 [TiDB 整体架构](/tidb-architecture.md)),用户使用 MySQL 客户端登录的是哪个 TiDB server ,`show processlist` 就会显示当前连接的这个 TiDB server 中执行的 session 列表,不是整个集群中运行的全部 session 列表;而 MySQL 是单机数据库,`show processlist` 列出的是当前整个 MySQL 数据库的全部执行 SQL 列表。 + ++ 在查询执行期间,TiDB 中的 `State` 列不会持续更新。由于 TiDB 支持并行查询,每个语句可能同时处于多个状态,因此很难显示为某一种状态。 + +## 在 TiDB 中如何控制或改变 SQL 提交的执行优先级? + +TiDB 支持改变 [per-session](/system-variables.md#tidb_force_priority)、[全局](/tidb-configuration-file.md#force-priority)或单个语句的优先级。优先级包括: + +- HIGH_PRIORITY:该语句为高优先级语句,TiDB 在执行阶段会优先处理这条语句 +- LOW_PRIORITY:该语句为低优先级语句,TiDB 在执行阶段会降低这条语句的优先级 + +以上两种参数可以结合 TiDB 的 DML 语言进行使用,使用方法举例如下: + +1. 通过在数据库中写 SQL 的方式来调整优先级: + + {{< copyable "sql" >}} + + ```sql + select HIGH_PRIORITY | LOW_PRIORITY count(*) from table_name; + insert HIGH_PRIORITY | LOW_PRIORITY into table_name insert_values; + delete HIGH_PRIORITY | LOW_PRIORITY from table_name; + update HIGH_PRIORITY | LOW_PRIORITY table_reference set assignment_list where where_condition; + replace HIGH_PRIORITY | LOW_PRIORITY into table_name; + ``` + +2. 全表扫会自动调整为低优先级,analyze 也是默认低优先级。 + +## 在 TiDB 中 auto analyze 的触发策略是怎样的? + +触发策略:新表达到 1000 条,并且在 1 分钟内没有写入,会自动触发。 + +当表的(修改数/当前总行数)大于 `tidb_auto_analyze_ratio` 的时候,会自动触发 `analyze` 语句。`tidb_auto_analyze_ratio` 的默认值为 0.5,即默认开启此功能。为了保险起见,在开启此功能的时候,保证了其最小值为 0.3。但是不能大于等于 `pseudo-estimate-ratio`(默认值为 0.8),否则会有一段时间使用 pseudo 统计信息,建议设置值为 0.5。 + +## 可以使用 Hints 控制优化器行为吗? + +在 TiDB 中,你可以用多种方法控制查询优化器的默认行为,包括使用 [Optimizer Hints](/optimizer-hints.md) 和 [SQL 执行计划管理 (SPM)](/sql-plan-management.md)。基本用法同 MySQL 中的一致,还包含若干 TiDB 特有的用法,示例如下:`select column_name from table_name use index(index_name)where where_condition;` + +## 触发 Information schema is changed 错误的原因? + +TiDB 在执行 SQL 语句时,会使用当时的 `schema` 来处理该 SQL 语句,而且 TiDB 支持在线异步变更 DDL。那么,在执行 DML 的时候可能有 DDL 语句也在执行,而你需要确保每个 SQL 语句在同一个 `schema` 上执行。所以当执行 DML 时,遇到正在执行中的 DDL 操作就可能会报 `Information schema is changed` 的错误。为了避免太多的 DML 语句报错,已做了一些优化。 + +现在会报此错的可能原因如下(只有第一个报错原因与表有关): + +- 执行的 DML 语句中涉及的表和集群中正在执行的 DDL 的表有相同的,那么这个 DML 语句就会报此错。 +- 这个 DML 执行时间很久,而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 1024 (此为默认值,可以通过 `tidb_max_delta_schema_count` 变量修改)。 +- 接受 DML 请求的 TiDB 长时间不能加载到 `schema information`(TiDB 与 PD 或 TiKV 之间的网络连接故障等会导致此问题),而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 100。 +- TiDB 重启后执行第一个 DDL 操作前,执行 DML 操作,并且在执行过程中遇到了第 1 个 DDL 操作(即在执行第 1 个 DDL 操作前,启动该 DML 对应的事务,且在该 DDL 变更第一个 `schema` 版本后,提交该 DML 对应的事务),那么这个 DML 会报此错。 + +> **注意:** +> +> + 目前 TiDB 未缓存所有的 `schema` 版本信息。 +> + 对于每个 DDL 操作,`schema` 版本变更的数量与对应 `schema state` 变更的次数一致。 +> + 不同的 DDL 操作版本变更次数不一样。例如,`create table` 操作会有 1 次 `schema` 版本变更;`add column` 操作有 4 次 `schema` 版本变更。 + +## 触发 Information schema is out of date 错误的原因? + +当执行 DML 时,TiDB 超过一个 DDL lease 时间(默认 45s)没能加载到最新的 schema 就可能会报 `Information schema is out of date` 的错误。遇到此错的可能原因如下: + +- 执行此 DML 的 TiDB 被 kill 后准备退出,且此 DML 对应的事务执行时间超过一个 DDL lease,在事务提交时会报这个错误。 +- TiDB 在执行此 DML 时,有一段时间内连不上 PD 或者 TiKV,导致 TiDB 超过一个 DDL lease 时间没有 load schema,或者导致 TiDB 断开与 PD 之间带 keep alive 设置的连接。 + +## 高并发情况下执行 DDL 时报错的原因? + +高并发情况下执行 DDL(比如批量建表)时,极少部分 DDL 可能会由于并发执行时 key 冲突而执行失败。 + +并发执行 DDL 时,建议将 DDL 数量保持在 20 以下,否则你需要在应用端重试失败的 DDL 语句。 + +## SQL 优化 + +### TiDB 执行计划解读 + +详细解读[理解 TiDB 执行计划](/explain-overview.md)。 + +### 统计信息收集 + +详细解读[统计信息](/statistics.md)。 + +### Count 如何加速? + +Count 就是暴力扫表,提高并发度能显著的提升速度,修改并发度可以参考 `tidb_distsql_scan_concurrency` 变量,但是也要看 CPU 和 I/O 资源。TiDB 每次查询都要访问 TiKV,在数据量小的情况下,MySQL 都在内存里,TiDB 还需要进行一次网络访问。 + +提升建议: + +- 建议提升硬件配置,可以参考[部署建议](/hardware-and-software-requirements.md)。 +- 提升并发度,默认是 10,可以提升到 50 试试,但是一般提升在 2-4 倍之间。 +- 测试大数据量的 count。 +- 调优 TiKV 配置,可以参考[性能调优](/tune-tikv-memory-performance.md)。 +- 可以参考[下推计算结果缓存](/coprocessor-cache.md)。 + +### 查看当前 DDL 的进度? + +通过 `admin show ddl` 查看当前 job 进度。操作如下: + +{{< copyable "sql" >}} + +```sql +admin show ddl; +``` + +```sql +*************************** 1. row *************************** + SCHEMA_VER: 140 + OWNER: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc +RUNNING_JOBS: ID:121, Type:add index, State:running, SchemaState:write reorganization, SchemaID:1, TableID:118, RowCount:77312, ArgLen:0, start time: 2018-12-05 16:26:10.652 +0800 CST, Err:<nil>, ErrCount:0, SnapshotVersion:404749908941733890 + SELF_ID: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc +``` + +从上面操作结果可知,当前正在处理的是 `add index` 操作。且从 `RUNNING_JOBS` 列的 `RowCount` 字段可以知道当前 `add index` 操作已经添加了 77312 行索引。 + +### 如何查看 DDL job? + +可以使用 `admin show ddl` 语句查看正在运行的 DDL 作业。 + +- `admin show ddl jobs`:用于查看当前 DDL 作业队列中的所有结果(包括正在运行以及等待运行的任务)以及已执行完成的 DDL 作业队列中的最近十条结果。 +- `admin show ddl job queries 'job_id' [, 'job_id'] ...`:用于显示 `job_id` 对应的 DDL 任务的原始 SQL 语句。此 `job_id` 只搜索正在执行中的任务以及 DDL 历史作业队列中的最近十条结果。 + +### TiDB 是否支持基于 COST 的优化 (CBO),如果支持,实现到什么程度? + +是的,TiDB 使用的是基于成本的优化器 (CBO),会对代价模型、统计信息持续优化。除此之外,TiDB 还支持 hash join、soft-merge join 等 join 算法。 + +### 如何确定某张表是否需要做 analyze ? + +可以通过 `show stats_healthy` 来查看 Healthy 字段,一般小于等于 60 的表需要做 analyze。 + +### SQL 的执行计划展开成了树,ID 的序号有什么规律吗?这棵树的执行顺序会是怎么样的? + +ID 没什么规律,只要是唯一就行。不过生成的时候,是有一个计数器,生成一个 plan 就加一,执行的顺序和序号无关。整个执行计划是一颗树,执行时从根节点开始,不断地向上返回数据。执行计划的理解,请参考[理解 TiDB 执行计划](/explain-overview.md)。 + +### TiDB 执行计划中,task cop 在一个 root 下,这个是并行的么? + +目前 TiDB 的计算任务隶属于两种不同的 task:cop task 和 root task。cop task 是指被下推到 KV 端分布式执行的计算任务,root task 是指在 TiDB 端单点执行的计算任务。 + +一般来讲 root task 的输入数据是来自于 cop task 的,但是 root task 在处理数据的时候,TiKV 上的 cop task 也可以同时处理数据,等待 TiDB 的 root task 拉取。所以从上述观点来看,他们是并行的,同时存在数据上下游关系。 + +在执行的过程中,某些时间段其实也是并行的,第一个 cop task 在处理 [100, 200] 的数据,第二个 cop task 在处理 [1, 100] 的数据。执行计划的理解,请参考[理解 TiDB 执行计划](/explain-overview.md)。 + +## 数据库优化 + +### TiDB 参数及调整 + +详情参考 [TiDB 配置参数](/command-line-flags-for-tidb-configuration.md)。 + +### 如何打散热点 + +TiDB 中以 Region 分片来管理数据库,通常来讲,TiDB 的热点指的是 Region 的读写访问热点。而 TiDB 中对于非整数主键或没有主键的表,可以通过设置 `SHARD_ROW_ID_BITS` 来适度分解 Region 分片,以达到打散 Region 热点的效果。详情可参考官网 [SHARD_ROW_ID_BITS](/shard-row-id-bits.md) 中的介绍。 + +### TiKV 性能参数调优 + +详情参考 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 diff --git a/functions-and-operators/expressions-pushed-down.md b/functions-and-operators/expressions-pushed-down.md index ac926068f72c..8919a034ab35 100644 --- a/functions-and-operators/expressions-pushed-down.md +++ b/functions-and-operators/expressions-pushed-down.md @@ -9,14 +9,29 @@ summary: TiDB 中下推到 TiKV 的表达式列表及相关设置。 ## 已支持下推的表达式列表 -| 表达式分类 | 具体操作 | -| :-------------- | :------------------------------------- | -| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | -| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | <, <=, =, != (`<>`), >, >=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | -| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, *, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | -| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_ifnull) | -| [JSON运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)][json_type],<br/> [JSON_EXTRACT(json_doc, path[, path] ...)][json_extract],<br/> [JSON_OBJECT(key, val[, key, val] ...)][json_object],<br/> [JSON_ARRAY([val[, val] ...])][json_array],<br/> [JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge],<br/> [JSON_SET(json_doc, path, val[, path, val] ...)][json_set],<br/> [JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert],<br/> [JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace],<br/> [JSON_REMOVE(json_doc, path[, path] ...)][json_remove] | -| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 表达式分类 | 具体操作 | ++:========================================================================+:==============================================================================================================================================================================================================================================================================================================================================================================================================+ +| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | \<, \<=, =, != (`<>`), \>, \>=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, \*, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#function_ifnull) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [JSON运算](/functions-and-operators/json-functions.md) | \[JSON_TYPE(json_val)\]\[json_type\], | +| | \[JSON_EXTRACT(json_doc, path\[, path\] ...)\]\[json_extract\], | +| | \[JSON_OBJECT(key, val\[, key, val\] ...)\]\[json_object\], | +| | \[JSON_ARRAY(\[val\[, val\] ...\])\]\[json_array\], | +| | \[JSON_MERGE(json_doc, json_doc\[, json_doc\] ...)\]\[json_merge\], | +| | \[JSON_SET(json_doc, path, val\[, path, val\] ...)\]\[json_set\], | +| | \[JSON_INSERT(json_doc, path, val\[, path, val\] ...)\]\[json_insert\], | +| | \[JSON_REPLACE(json_doc, path, val\[, path, val\] ...)\]\[json_replace\], | +| | \[JSON_REMOVE(json_doc, path\[, path\] ...)\]\[json_remove\] | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | ++-------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ## 禁止特定表达式下推 diff --git a/geo-distributed-deployment-topology.md b/geo-distributed-deployment-topology.md index 8f966a37bfc7..10e76b7b2554 100644 --- a/geo-distributed-deployment-topology.md +++ b/geo-distributed-deployment-topology.md @@ -9,12 +9,27 @@ summary: 介绍跨数据中心部署 TiDB 集群的拓扑结构。 ## 拓扑信息 -|实例 | 个数 | 物理机配置 | BJ IP | SH IP |配置 | -| :-- | :-- | :-- | :-- | :-- | :-- | -| TiDB |5 | 16 VCore 32GB * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 <br/> 10.0.1.4 | 10.0.1.5 | 默认端口 <br/> 全局目录配置 | -| PD | 5 | 4 VCore 8GB * 1 |10.0.1.6 <br/> 10.0.1.7 <br/> 10.0.1.8 <br/> 10.0.1.9 | 10.0.1.10 | 默认端口 <br/> 全局目录配置 | -| TiKV | 5 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.11 <br/> 10.0.1.12 <br/> 10.0.1.13 <br/> 10.0.1.14 | 10.0.1.15 | 默认端口 <br/> 全局目录配置 | -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.16 || 默认端口 <br/> 全局目录配置 | ++----------------------+-----------+-----------------------------------+-----------+-----------+--------------+ +| 实例 | 个数 | 物理机配置 | BJ IP | SH IP | 配置 | ++:=====================+:==========+:==================================+:==========+:==========+:=============+ +| TiDB | 5 | 16 VCore 32GB \* 1 | 10.0.1.1 | 10.0.1.5 | 默认端口 | +| | | | 10.0.1.2 | | 全局目录配置 | +| | | | 10.0.1.3 | | | +| | | | 10.0.1.4 | | | ++----------------------+-----------+-----------------------------------+-----------+-----------+--------------+ +| PD | 5 | 4 VCore 8GB \* 1 | 10.0.1.6 | 10.0.1.10 | 默认端口 | +| | | | 10.0.1.7 | | 全局目录配置 | +| | | | 10.0.1.8 | | | +| | | | 10.0.1.9 | | | ++----------------------+-----------+-----------------------------------+-----------+-----------+--------------+ +| TiKV | 5 | 16 VCore 32GB 2TB (nvme ssd) \* 1 | 10.0.1.11 | 10.0.1.15 | 默认端口 | +| | | | 10.0.1.12 | | 全局目录配置 | +| | | | 10.0.1.13 | | | +| | | | 10.0.1.14 | | | ++----------------------+-----------+-----------------------------------+-----------+-----------+--------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.16 | | 默认端口 | +| | | | | | 全局目录配置 | ++----------------------+-----------+-----------------------------------+-----------+-----------+--------------+ ### 拓扑模版 diff --git a/hybrid-deployment-topology.md b/hybrid-deployment-topology.md index 1d5eb63d5130..f3a361339beb 100644 --- a/hybrid-deployment-topology.md +++ b/hybrid-deployment-topology.md @@ -9,12 +9,24 @@ summary: 介绍混合部署 TiDB 集群的拓扑结构。 ## 拓扑信息 -| 实例 | 个数 | 物理机配置 | IP | 配置 | -| :-- | :-- | :-- | :-- | :-- | -| TiDB | 6 | 32 VCore 64GB | 10.0.1.1<br/> 10.0.1.2<br/> 10.0.1.3 | 配置 numa 绑核操作 | -| PD | 3 | 16 VCore 32 GB | 10.0.1.4<br/> 10.0.1.5<br/> 10.0.1.6 | 配置 location_labels 参数 | -| TiKV | 6 | 32 VCore 64GB | 10.0.1.7<br/> 10.0.1.8<br/> 10.0.1.9 | 1. 区分实例级别的 port、status_port;<br/> 2. 配置全局参数 readpool、storage 以及 raftstore;<br/> 3. 配置实例级别 host 维度的 labels;<br/> 4. 配置 numa 绑核操作| -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.10 | 默认配置 | ++----------------------+-------------+------------------------------+-------------+----------------------------------------------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:=====================+:============+:=============================+:============+:===================================================+ +| TiDB | 6 | 32 VCore 64GB | 10.0.1.1 | 配置 numa 绑核操作 | +| | | | 10.0.1.2 | | +| | | | 10.0.1.3 | | ++----------------------+-------------+------------------------------+-------------+----------------------------------------------------+ +| PD | 3 | 16 VCore 32 GB | 10.0.1.4 | 配置 location_labels 参数 | +| | | | 10.0.1.5 | | +| | | | 10.0.1.6 | | ++----------------------+-------------+------------------------------+-------------+----------------------------------------------------+ +| TiKV | 6 | 32 VCore 64GB | 10.0.1.7 | 1\. 区分实例级别的 port、status_port; | +| | | | 10.0.1.8 | 2. 配置全局参数 readpool、storage 以及 raftstore; | +| | | | 10.0.1.9 | 3. 配置实例级别 host 维度的 labels; | +| | | | | 4. 配置 numa 绑核操作 | ++----------------------+-------------+------------------------------+-------------+----------------------------------------------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.10 | 默认配置 | ++----------------------+-------------+------------------------------+-------------+----------------------------------------------------+ ### 拓扑模版 diff --git a/minimal-deployment-topology.md b/minimal-deployment-topology.md index 8ab6ef2b0d5d..efe80b13485d 100644 --- a/minimal-deployment-topology.md +++ b/minimal-deployment-topology.md @@ -9,12 +9,24 @@ summary: 介绍 TiDB 集群的最小拓扑。 ## 拓扑信息 -|实例 | 个数 | 物理机配置 | IP |配置 | -| :-- | :-- | :-- | :-- | :-- | -| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口 <br/> 全局目录配置 | -| PD | 3 | 4 VCore 8GB * 1 |10.0.1.4 <br/> 10.0.1.5 <br/> 10.0.1.6 | 默认端口 <br/> 全局目录配置 | -| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.7 <br/> 10.0.1.8 <br/> 10.0.1.9 | 默认端口 <br/> 全局目录配置 | -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.10 | 默认端口 <br/> 全局目录配置 | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:=====================+:============+:==================================+:============+:=============+ +| TiDB | 3 | 16 VCore 32GB \* 1 | 10.0.1.1 | 默认端口 | +| | | | 10.0.1.2 | 全局目录配置 | +| | | | 10.0.1.3 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| PD | 3 | 4 VCore 8GB \* 1 | 10.0.1.4 | 默认端口 | +| | | | 10.0.1.5 | 全局目录配置 | +| | | | 10.0.1.6 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) \* 1 | 10.0.1.7 | 默认端口 | +| | | | 10.0.1.8 | 全局目录配置 | +| | | | 10.0.1.9 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.10 | 默认端口 | +| | | | | 全局目录配置 | ++----------------------+-------------+-----------------------------------+-------------+--------------+ ### 拓扑模版 diff --git a/multi-data-centers-in-one-city-deployment.md b/multi-data-centers-in-one-city-deployment.md index 4ecdb84d3481..0ddc96ea35dc 100644 --- a/multi-data-centers-in-one-city-deployment.md +++ b/multi-data-centers-in-one-city-deployment.md @@ -1,158 +1,158 @@ ---- -title: 同城多数据中心部署 TiDB -summary: 本文档介绍同城多数据中心部署 TiDB 方案。 ---- - -# 同城多数据中心部署 TiDB - -作为 NewSQL 数据库,TiDB 兼顾了传统关系型数据库的优秀特性、NoSQL 数据库可扩展性以及跨数据中心场景下的高可用。本文档旨在介绍同城多数据中心部署 TiDB 方案。 - -## 了解 Raft 协议 - -Raft 是一种分布式一致性算法,在 TiDB 集群的多种组件中,PD 和 TiKV 都通过 Raft 实现了数据的容灾。Raft 的灾难恢复能力通过如下机制实现: - -- Raft 成员的本质是日志复制和状态机。Raft 成员之间通过复制日志来实现数据同步;Raft 成员在不同条件下切换自己的成员状态,其目标是选出 leader 以提供对外服务。 -- Raft 是一个表决系统,它遵循多数派协议,在一个 Raft Group 中,某成员获得大多数投票,它的成员状态就会转变为 leader。也就是说,当一个 Raft Group 还保有大多数节点 (majority) 时,它就能够选出 leader 以提供对外服务。 - -遵循 Raft 可靠性的特点,放到现实场景中: - -- 想克服任意 1 台服务器 (host) 的故障,应至少提供 3 台服务器。 -- 想克服任意 1 个机柜 (rack) 的故障,应至少提供 3 个机柜。 -- 想克服任意 1 个数据中心(dc,又称机房)的故障,应至少提供 3 个数据中心。 -- 想应对任意 1 个城市的灾难场景,应至少规划 3 个城市用于部署。 - -可见,原生 Raft 协议对于偶数副本的支持并不是很友好,考虑跨城网络延迟影响,或许同城三数据中心是最适合部署 Raft 的高可用及容灾方案。 - -## 同城三数据中心方案 - -同城三数据中心方案,即同城存有三个机房部署 TiDB 集群,同城三数据中心间的数据同步通过集群自身内部(Raft 协议)完成。同城三数据中心可同时对外进行读写服务,任意中心发生故障不影响数据一致性。 - -### 简易架构图 - -集群 TiDB、TiKV 和 PD 组件分别分布在 3 个不同的数据中心,这是最常规且高可用性最高的方案。 - - - -**优点:** - -- 所有数据的副本分布在三个数据中心,具备高可用和容灾能力 -- 任何一个数据中心失效后,不会产生任何数据丢失 (RPO = 0) -- 任何一个数据中心失效后,其他两个数据中心会自动发起 leader election,并在合理长的时间内(通常情况 20s 以内)自动恢复服务 - - - -**缺点:** - -性能受网络延迟影响。具体影响如下: - -- 对于写入的场景,所有写入的数据需要同步复制到至少 2 个数据中心,由于 TiDB 写入过程使用两阶段提交,故写入延迟至少需要 2 倍数据中心间的延迟。 -- 对于读请求来说,如果数据 leader 与发起读取的 TiDB 节点不在同一个数据中心,也会受网络延迟影响。 -- TiDB 中的每个事务都需要向 PD leader 获取 TSO,当 TiDB 与 PD leader 不在同一个数据中心时,它上面运行的事务也会因此受网络延迟影响,每个有写入的事务会获取两次 TSO。 - -### 架构优化图 - -如果不需要每个数据中心同时对外提供服务,可以将业务流量全部派发到一个数据中心,并通过调度策略把 Region leader 和 PD leader 都迁移到同一个数据中心。这样一来,不管是从 PD 获取 TSO,还是读取 Region,都不会受数据中心间网络的影响。当该数据中心失效后,PD leader 和 Region leader 会自动在其它数据中心选出,只需要把业务流量转移至其他存活的数据中心即可。 - - - -**优点:** - -集群 TSO 获取能力以及读取性能有所提升。具体调度策略设置模板参照如下: - -```shell --- 其他机房统一驱逐 leader 到业务流量机房 -config set label-property reject-leader LabelName labelValue - --- 迁移 PD leader 并设置优先级 -member leader transfer pdName1 -member leader_priority pdName1 5 -member leader_priority pdName2 4 -member leader_priority pdName3 3 -``` - -> **注意:** -> -> TiDB 5.2 及以上版本默认不支持 `label-property` 配置。若要设置副本策略,请使用 [Placement Rules](/configure-placement-rules.md)。 - -**缺点:** - -- 写入场景仍受数据中心网络延迟影响,这是因为遵循 Raft 多数派协议,所有写入的数据需要同步复制到至少 2 个数据中心 -- TiDB Server 数据中心级别单点 -- 业务流量纯走单数据中心,性能受限于单数据中心网络带宽压力 -- TSO 获取能力以及读取性能受限于业务流量数据中心集群 PD、TiKV 组件是否正常,否则仍受跨数据中心网络交互影响 - -### 样例部署图 - -#### 样例拓扑架构 - -下面假设某城存有 IDC1、IDC2、IDC3 三机房,机房 IDC 中存有两套机架,每个机架存有三台服务器,不考虑混布以及单台机器多实例部署下,同城三数据中心架构集群(3 副本)部署参考如下: - - - -#### TiKV Labels 简介 - -TiKV 是一个 Multi-Raft 系统,其数据按 Region(默认 96M)切分,每个 Region 的 3 个副本构成了一个 Raft Group。假设一个 3 副本 TiDB 集群,由于 Region 的副本数与 TiKV 实例数量无关,则一个 Region 的 3 个副本只会被调度到其中 3 个 TiKV 实例上,也就是说即使集群扩容 N 个 TiKV 实例,其本质仍是一个 3 副本集群。 - -由于 3 副本的 Raft Group 只能容忍 1 副本故障,当集群被扩容到 N 个 TiKV 实例时,这个集群依然只能容忍一个 TiKV 实例的故障。2 个 TiKV 实例的故障可能会导致某些 Region 丢失多个副本,整个集群的数据也不再完整,访问到这些 Region 上的数据的 SQL 请求将会失败。而 N 个 TiKV 实例中同时有两个发生故障的概率是远远高于 3 个 TiKV 中同时有两个发生故障的概率的,也就是说 Multi-Raft 系统集群扩容 TiKV 实例越多,其可用性是逐渐降低的。 - -正因为 Multi-Raft TiKV 系统局限性,Labels 标签应运而出,其主要用于描述 TiKV 的位置信息。Label 信息随着部署或滚动更新操作刷新到 TiKV 的启动配置文件中,启动后的 TiKV 会将自己最新的 Label 信息上报给 PD,PD 根据用户登记的 Label 名称(也就是 Label 元信息),结合 TiKV 的拓扑进行 Region 副本的最优调度,从而提高系统可用性。 - -#### TiKV Labels 样例规划 - -针对 TiKV Labels 标签,你需要根据已有的物理资源、容灾能力容忍度等方面进行设计与规划,进而提升系统的可用性和容灾能力。并根据已规划的拓扑架构,在集群初始化配置文件中进行配置(此处省略其他非重点项): - -```ini -server_configs: - pd: - replication.location-labels: ["zone","dc","rack","host"] - -tikv_servers: - - host: 10.63.10.30 - config: - server.labels: { zone: "z1", dc: "d1", rack: "r1", host: "30" } - - host: 10.63.10.31 - config: - server.labels: { zone: "z1", dc: "d1", rack: "r1", host: "31" } - - host: 10.63.10.32 - config: - server.labels: { zone: "z1", dc: "d1", rack: "r2", host: "32" } - - host: 10.63.10.33 - config: - server.labels: { zone: "z1", dc: "d1", rack: "r2", host: "33" } - - - host: 10.63.10.34 - config: - server.labels: { zone: "z2", dc: "d1", rack: "r1", host: "34" } - - host: 10.63.10.35 - config: - server.labels: { zone: "z2", dc: "d1", rack: "r1", host: "35" } - - host: 10.63.10.36 - config: - server.labels: { zone: "z2", dc: "d1", rack: "r2", host: "36" } - - host: 10.63.10.37 - config: - server.labels: { zone: "z2", dc: "d1", rack: "r2", host: "37" } - - - host: 10.63.10.38 - config: - server.labels: { zone: "z3", dc: "d1", rack: "r1", host: "38" } - - host: 10.63.10.39 - config: - server.labels: { zone: "z3", dc: "d1", rack: "r1", host: "39" } - - host: 10.63.10.40 - config: - server.labels: { zone: "z3", dc: "d1", rack: "r2", host: "40" } - - host: 10.63.10.41 - config: - server.labels: { zone: "z3", dc: "d1", rack: "r2", host: "41" } -``` - -本例中,zone 表示逻辑可用区层级,用于控制副本的隔离(当前集群 3 副本)。 - -不直接采用 dc,rack,host 三层 Label 结构的原因是考虑到将来可能发生 dc(数据中心)的扩容,假设新扩容的 dc 编号是 d2,d3,d4,则只需在对应可用区下扩容 dc;rack 扩容只需在对应 dc 下扩容即可。 - -如果直接采用 dc,rack,host 三层 Label 结构,那么扩容 dc 操作可能需重打 Label,TiKV 数据整体需要 Rebalance。 - -### 高可用和容灾分析 - -同城多数据中心方案提供的保障是,任意一个数据中心故障时,集群能自动恢复服务,不需要人工介入,并能保证数据一致性。注意,各种调度策略都是用于帮助性能优化的,当发生故障时,调度机制总是第一优先考虑可用性而不是性能。 +--- +title: 同城多数据中心部署 TiDB +summary: 本文档介绍同城多数据中心部署 TiDB 方案。 +--- + +# 同城多数据中心部署 TiDB + +作为 NewSQL 数据库,TiDB 兼顾了传统关系型数据库的优秀特性、NoSQL 数据库可扩展性以及跨数据中心场景下的高可用。本文档旨在介绍同城多数据中心部署 TiDB 方案。 + +## 了解 Raft 协议 + +Raft 是一种分布式一致性算法,在 TiDB 集群的多种组件中,PD 和 TiKV 都通过 Raft 实现了数据的容灾。Raft 的灾难恢复能力通过如下机制实现: + +- Raft 成员的本质是日志复制和状态机。Raft 成员之间通过复制日志来实现数据同步;Raft 成员在不同条件下切换自己的成员状态,其目标是选出 leader 以提供对外服务。 +- Raft 是一个表决系统,它遵循多数派协议,在一个 Raft Group 中,某成员获得大多数投票,它的成员状态就会转变为 leader。也就是说,当一个 Raft Group 还保有大多数节点 (majority) 时,它就能够选出 leader 以提供对外服务。 + +遵循 Raft 可靠性的特点,放到现实场景中: + +- 想克服任意 1 台服务器 (host) 的故障,应至少提供 3 台服务器。 +- 想克服任意 1 个机柜 (rack) 的故障,应至少提供 3 个机柜。 +- 想克服任意 1 个数据中心(dc,又称机房)的故障,应至少提供 3 个数据中心。 +- 想应对任意 1 个城市的灾难场景,应至少规划 3 个城市用于部署。 + +可见,原生 Raft 协议对于偶数副本的支持并不是很友好,考虑跨城网络延迟影响,或许同城三数据中心是最适合部署 Raft 的高可用及容灾方案。 + +## 同城三数据中心方案 + +同城三数据中心方案,即同城存有三个机房部署 TiDB 集群,同城三数据中心间的数据同步通过集群自身内部(Raft 协议)完成。同城三数据中心可同时对外进行读写服务,任意中心发生故障不影响数据一致性。 + +### 简易架构图 + +集群 TiDB、TiKV 和 PD 组件分别分布在 3 个不同的数据中心,这是最常规且高可用性最高的方案。 + + + +**优点:** + +- 所有数据的副本分布在三个数据中心,具备高可用和容灾能力 +- 任何一个数据中心失效后,不会产生任何数据丢失 (RPO = 0) +- 任何一个数据中心失效后,其他两个数据中心会自动发起 leader election,并在合理长的时间内(通常情况 20s 以内)自动恢复服务 + + + +**缺点:** + +性能受网络延迟影响。具体影响如下: + +- 对于写入的场景,所有写入的数据需要同步复制到至少 2 个数据中心,由于 TiDB 写入过程使用两阶段提交,故写入延迟至少需要 2 倍数据中心间的延迟。 +- 对于读请求来说,如果数据 leader 与发起读取的 TiDB 节点不在同一个数据中心,也会受网络延迟影响。 +- TiDB 中的每个事务都需要向 PD leader 获取 TSO,当 TiDB 与 PD leader 不在同一个数据中心时,它上面运行的事务也会因此受网络延迟影响,每个有写入的事务会获取两次 TSO。 + +### 架构优化图 + +如果不需要每个数据中心同时对外提供服务,可以将业务流量全部派发到一个数据中心,并通过调度策略把 Region leader 和 PD leader 都迁移到同一个数据中心。这样一来,不管是从 PD 获取 TSO,还是读取 Region,都不会受数据中心间网络的影响。当该数据中心失效后,PD leader 和 Region leader 会自动在其它数据中心选出,只需要把业务流量转移至其他存活的数据中心即可。 + + + +**优点:** + +集群 TSO 获取能力以及读取性能有所提升。具体调度策略设置模板参照如下: + +```shell +-- 其他机房统一驱逐 leader 到业务流量机房 +config set label-property reject-leader LabelName labelValue + +-- 迁移 PD leader 并设置优先级 +member leader transfer pdName1 +member leader_priority pdName1 5 +member leader_priority pdName2 4 +member leader_priority pdName3 3 +``` + +> **注意:** +> +> TiDB 5.2 及以上版本默认不支持 `label-property` 配置。若要设置副本策略,请使用 [Placement Rules](/configure-placement-rules.md)。 + +**缺点:** + +- 写入场景仍受数据中心网络延迟影响,这是因为遵循 Raft 多数派协议,所有写入的数据需要同步复制到至少 2 个数据中心 +- TiDB Server 数据中心级别单点 +- 业务流量纯走单数据中心,性能受限于单数据中心网络带宽压力 +- TSO 获取能力以及读取性能受限于业务流量数据中心集群 PD、TiKV 组件是否正常,否则仍受跨数据中心网络交互影响 + +### 样例部署图 + +#### 样例拓扑架构 + +下面假设某城存有 IDC1、IDC2、IDC3 三机房,机房 IDC 中存有两套机架,每个机架存有三台服务器,不考虑混布以及单台机器多实例部署下,同城三数据中心架构集群(3 副本)部署参考如下: + + + +#### TiKV Labels 简介 + +TiKV 是一个 Multi-Raft 系统,其数据按 Region(默认 96M)切分,每个 Region 的 3 个副本构成了一个 Raft Group。假设一个 3 副本 TiDB 集群,由于 Region 的副本数与 TiKV 实例数量无关,则一个 Region 的 3 个副本只会被调度到其中 3 个 TiKV 实例上,也就是说即使集群扩容 N 个 TiKV 实例,其本质仍是一个 3 副本集群。 + +由于 3 副本的 Raft Group 只能容忍 1 副本故障,当集群被扩容到 N 个 TiKV 实例时,这个集群依然只能容忍一个 TiKV 实例的故障。2 个 TiKV 实例的故障可能会导致某些 Region 丢失多个副本,整个集群的数据也不再完整,访问到这些 Region 上的数据的 SQL 请求将会失败。而 N 个 TiKV 实例中同时有两个发生故障的概率是远远高于 3 个 TiKV 中同时有两个发生故障的概率的,也就是说 Multi-Raft 系统集群扩容 TiKV 实例越多,其可用性是逐渐降低的。 + +正因为 Multi-Raft TiKV 系统局限性,Labels 标签应运而出,其主要用于描述 TiKV 的位置信息。Label 信息随着部署或滚动更新操作刷新到 TiKV 的启动配置文件中,启动后的 TiKV 会将自己最新的 Label 信息上报给 PD,PD 根据用户登记的 Label 名称(也就是 Label 元信息),结合 TiKV 的拓扑进行 Region 副本的最优调度,从而提高系统可用性。 + +#### TiKV Labels 样例规划 + +针对 TiKV Labels 标签,你需要根据已有的物理资源、容灾能力容忍度等方面进行设计与规划,进而提升系统的可用性和容灾能力。并根据已规划的拓扑架构,在集群初始化配置文件中进行配置(此处省略其他非重点项): + +```ini +server_configs: + pd: + replication.location-labels: ["zone","dc","rack","host"] + +tikv_servers: + - host: 10.63.10.30 + config: + server.labels: { zone: "z1", dc: "d1", rack: "r1", host: "30" } + - host: 10.63.10.31 + config: + server.labels: { zone: "z1", dc: "d1", rack: "r1", host: "31" } + - host: 10.63.10.32 + config: + server.labels: { zone: "z1", dc: "d1", rack: "r2", host: "32" } + - host: 10.63.10.33 + config: + server.labels: { zone: "z1", dc: "d1", rack: "r2", host: "33" } + + - host: 10.63.10.34 + config: + server.labels: { zone: "z2", dc: "d1", rack: "r1", host: "34" } + - host: 10.63.10.35 + config: + server.labels: { zone: "z2", dc: "d1", rack: "r1", host: "35" } + - host: 10.63.10.36 + config: + server.labels: { zone: "z2", dc: "d1", rack: "r2", host: "36" } + - host: 10.63.10.37 + config: + server.labels: { zone: "z2", dc: "d1", rack: "r2", host: "37" } + + - host: 10.63.10.38 + config: + server.labels: { zone: "z3", dc: "d1", rack: "r1", host: "38" } + - host: 10.63.10.39 + config: + server.labels: { zone: "z3", dc: "d1", rack: "r1", host: "39" } + - host: 10.63.10.40 + config: + server.labels: { zone: "z3", dc: "d1", rack: "r2", host: "40" } + - host: 10.63.10.41 + config: + server.labels: { zone: "z3", dc: "d1", rack: "r2", host: "41" } +``` + +本例中,zone 表示逻辑可用区层级,用于控制副本的隔离(当前集群 3 副本)。 + +不直接采用 dc,rack,host 三层 Label 结构的原因是考虑到将来可能发生 dc(数据中心)的扩容,假设新扩容的 dc 编号是 d2,d3,d4,则只需在对应可用区下扩容 dc;rack 扩容只需在对应 dc 下扩容即可。 + +如果直接采用 dc,rack,host 三层 Label 结构,那么扩容 dc 操作可能需重打 Label,TiKV 数据整体需要 Rebalance。 + +### 高可用和容灾分析 + +同城多数据中心方案提供的保障是,任意一个数据中心故障时,集群能自动恢复服务,不需要人工介入,并能保证数据一致性。注意,各种调度策略都是用于帮助性能优化的,当发生故障时,调度机制总是第一优先考虑可用性而不是性能。 diff --git a/post-installation-check.md b/post-installation-check.md index 16b5b7896c53..b63da861f80b 100644 --- a/post-installation-check.md +++ b/post-installation-check.md @@ -1,212 +1,212 @@ ---- -title: 验证集群运行状态 -summary: 介绍如何验证集群运行状态。 ---- - -# 验证集群运行状态 - -在部署完一套 TiDB 集群后,需要检查集群是否正常运行。本文介绍如何通过 TiUP 命令、[TiDB Dashboard](/dashboard/dashboard-intro.md) 和 Grafana 检查集群状态,以及如何登录 TiDB 数据库执行简单的 SQL 操作。 - -## 通过 TiUP 检查集群状态 - -检查集群状态的命令是 `tiup cluster display <cluster-name>`,例如: - -{{< copyable "shell-regular" >}} - -```shell -tiup cluster display tidb-test -``` - -预期结果输出:各节点 Status 状态信息为 `Up` 说明集群状态正常。 - -## 通过 TiDB Dashboard 和 Grafana 检查集群状态 - -本节介绍如何通过 [TiDB Dashboard](/dashboard/dashboard-intro.md) 和 Grafana 检查集群状态。 - -### 查看 TiDB Dashboard 检查 TiDB 集群状态 - -1. 通过 `{pd-ip}:{pd-port}/dashboard` 登录 TiDB Dashboard,登录用户和口令为 TiDB 数据库 `root` 用户和口令。如果你修改过数据库的 `root` 密码,则以修改后的密码为准,默认密码为空。 - -  - -2. 主页面显示 TiDB 集群中节点信息 - -  - -### 查看 Grafana 监控 Overview 页面检查 TiDB 集群状态 - -- 通过 `{Grafana-ip}:3000` 登录 Grafana 监控,默认用户名及密码为 `admin`/`admin`。 - -- 点击 **Overview** 监控页面检查 TiDB 端口和负载监控信息。 - -  - -## 登录数据库执行简单 DML/DDL 操作和查询 SQL 语句 - -> **注意:** -> -> 登录数据库前,你需要安装 MySQL 客户端。 - -执行以下命令登录数据库: - -{{< copyable "shell-regular" >}} - -```shell -mysql -u root -h ${tidb_server_host_IP_address} -P 4000 -``` - -其中,`${tidb_server_host_IP_address}` 是在[初始化集群拓扑文件](/production-deployment-using-tiup.md#第-3-步初始化集群拓扑文件)时为 `tidb_servers` 配置的 IP 地址之一,例如 `10.0.1.7`。 - -输出下列信息表示登录成功: - -```sql -Welcome to the MySQL monitor. Commands end with ; or \g. -Your MySQL connection id is 3 -Server version: 5.7.25-TiDB-v5.0.0 TiDB Server (Apache License 2.0) Community Edition, MySQL 5.7 compatible - -Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - -Oracle is a registered trademark of Oracle Corporation and/or its -affiliates. Other names may be trademarks of their respective -owners. - -Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. -``` - -### 数据库操作 - -+ 检查 TiDB 版本 - - {{< copyable "sql" >}} - - ```sql - select tidb_version()\G - ``` - - 预期结果输出: - - ```sql - *************************** 1. row *************************** - tidb_version(): Release Version: v5.0.0 - Edition: Community - Git Commit Hash: 689a6b6439ae7835947fcaccf329a3fc303986cb - Git Branch: HEAD - UTC Build Time: 2020-05-28 11:09:45 - GoVersion: go1.13.4 - Race Enabled: false - TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306 - Check Table Before Drop: false - 1 row in set (0.00 sec) - ``` - -+ 创建 PingCAP database - - {{< copyable "sql" >}} - - ```sql - create database pingcap; - ``` - - ```sql - Query OK, 0 rows affected (0.10 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - use pingcap; - ``` - - 预期输出 - - ```sql - Database changed - ``` - -+ 创建 `tab_tidb` 表 - - {{< copyable "sql" >}} - - ```sql - CREATE TABLE `tab_tidb` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL DEFAULT '', - `age` int(11) NOT NULL DEFAULT 0, - `version` varchar(20) NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - KEY `idx_age` (`age`)); - ``` - - 预期输出 - - ```sql - Query OK, 0 rows affected (0.11 sec) - ``` - -+ 插入数据 - - {{< copyable "sql" >}} - - ```sql - insert into `tab_tidb` values (1,'TiDB',5,'TiDB-v5.0.0'); - ``` - - 预期输出 - - ```sql - Query OK, 1 row affected (0.03 sec) - ``` - -+ 查看 `tab_tidb` 结果 - - {{< copyable "sql" >}} - - ```sql - select * from tab_tidb; - ``` - - 预期输出 - - ```sql - +----+------+-----+-------------+ - | id | name | age | version | - +----+------+-----+-------------+ - | 1 | TiDB | 5 | TiDB-v5.0.0 | - +----+------+-----+-------------+ - 1 row in set (0.00 sec) - ``` - -+ 查看 TiKV store 状态、`store_id`、存储情况以及启动时间 - - {{< copyable "sql" >}} - - ```sql - select STORE_ID,ADDRESS,STORE_STATE,STORE_STATE_NAME,CAPACITY,AVAILABLE,UPTIME from INFORMATION_SCHEMA.TIKV_STORE_STATUS; - ``` - - 预期输出 - - ```sql - +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ - | STORE_ID | ADDRESS | STORE_STATE | STORE_STATE_NAME | CAPACITY | AVAILABLE | UPTIME | - +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ - | 1 | 10.0.1.1:20160 | 0 | Up | 49.98GiB | 46.3GiB | 5h21m52.474864026s | - | 4 | 10.0.1.2:20160 | 0 | Up | 49.98GiB | 46.32GiB | 5h21m52.522669177s | - | 5 | 10.0.1.3:20160 | 0 | Up | 49.98GiB | 45.44GiB | 5h21m52.713660541s | - +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ - 3 rows in set (0.00 sec) - ``` - -+ 退出 - - {{< copyable "sql" >}} - - ```sql - exit - ``` - - 预期输出 - - ```sql - Bye - ``` +--- +title: 验证集群运行状态 +summary: 介绍如何验证集群运行状态。 +--- + +# 验证集群运行状态 + +在部署完一套 TiDB 集群后,需要检查集群是否正常运行。本文介绍如何通过 TiUP 命令、[TiDB Dashboard](/dashboard/dashboard-intro.md) 和 Grafana 检查集群状态,以及如何登录 TiDB 数据库执行简单的 SQL 操作。 + +## 通过 TiUP 检查集群状态 + +检查集群状态的命令是 `tiup cluster display <cluster-name>`,例如: + +{{< copyable "shell-regular" >}} + +```shell +tiup cluster display tidb-test +``` + +预期结果输出:各节点 Status 状态信息为 `Up` 说明集群状态正常。 + +## 通过 TiDB Dashboard 和 Grafana 检查集群状态 + +本节介绍如何通过 [TiDB Dashboard](/dashboard/dashboard-intro.md) 和 Grafana 检查集群状态。 + +### 查看 TiDB Dashboard 检查 TiDB 集群状态 + +1. 通过 `{pd-ip}:{pd-port}/dashboard` 登录 TiDB Dashboard,登录用户和口令为 TiDB 数据库 `root` 用户和口令。如果你修改过数据库的 `root` 密码,则以修改后的密码为准,默认密码为空。 + +  + +2. 主页面显示 TiDB 集群中节点信息 + +  + +### 查看 Grafana 监控 Overview 页面检查 TiDB 集群状态 + +- 通过 `{Grafana-ip}:3000` 登录 Grafana 监控,默认用户名及密码为 `admin`/`admin`。 + +- 点击 **Overview** 监控页面检查 TiDB 端口和负载监控信息。 + +  + +## 登录数据库执行简单 DML/DDL 操作和查询 SQL 语句 + +> **注意:** +> +> 登录数据库前,你需要安装 MySQL 客户端。 + +执行以下命令登录数据库: + +{{< copyable "shell-regular" >}} + +```shell +mysql -u root -h ${tidb_server_host_IP_address} -P 4000 +``` + +其中,`${tidb_server_host_IP_address}` 是在[初始化集群拓扑文件](/production-deployment-using-tiup.md#第-3-步初始化集群拓扑文件)时为 `tidb_servers` 配置的 IP 地址之一,例如 `10.0.1.7`。 + +输出下列信息表示登录成功: + +```sql +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 3 +Server version: 5.7.25-TiDB-v5.0.0 TiDB Server (Apache License 2.0) Community Edition, MySQL 5.7 compatible + +Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. +``` + +### 数据库操作 + ++ 检查 TiDB 版本 + + {{< copyable "sql" >}} + + ```sql + select tidb_version()\G + ``` + + 预期结果输出: + + ```sql + *************************** 1. row *************************** + tidb_version(): Release Version: v5.0.0 + Edition: Community + Git Commit Hash: 689a6b6439ae7835947fcaccf329a3fc303986cb + Git Branch: HEAD + UTC Build Time: 2020-05-28 11:09:45 + GoVersion: go1.13.4 + Race Enabled: false + TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306 + Check Table Before Drop: false + 1 row in set (0.00 sec) + ``` + ++ 创建 PingCAP database + + {{< copyable "sql" >}} + + ```sql + create database pingcap; + ``` + + ```sql + Query OK, 0 rows affected (0.10 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + use pingcap; + ``` + + 预期输出 + + ```sql + Database changed + ``` + ++ 创建 `tab_tidb` 表 + + {{< copyable "sql" >}} + + ```sql + CREATE TABLE `tab_tidb` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(20) NOT NULL DEFAULT '', + `age` int(11) NOT NULL DEFAULT 0, + `version` varchar(20) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `idx_age` (`age`)); + ``` + + 预期输出 + + ```sql + Query OK, 0 rows affected (0.11 sec) + ``` + ++ 插入数据 + + {{< copyable "sql" >}} + + ```sql + insert into `tab_tidb` values (1,'TiDB',5,'TiDB-v5.0.0'); + ``` + + 预期输出 + + ```sql + Query OK, 1 row affected (0.03 sec) + ``` + ++ 查看 `tab_tidb` 结果 + + {{< copyable "sql" >}} + + ```sql + select * from tab_tidb; + ``` + + 预期输出 + + ```sql + +----+------+-----+-------------+ + | id | name | age | version | + +----+------+-----+-------------+ + | 1 | TiDB | 5 | TiDB-v5.0.0 | + +----+------+-----+-------------+ + 1 row in set (0.00 sec) + ``` + ++ 查看 TiKV store 状态、`store_id`、存储情况以及启动时间 + + {{< copyable "sql" >}} + + ```sql + select STORE_ID,ADDRESS,STORE_STATE,STORE_STATE_NAME,CAPACITY,AVAILABLE,UPTIME from INFORMATION_SCHEMA.TIKV_STORE_STATUS; + ``` + + 预期输出 + + ```sql + +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ + | STORE_ID | ADDRESS | STORE_STATE | STORE_STATE_NAME | CAPACITY | AVAILABLE | UPTIME | + +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ + | 1 | 10.0.1.1:20160 | 0 | Up | 49.98GiB | 46.3GiB | 5h21m52.474864026s | + | 4 | 10.0.1.2:20160 | 0 | Up | 49.98GiB | 46.32GiB | 5h21m52.522669177s | + | 5 | 10.0.1.3:20160 | 0 | Up | 49.98GiB | 45.44GiB | 5h21m52.713660541s | + +----------+--------------------+-------------+------------------+----------+-----------+--------------------+ + 3 rows in set (0.00 sec) + ``` + ++ 退出 + + {{< copyable "sql" >}} + + ```sql + exit + ``` + + 预期输出 + + ```sql + Bye + ``` diff --git a/quick-start-with-tidb.md b/quick-start-with-tidb.md index 4405c56e02c7..316cb39410b3 100644 --- a/quick-start-with-tidb.md +++ b/quick-start-with-tidb.md @@ -251,13 +251,25 @@ TiDB 是一个分布式系统。最基础的 TiDB 测试集群通常由 2 个 Ti > > 下表中拓扑实例的 IP 为示例 IP。在实际部署时,请替换为实际的 IP。 -| 实例 | 个数 | IP | 配置 | -|:-- | :-- | :-- | :-- | -| TiKV | 3 | 10.0.1.1 <br/> 10.0.1.1 <br/> 10.0.1.1 | 避免端口和目录冲突 | -| TiDB | 1 | 10.0.1.1 | 默认端口 <br/> 全局目录配置 | -| PD | 1 | 10.0.1.1 | 默认端口 <br/> 全局目录配置 | -| TiFlash | 1 | 10.0.1.1 | 默认端口 <br/> 全局目录配置 | -| Monitor | 1 | 10.0.1.1 | 默认端口 <br/> 全局目录配置 | ++-----------------+-----------------+-----------------+--------------------+ +| 实例 | 个数 | IP | 配置 | ++:================+:================+:================+:===================+ +| TiKV | 3 | 10.0.1.1 | 避免端口和目录冲突 | +| | | 10.0.1.1 | | +| | | 10.0.1.1 | | ++-----------------+-----------------+-----------------+--------------------+ +| TiDB | 1 | 10.0.1.1 | 默认端口 | +| | | | 全局目录配置 | ++-----------------+-----------------+-----------------+--------------------+ +| PD | 1 | 10.0.1.1 | 默认端口 | +| | | | 全局目录配置 | ++-----------------+-----------------+-----------------+--------------------+ +| TiFlash | 1 | 10.0.1.1 | 默认端口 | +| | | | 全局目录配置 | ++-----------------+-----------------+-----------------+--------------------+ +| Monitor | 1 | 10.0.1.1 | 默认端口 | +| | | | 全局目录配置 | ++-----------------+-----------------+-----------------+--------------------+ 部署主机软件和环境要求: diff --git a/sql-mode.md b/sql-mode.md index 159aa6074fa8..f960f9cc37b7 100644 --- a/sql-mode.md +++ b/sql-mode.md @@ -18,36 +18,69 @@ Modes 是用逗号 (',') 间隔开的一系列不同的模式。使用 `SELECT @ ## SQL mode 列表,如下 -| 名称 | 含义 | -| --- | --- | -| PIPES_AS_CONCAT | 将 "\|\|" 视为字符串连接操作符(+)(同CONCAT()),而不视为OR(支持) | -| ANSI_QUOTES | 将 `"` 视为识别符,如果启用 ANSI_QUOTES,只单引号内的会被认为是 String Literals,双引号被解释为识别符,因此不能用双引号来引用字符串(支持)| -| IGNORE_SPACE | 若开启该模式,系统忽略空格。例如:“user” 和 “user “ 是相同的(支持)| -| ONLY_FULL_GROUP_BY | 如果 GROUP BY 出现的列并没有在 SELECT,HAVING,ORDER BY 中出现,此 SQL 不合法,因为不在 GROUP BY 中的列被查询展示出来不符合正常现象(支持) | -| NO_UNSIGNED_SUBTRACTION | 在减运算中,如果某个操作数没有符号,不要将结果标记为UNSIGNED(支持)| -| NO_DIR_IN_CREATE | 创建表时,忽视所有 INDEX DIRECTORY 和 DATA DIRECTORY 指令,该选项仅对从复制服务器有用 (仅语法支持)| -| NO_KEY_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持)| -| NO_FIELD_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持)| -| NO_TABLE_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持)| -| NO_AUTO_VALUE_ON_ZERO | 若启用该模式,在AUTO_INCREMENT列的处理传入的值是 0 或者具体数值时系统直接将该值写入此列,传入 NULL 时系统自动生成下一个序列号(支持)| -| NO_BACKSLASH_ESCAPES | 若启用该模式,`\` 反斜杠符号仅代表它自己(支持)| -| STRICT_TRANS_TABLES | 对于事务存储引擎启用严格模式,insert非法值之后,回滚整条语句(支持)| -| STRICT_ALL_TABLES | 对于事务型表,写入非法值之后,回滚整个事务语句(支持)| -| NO_ZERO_IN_DATE | 在严格模式,不接受月或日部分为0的日期。如果使用IGNORE选项,我们为类似的日期插入'0000-00-00'。在非严格模式,可以接受该日期,但会生成警告(支持) -| NO_ZERO_DATE | 在严格模式,不要将 '0000-00-00'做为合法日期。你仍然可以用IGNORE选项插入零日期。在非严格模式,可以接受该日期,但会生成警告(支持)| -| ALLOW_INVALID_DATES | 不检查全部日期的合法性,仅检查月份值在 1 到 12 及 日期值在 1 到 31 之间,仅适用于 DATE 和 DATATIME 列,TIMESTAMP 列需要全部检查其合法性(支持)| -| ERROR_FOR_DIVISION_BY_ZERO | 若启用该模式,在 INSERT 或 UPDATE 过程中,被除数为 0 值时,系统产生错误 <br/> 若未启用该模式,被除数为 0 值时,系统产生警告,并用 NULL 代替(支持) | -| NO_AUTO_CREATE_USER | 防止 GRANT 自动创建新用户,但指定密码除外(支持)| -| HIGH_NOT_PRECEDENCE | NOT 操作符的优先级是表达式。例如: NOT a BETWEEN b AND c 被解释为 NOT (a BETWEEN b AND c)。在部份旧版本MySQL中, 表达式被解释为(NOT a) BETWEEN b AND c (支持) | -| NO_ENGINE_SUBSTITUTION | 如果需要的存储引擎被禁用或未编译,可以防止自动替换存储引擎(仅语法支持)| -| PAD_CHAR_TO_FULL_LENGTH | 若启用该模式,系统对于 CHAR 类型不会截断尾部空格(仅语法支持。该模式[在 MySQL 8.0 中已废弃](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length)。)| -| REAL_AS_FLOAT | 将 REAL 视为 FLOAT 的同义词,而不是 DOUBLE 的同义词(支持)| -| POSTGRESQL | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS(仅语法支持)| -| MSSQL | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS(仅语法支持)| -| DB2 | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS(仅语法支持)| -| MAXDB | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER(支持)| -| MySQL323 | 等同于 NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE(仅语法支持)| -| MYSQL40 | 等同于 NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE(仅语法支持)| -| ANSI | 等同于 REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE(仅语法支持)| -| TRADITIONAL | 等同于 STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER(仅语法支持)| -| ORACLE | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER(仅语法支持)| ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 名称 | 含义 | ++===================================+========================================================================================================================================================================================+ +| PIPES_AS_CONCAT | 将 "||" 视为字符串连接操作符(+)(同CONCAT()),而不视为OR(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ANSI_QUOTES | 将 `"` 视为识别符,如果启用 ANSI_QUOTES,只单引号内的会被认为是 String Literals,双引号被解释为识别符,因此不能用双引号来引用字符串(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| IGNORE_SPACE | 若开启该模式,系统忽略空格。例如:“user” 和 “user “ 是相同的(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ONLY_FULL_GROUP_BY | 如果 GROUP BY 出现的列并没有在 SELECT,HAVING,ORDER BY 中出现,此 SQL 不合法,因为不在 GROUP BY 中的列被查询展示出来不符合正常现象(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_UNSIGNED_SUBTRACTION | 在减运算中,如果某个操作数没有符号,不要将结果标记为UNSIGNED(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_DIR_IN_CREATE | 创建表时,忽视所有 INDEX DIRECTORY 和 DATA DIRECTORY 指令,该选项仅对从复制服务器有用 (仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_KEY_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_FIELD_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_TABLE_OPTIONS | 使用 SHOW CREATE TABLE 时不会输出 MySQL 特有的语法部分,如 ENGINE ,使用 mysqldump 跨DB种类迁移的时需要考虑此选项(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_AUTO_VALUE_ON_ZERO | 若启用该模式,在AUTO_INCREMENT列的处理传入的值是 0 或者具体数值时系统直接将该值写入此列,传入 NULL 时系统自动生成下一个序列号(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_BACKSLASH_ESCAPES | 若启用该模式,`\` 反斜杠符号仅代表它自己(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| STRICT_TRANS_TABLES | 对于事务存储引擎启用严格模式,insert非法值之后,回滚整条语句(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| STRICT_ALL_TABLES | 对于事务型表,写入非法值之后,回滚整个事务语句(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_ZERO_IN_DATE | 在严格模式,不接受月或日部分为0的日期。如果使用IGNORE选项,我们为类似的日期插入'0000-00-00'。在非严格模式,可以接受该日期,但会生成警告(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_ZERO_DATE | 在严格模式,不要将 '0000-00-00'做为合法日期。你仍然可以用IGNORE选项插入零日期。在非严格模式,可以接受该日期,但会生成警告(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ALLOW_INVALID_DATES | 不检查全部日期的合法性,仅检查月份值在 1 到 12 及 日期值在 1 到 31 之间,仅适用于 DATE 和 DATATIME 列,TIMESTAMP 列需要全部检查其合法性(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ERROR_FOR_DIVISION_BY_ZERO | 若启用该模式,在 INSERT 或 UPDATE 过程中,被除数为 0 值时,系统产生错误 | +| | 若未启用该模式,被除数为 0 值时,系统产生警告,并用 NULL 代替(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_AUTO_CREATE_USER | 防止 GRANT 自动创建新用户,但指定密码除外(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| HIGH_NOT_PRECEDENCE | NOT 操作符的优先级是表达式。例如: NOT a BETWEEN b AND c 被解释为 NOT (a BETWEEN b AND c)。在部份旧版本MySQL中, 表达式被解释为(NOT a) BETWEEN b AND c (支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| NO_ENGINE_SUBSTITUTION | 如果需要的存储引擎被禁用或未编译,可以防止自动替换存储引擎(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| PAD_CHAR_TO_FULL_LENGTH | 若启用该模式,系统对于 CHAR 类型不会截断尾部空格(仅语法支持。该模式[在 MySQL 8.0 中已废弃](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_pad_char_to_full_length)。) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| REAL_AS_FLOAT | 将 REAL 视为 FLOAT 的同义词,而不是 DOUBLE 的同义词(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| POSTGRESQL | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| MSSQL | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| DB2 | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| MAXDB | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER(支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| MySQL323 | 等同于 NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| MYSQL40 | 等同于 NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ANSI | 等同于 REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| TRADITIONAL | 等同于 STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ORACLE | 等同于 PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER(仅语法支持) | ++-----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/sql-statements/sql-statement-admin.md b/sql-statements/sql-statement-admin.md index 04ba1ac6aada..ec06129eebb5 100644 --- a/sql-statements/sql-statement-admin.md +++ b/sql-statements/sql-statement-admin.md @@ -8,12 +8,17 @@ title: ADMIN ## ADMIN 与 DDL 相关的扩展语句 -| 语句 | 功能描述 | -|------------------------------------------------------------------------------------------|-----------------------------| -| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业 | -| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64 校验和 | -| [<code>ADMIN CHECK [TABLE\|INDEX]</code>](/sql-statements/sql-statement-admin-check-table-index.md) | 校验表中数据和对应索引的一致性 | -| [<code>ADMIN SHOW DDL [JOBS\|QUERIES]</code>](/sql-statements/sql-statement-admin-show-ddl.md) | 显示有关当前正在运行或最近完成的 DDL 作业的详细信息| ++-----------------------------------------------------------------------------------------+-----------------------------------------------------+ +| 语句 | 功能描述 | ++=========================================================================================+=====================================================+ +| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业 | ++-----------------------------------------------------------------------------------------+-----------------------------------------------------+ +| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64 校验和 | ++-----------------------------------------------------------------------------------------+-----------------------------------------------------+ +| [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) | 校验表中数据和对应索引的一致性 | ++-----------------------------------------------------------------------------------------+-----------------------------------------------------+ +| [`ADMIN SHOW DDL [JOBS|QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) | 显示有关当前正在运行或最近完成的 DDL 作业的详细信息 | ++-----------------------------------------------------------------------------------------+-----------------------------------------------------+ ## `admin reload` 语句 diff --git a/ticdc-deployment-topology.md b/ticdc-deployment-topology.md index dfb573f55c24..0adc5d03331d 100644 --- a/ticdc-deployment-topology.md +++ b/ticdc-deployment-topology.md @@ -13,13 +13,28 @@ summary: 介绍 TiCDC 部署 TiDB 集群的拓扑结构。 ## 拓扑信息 -|实例 | 个数 | 物理机配置 | IP |配置 | -| :-- | :-- | :-- | :-- | :-- | -| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口 <br/> 全局目录配置 | -| PD | 3 | 4 VCore 8GB * 1 |10.0.1.4 <br/> 10.0.1.5 <br/> 10.0.1.6 | 默认端口 <br/> 全局目录配置 | -| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.7 <br/> 10.0.1.8 <br/> 10.0.1.9 | 默认端口 <br/> 全局目录配置 | -| CDC | 3 | 8 VCore 16GB * 1 | 10.0.1.11 <br/> 10.0.1.12 <br/> 10.0.1.13 | 默认端口 <br/> 全局目录配置 | -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.11 | 默认端口 <br/> 全局目录配置 | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:=====================+:============+:==================================+:============+:=============+ +| TiDB | 3 | 16 VCore 32GB \* 1 | 10.0.1.1 | 默认端口 | +| | | | 10.0.1.2 | 全局目录配置 | +| | | | 10.0.1.3 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| PD | 3 | 4 VCore 8GB \* 1 | 10.0.1.4 | 默认端口 | +| | | | 10.0.1.5 | 全局目录配置 | +| | | | 10.0.1.6 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) \* 1 | 10.0.1.7 | 默认端口 | +| | | | 10.0.1.8 | 全局目录配置 | +| | | | 10.0.1.9 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| CDC | 3 | 8 VCore 16GB \* 1 | 10.0.1.11 | 默认端口 | +| | | | 10.0.1.12 | 全局目录配置 | +| | | | 10.0.1.13 | | ++----------------------+-------------+-----------------------------------+-------------+--------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.11 | 默认端口 | +| | | | | 全局目录配置 | ++----------------------+-------------+-----------------------------------+-------------+--------------+ ### 拓扑模版 diff --git a/ticdc/ticdc-overview.md b/ticdc/ticdc-overview.md index c67a80e2fcd5..18a046166c60 100644 --- a/ticdc/ticdc-overview.md +++ b/ticdc/ticdc-overview.md @@ -133,11 +133,19 @@ TiCDC Open Protocol 是一种行级别的数据变更通知协议,为监控、 `sort-dir` 配置项用于给 TiCDC 内部的排序器指定临时文件目录,其作用在各版本有过如下兼容性更改: -| 版本 | `sort-engine` 的使用 | 说明 | 使用建议 | -| :--- | :--- | :-- | :-- | -| v4.0.11 及之前的 v4.0 版本,v5.0.0-rc | 作为 changefeed 配置项,给 `file` sorter 和 `unified` Sorter 指定临时文件目录 | 在这些版本中,`file` sorter 和 `unified` sorter **均不是**正式功能 (GA),不推荐在生产环境中使用。<br/><br/>如果有多个 changefeed 被配置使用了 `unified` 作为 `sort-engine`,那么实际使用的临时文件目录可能是任何一个 changefeed 的 `sort-dir` 配置,且每个 TiCDC 节点上使用的目录可能不一致。 | 不推荐在生产环境中使用 Unified Sorter | -| v4.0.12,v4.0.13,v5.0.0 及 v5.0.1 | 作为 changefeed 配置项或 `cdc server` 配置项 | 在默认情况下 changefeed 的 `sort-dir` 配置不会生效,而 `cdc server` 的 `sort-dir` 配置默认为 `/tmp/cdc_sort`。建议生产环境下仅配置 `cdc server` 的相关配置。<br /><br />如果你使用 TiUP 部署 TiCDC,建议升级到最新的 TiUP 版本并在 TiCDC server 配置中设置 `sorter.sort-dir` 一项。<br /><br />在 v4.0.13、v5.0.0 和 v5.0.1 中 unified sorter 是默认开启的,如果要将集群升级至这些版本,请确保 TiCDC server 配置中的 `sorter.sort-dir` 已经被正确配置。| 需要通过 `cdc server` 命令行参数(或 TiUP)配置 `sort-dir` | -| v4.0.14 及之后的 v4.0 版本,v5.0.3 及之后的 v5.0 版本,更新的版本 | `sort-dir` 被弃用,建议配置 `data-dir` | `data-dir` 可以通过最新版本的 TiUP 进行配置。这些版本中 unified sorter 是默认开启的,升级时请确保 `data-dir` 已经被正确配置,否则将默认使用 `/tmp/cdc_data`。<br /><br />如果该目录所在设备空间不足,有可能出现硬盘空间不足的问题。之前配置的 changefeed 的 `sort-dir` 配置将会失效。| 需要通过 `cdc server` 命令行参数(或 TiUP)配置 `data-dir` | ++-------------------------------------------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+ +| 版本 | `sort-engine` 的使用 | 说明 | 使用建议 | ++:==================================================================+:==============================================================================+:===================================================================================================================================================================================+:===========================================================+ +| v4.0.11 及之前的 v4.0 版本,v5.0.0-rc | 作为 changefeed 配置项,给 `file` sorter 和 `unified` Sorter 指定临时文件目录 | 在这些版本中,`file` sorter 和 `unified` sorter **均不是**正式功能 (GA),不推荐在生产环境中使用。 | 不推荐在生产环境中使用 Unified Sorter | +| | | 如果有多个 changefeed 被配置使用了 `unified` 作为 `sort-engine`,那么实际使用的临时文件目录可能是任何一个 changefeed 的 `sort-dir` 配置,且每个 TiCDC 节点上使用的目录可能不一致。 | | ++-------------------------------------------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+ +| v4.0.12,v4.0.13,v5.0.0 及 v5.0.1 | 作为 changefeed 配置项或 `cdc server` 配置项 | 在默认情况下 changefeed 的 `sort-dir` 配置不会生效,而 `cdc server` 的 `sort-dir` 配置默认为 `/tmp/cdc_sort`。建议生产环境下仅配置 `cdc server` 的相关配置。 | 需要通过 `cdc server` 命令行参数(或 TiUP)配置 `sort-dir` | +| | | 如果你使用 TiUP 部署 TiCDC,建议升级到最新的 TiUP 版本并在 TiCDC server 配置中设置 `sorter.sort-dir` 一项。 | | +| | | 在 v4.0.13、v5.0.0 和 v5.0.1 中 unified sorter 是默认开启的,如果要将集群升级至这些版本,请确保 TiCDC server 配置中的 `sorter.sort-dir` 已经被正确配置。 | | ++-------------------------------------------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+ +| v4.0.14 及之后的 v4.0 版本,v5.0.3 及之后的 v5.0 版本,更新的版本 | `sort-dir` 被弃用,建议配置 `data-dir` | `data-dir` 可以通过最新版本的 TiUP 进行配置。这些版本中 unified sorter 是默认开启的,升级时请确保 `data-dir` 已经被正确配置,否则将默认使用 `/tmp/cdc_data`。 | 需要通过 `cdc server` 命令行参数(或 TiUP)配置 `data-dir` | +| | | 如果该目录所在设备空间不足,有可能出现硬盘空间不足的问题。之前配置的 changefeed 的 `sort-dir` 配置将会失效。 | | ++-------------------------------------------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+ ### 全局临时表兼容性说明 diff --git a/tidb-binlog-deployment-topology.md b/tidb-binlog-deployment-topology.md index 14e7faac147d..8b588b2d9c80 100644 --- a/tidb-binlog-deployment-topology.md +++ b/tidb-binlog-deployment-topology.md @@ -9,13 +9,29 @@ summary: 介绍如何在部署最小拓扑集群的基础上,同时部署 TiDB ## 拓扑信息 -| 实例 |个数| 物理机配置 | IP | 配置 | -| :-- | :-- | :-- | :-- | :-- | -|TiDB | 3 | 16 VCore 32 GB | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口配置;<br/>开启 enable_binlog; <br/> 开启 ignore-error | -| PD | 3 | 4 VCore 8 GB | 10.0.1.4 <br/> 10.0.1.5 <br/> 10.0.1.6 | 默认端口配置 | -| TiKV | 3 | 16 VCore 32 GB | 10.0.1.7 <br/> 10.0.1.8 <br/> 10.0.1.9 | 默认端口配置 | -| Pump| 3 |8 VCore 16GB |10.0.1.1 <br/> 10.0.1.7 <br/> 10.0.1.8 | 默认端口配置; <br/> 设置 GC 时间 7 天 | -| Drainer | 1 | 8 VCore 16GB | 10.0.1.12 | 默认端口配置;<br/> 设置默认初始化 commitTS -1 为最近的时间戳 <br/> 配置下游目标 TiDB 10.0.1.12:4000 | ++-------------+-------------+----------------+-------------+-------------------------------------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:============+:============+:===============+:============+:==========================================+ +| TiDB | 3 | 16 VCore 32 GB | 10.0.1.1 | 默认端口配置; | +| | | | 10.0.1.2 | 开启 enable_binlog; | +| | | | 10.0.1.3 | 开启 ignore-error | ++-------------+-------------+----------------+-------------+-------------------------------------------+ +| PD | 3 | 4 VCore 8 GB | 10.0.1.4 | 默认端口配置 | +| | | | 10.0.1.5 | | +| | | | 10.0.1.6 | | ++-------------+-------------+----------------+-------------+-------------------------------------------+ +| TiKV | 3 | 16 VCore 32 GB | 10.0.1.7 | 默认端口配置 | +| | | | 10.0.1.8 | | +| | | | 10.0.1.9 | | ++-------------+-------------+----------------+-------------+-------------------------------------------+ +| Pump | 3 | 8 VCore 16GB | 10.0.1.1 | 默认端口配置; | +| | | | 10.0.1.7 | 设置 GC 时间 7 天 | +| | | | 10.0.1.8 | | ++-------------+-------------+----------------+-------------+-------------------------------------------+ +| Drainer | 1 | 8 VCore 16GB | 10.0.1.12 | 默认端口配置; | +| | | | | 设置默认初始化 commitTS -1 为最近的时间戳 | +| | | | | 配置下游目标 TiDB 10.0.1.12:4000 | ++-------------+-------------+----------------+-------------+-------------------------------------------+ ### 拓扑模版 diff --git a/tidb-lightning/tidb-lightning-backends.md b/tidb-lightning/tidb-lightning-backends.md index 82b043afef5e..12bd29044d42 100644 --- a/tidb-lightning/tidb-lightning-backends.md +++ b/tidb-lightning/tidb-lightning-backends.md @@ -256,140 +256,64 @@ on-duplicate = "replace" # 或者 “error”、“ignore” 当需要将数据导入到 TiDB 集群时,TiDB Lightning TiDB-backend 可以完全取代 [Loader](https://docs.pingcap.com/zh/tidb/v4.0/loader-overview)。下表说明了如何将 Loader 的配置迁移到 [TiDB Lightning 配置](/tidb-lightning/tidb-lightning-configuration.md)中: -<table> -<thead><tr><th>Loader</th><th>TiDB Lightning</th></tr></thead> -<tbody> -<tr><td> - -```toml -# 日志级别 -log-level = "info" -# 日志的输出目录 -log-file = "loader.log" -# Prometheus -status-addr = ":8272" -# 线程数 -pool-size = 16 -``` - -</td><td> - -```toml -[lightning] -# 日志级别 -level = "info" -# 日志的输出目录。如果未指定该位置目录,默认为执行命令的所在目录。 -file = "tidb-lightning.log" -# Prometheus -pprof-port = 8289 -# 并发度 (最好使用默认设置) -#region-concurrency = 16 -``` - -</td></tr> -<tr><td> - -```toml -# 断点数据库名 -checkpoint-schema = "tidb_loader" -``` - -</td><td> - -```toml -[checkpoint] -# 断点存储 -enable = true -schema = "tidb_lightning_checkpoint" -# 断点默认存储在本地的文件系统,这样更高效。但你也可以 -# 选择将断点存储在目标数据库中,设置如下: -# driver = "mysql" -``` - -</td></tr> -<tr><td> - -```toml -``` - -</td><td> - -```toml -[tikv-importer] -# 使用 TiDB-backend -backend = "tidb" -``` - -</td></tr> -<tr><td> - -```toml -# 数据源目录 -dir = "/data/export/" -``` - -</td><td> - -```toml -[mydumper] -# 数据源目录 -data-source-dir = "/data/export" -``` - -</td></tr> - -<tr><td> - -```toml -[db] -# TiDB 连接参数 -host = "127.0.0.1" -port = 4000 -user = "root" -password = "" -#sql-mode = "" -``` - -</td><td> - -```toml -[tidb] -# TiDB 连接参数 -host = "127.0.0.1" -port = 4000 -# 在 TiDB-backend 模式下,该参数为可选参数 -# status-port = 10080 -user = "root" -password = "" -#sql-mode = "" -``` - -</td></tr> -<tr><td> - -```toml -# [[route-rules]] -# Table routes -# schema-pattern = "shard_db_*" -# table-pattern = "shard_table_*" -# target-schema = "shard_db" -# target-table = "shard_table" -``` - -</td><td> - -```toml -# [[routes]] -# Table routes -# schema-pattern = "shard_db_*" -# table-pattern = "shard_table_*" -# target-schema = "shard_db" -# target-table = "shard_table" -``` - -</td></tr> -</tbody> -</table> ++-----------------------------------+--------------------------------------------------------------------+ +| Loader | TiDB Lightning | ++===================================+====================================================================+ +| ``` toml | ``` toml | +| # 日志级别 | [lightning] | +| log-level = "info" | # 日志级别 | +| # 日志的输出目录 | level = "info" | +| log-file = "loader.log" | # 日志的输出目录。如果未指定该位置目录,默认为执行命令的所在目录。 | +| # Prometheus | file = "tidb-lightning.log" | +| status-addr = ":8272" | # Prometheus | +| # 线程数 | pprof-port = 8289 | +| pool-size = 16 | # 并发度 (最好使用默认设置) | +| ``` | #region-concurrency = 16 | +| | ``` | ++-----------------------------------+--------------------------------------------------------------------+ +| ``` toml | ``` toml | +| # 断点数据库名 | [checkpoint] | +| checkpoint-schema = "tidb_loader" | # 断点存储 | +| ``` | enable = true | +| | schema = "tidb_lightning_checkpoint" | +| | # 断点默认存储在本地的文件系统,这样更高效。但你也可以 | +| | # 选择将断点存储在目标数据库中,设置如下: | +| | # driver = "mysql" | +| | ``` | ++-----------------------------------+--------------------------------------------------------------------+ +| ``` toml | ``` toml | +| ``` | [tikv-importer] | +| | # 使用 TiDB-backend | +| | backend = "tidb" | +| | ``` | ++-----------------------------------+--------------------------------------------------------------------+ +| ``` toml | ``` toml | +| # 数据源目录 | [mydumper] | +| dir = "/data/export/" | # 数据源目录 | +| ``` | data-source-dir = "/data/export" | +| | ``` | ++-----------------------------------+--------------------------------------------------------------------+ +| ``` toml | ``` toml | +| [db] | [tidb] | +| # TiDB 连接参数 | # TiDB 连接参数 | +| host = "127.0.0.1" | host = "127.0.0.1" | +| port = 4000 | port = 4000 | +| user = "root" | # 在 TiDB-backend 模式下,该参数为可选参数 | +| password = "" | # status-port = 10080 | +| #sql-mode = "" | user = "root" | +| ``` | password = "" | +| | #sql-mode = "" | +| | ``` | ++-----------------------------------+--------------------------------------------------------------------+ +| ``` toml | ``` toml | +| # [[route-rules]] | # [[routes]] | +| # Table routes | # Table routes | +| # schema-pattern = "shard_db_*" | # schema-pattern = "shard_db_*" | +| # table-pattern = "shard_table_*" | # table-pattern = "shard_table_*" | +| # target-schema = "shard_db" | # target-schema = "shard_db" | +| # target-table = "shard_table" | # target-table = "shard_table" | +| ``` | ``` | ++-----------------------------------+--------------------------------------------------------------------+ ## TiDB Lightning Importer-backend diff --git a/tidb-limitations.md b/tidb-limitations.md index 1d8832f8a646..0a6c974f36d5 100644 --- a/tidb-limitations.md +++ b/tidb-limitations.md @@ -1,69 +1,69 @@ ---- -title: TiDB 使用限制 ---- - -# 使用限制 - -本文会将详细描述 TiDB 中常见的使用限制,包括:标识符长度,最大支持的数据库、表、索引、分区表、序列等的个数。 - -## 标识符长度限制 - -| 标识符类型 | 最大长度(字符)| -|:---------|:--------------| -| Database | 64 | -| Table | 64 | -| Column | 64 | -| Index | 64 | -| View | 64 | -| Sequence | 64 | - -## Databases、Tables、Views、Connections 总个数限制 - -| 标识符类型 | 最大个数 | -|:----------|:----------| -| Databases | unlimited | -| Tables | unlimited | -| Views | unlimited | -| Connections| unlimited| - -## 单个 Database 的限制 - -| 类型 | 最大限制 | -|:----------|:----------| -| Tables |unlimited | - -## 单个 Table 的限制 - -| 类型 | 最大限制(默认值) | -|:----------|:------------------------------| -| Columns | 默认为 1017,最大可调至 4096 | -| Indexs | 默认为 64,最大可调至 512 | -| Rows | 无限制 | -| Size | 无限制 | -| Partitions| 8192 | - -* Columns 的最大限制可通过 [`table-column-count-limit`](/tidb-configuration-file.md#table-column-count-limit-从-v50-版本开始引入) 修改。 -* Indexs 的最大限制可通过 [`index-limit`](/tidb-configuration-file.md#index-limit-从-v50-版本开始引入) 修改。 - -## 单行的限制 - -| 类型 | 最大限制 | -|:----------|:----------| -| Size | 默认为 6MB,可通过 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v50-版本开始引入) 配置项调整 | - -## 字符串类型限制 - -| 类型 | 最大限制 | -|:----------|:----------| -| CHAR | 256 字符 | -| BINARY | 256 字节 | -| VARBINARY | 65535 字节 | -| VARCHAR | 16383 字符 | -| TEXT | 6MB 字节 | -| BLOB | 6MB 字节 | - -## SQL Statements 的限制 - -| 类型 | 最大限制 | -|:----------|:----------| -| 单个事务最大语句数 | 在使用乐观事务并开启事务重试的情况下,默认限制 5000,可通过 [`stmt-count-limit`](/tidb-configuration-file.md#stmt-count-limit) 调整 | +--- +title: TiDB 使用限制 +--- + +# 使用限制 + +本文会将详细描述 TiDB 中常见的使用限制,包括:标识符长度,最大支持的数据库、表、索引、分区表、序列等的个数。 + +## 标识符长度限制 + +| 标识符类型 | 最大长度(字符)| +|:---------|:--------------| +| Database | 64 | +| Table | 64 | +| Column | 64 | +| Index | 64 | +| View | 64 | +| Sequence | 64 | + +## Databases、Tables、Views、Connections 总个数限制 + +| 标识符类型 | 最大个数 | +|:----------|:----------| +| Databases | unlimited | +| Tables | unlimited | +| Views | unlimited | +| Connections| unlimited| + +## 单个 Database 的限制 + +| 类型 | 最大限制 | +|:----------|:----------| +| Tables |unlimited | + +## 单个 Table 的限制 + +| 类型 | 最大限制(默认值) | +|:----------|:------------------------------| +| Columns | 默认为 1017,最大可调至 4096 | +| Indexs | 默认为 64,最大可调至 512 | +| Rows | 无限制 | +| Size | 无限制 | +| Partitions| 8192 | + +* Columns 的最大限制可通过 [`table-column-count-limit`](/tidb-configuration-file.md#table-column-count-limit-从-v50-版本开始引入) 修改。 +* Indexs 的最大限制可通过 [`index-limit`](/tidb-configuration-file.md#index-limit-从-v50-版本开始引入) 修改。 + +## 单行的限制 + +| 类型 | 最大限制 | +|:----------|:----------| +| Size | 默认为 6MB,可通过 [`txn-entry-size-limit`](/tidb-configuration-file.md#txn-entry-size-limit-从-v50-版本开始引入) 配置项调整 | + +## 字符串类型限制 + +| 类型 | 最大限制 | +|:----------|:----------| +| CHAR | 256 字符 | +| BINARY | 256 字节 | +| VARBINARY | 65535 字节 | +| VARCHAR | 16383 字符 | +| TEXT | 6MB 字节 | +| BLOB | 6MB 字节 | + +## SQL Statements 的限制 + +| 类型 | 最大限制 | +|:----------|:----------| +| 单个事务最大语句数 | 在使用乐观事务并开启事务重试的情况下,默认限制 5000,可通过 [`stmt-count-limit`](/tidb-configuration-file.md#stmt-count-limit) 调整 | diff --git a/tiflash-deployment-topology.md b/tiflash-deployment-topology.md index cbd469428178..8ba4c585e767 100644 --- a/tiflash-deployment-topology.md +++ b/tiflash-deployment-topology.md @@ -9,13 +9,27 @@ summary: 了解在部署最小拓扑集群的基础上,部署 TiFlash 的拓 ## 拓扑信息 -|实例 | 个数 | 物理机配置 | IP |配置 | -| :-- | :-- | :-- | :-- | :-- | -| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口 <br/> 全局目录配置 | -| PD | 3 | 4 VCore 8GB * 1 |10.0.1.4 <br/> 10.0.1.5 <br/> 10.0.1.6 | 默认端口 <br/> 全局目录配置 | -| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口 <br/> 全局目录配置 | -| TiFlash | 1 | 32 VCore 64 GB 2TB (nvme ssd) * 1 | 10.0.1.10 | 默认端口 <br/> 全局目录配置 | -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.10 | 默认端口 <br/> 全局目录配置 | ++----------------------+-------------+------------------------------------+-------------+--------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:=====================+:============+:===================================+:============+:=============+ +| TiDB | 3 | 16 VCore 32GB \* 1 | 10.0.1.1 | 默认端口 | +| | | | 10.0.1.2 | 全局目录配置 | +| | | | 10.0.1.3 | | ++----------------------+-------------+------------------------------------+-------------+--------------+ +| PD | 3 | 4 VCore 8GB \* 1 | 10.0.1.4 | 默认端口 | +| | | | 10.0.1.5 | 全局目录配置 | +| | | | 10.0.1.6 | | ++----------------------+-------------+------------------------------------+-------------+--------------+ +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) \* 1 | 10.0.1.1 | 默认端口 | +| | | | 10.0.1.2 | 全局目录配置 | +| | | | 10.0.1.3 | | ++----------------------+-------------+------------------------------------+-------------+--------------+ +| TiFlash | 1 | 32 VCore 64 GB 2TB (nvme ssd) \* 1 | 10.0.1.10 | 默认端口 | +| | | | | 全局目录配置 | ++----------------------+-------------+------------------------------------+-------------+--------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.10 | 默认端口 | +| | | | | 全局目录配置 | ++----------------------+-------------+------------------------------------+-------------+--------------+ ### 拓扑模版 diff --git a/tispark-deployment-topology.md b/tispark-deployment-topology.md index b0bffbade80f..83355fe8c3cb 100644 --- a/tispark-deployment-topology.md +++ b/tispark-deployment-topology.md @@ -15,13 +15,28 @@ summary: 介绍 TiUP 部署包含 TiSpark 组件的 TiDB 集群的拓扑结构 ## 拓扑信息 -|实例 | 个数 | 物理机配置 | IP |配置 | -| :-- | :-- | :-- | :-- | :-- | -| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1 <br/> 10.0.1.2 <br/> 10.0.1.3 | 默认端口 <br/> 全局目录配置 | -| PD | 3 | 4 VCore 8GB * 1 |10.0.1.4 <br/> 10.0.1.5 <br/> 10.0.1.6 | 默认端口 <br/> 全局目录配置 | -| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.7 <br/> 10.0.1.8 <br/> 10.0.1.9 | 默认端口 <br/> 全局目录配置 | -| TiSpark | 3 | 8 VCore 16GB * 1 | 10.0.1.21 (master) <br/> 10.0.1.22 (worker) <br/> 10.0.1.23 (worker) | 默认端口 <br/> 全局目录配置 | -| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.11 | 默认端口 <br/> 全局目录配置 | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ +| 实例 | 个数 | 物理机配置 | IP | 配置 | ++:=====================+:============+:==================================+:===================+:=============+ +| TiDB | 3 | 16 VCore 32GB \* 1 | 10.0.1.1 | 默认端口 | +| | | | 10.0.1.2 | 全局目录配置 | +| | | | 10.0.1.3 | | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ +| PD | 3 | 4 VCore 8GB \* 1 | 10.0.1.4 | 默认端口 | +| | | | 10.0.1.5 | 全局目录配置 | +| | | | 10.0.1.6 | | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) \* 1 | 10.0.1.7 | 默认端口 | +| | | | 10.0.1.8 | 全局目录配置 | +| | | | 10.0.1.9 | | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ +| TiSpark | 3 | 8 VCore 16GB \* 1 | 10.0.1.21 (master) | 默认端口 | +| | | | 10.0.1.22 (worker) | 全局目录配置 | +| | | | 10.0.1.23 (worker) | | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ +| Monitoring & Grafana | 1 | 4 VCore 8GB \* 1 500GB (ssd) | 10.0.1.11 | 默认端口 | +| | | | | 全局目录配置 | ++----------------------+-------------+-----------------------------------+--------------------+--------------+ ### 拓扑模版 diff --git a/troubleshoot-cpu-issues.md b/troubleshoot-cpu-issues.md index d9192911d760..d798f97ab9ad 100644 --- a/troubleshoot-cpu-issues.md +++ b/troubleshoot-cpu-issues.md @@ -1,139 +1,139 @@ ---- -title: 读写延迟增加 -summary: 介绍读写延时增加、抖动时的排查思路,可能的原因和解决方法。 ---- - -# 读写延迟增加 - -本文档介绍读写延迟增加、抖动时的排查思路,可能的原因和解决方法。 - -## 常见原因 - -### TiDB 执行计划不对导致延迟增高 - -查询语句的执行计划不稳定,偶尔执行计划选择错误的索引,导致查询延迟增加。 - -**现象:** - -* 如果慢日志中输出了执行计划,可以直接查看执行计划。用 `select tidb_decode_plan('xxx...')` 语句可以解析出具体的执行计划。 -* 监控中的 key 扫描异常升高;慢日志中 SQL 执行时间 `Scan Keys` 数目较大。 -* SQL 执行时间相比于其他数据库(例如 MySQL)有较大差距。可以对比其他数据库执行计划,例如 `Join Order` 是否不同。 - -**可能的原因:** - -* 统计信息不准确 - -**解决方案:** - -* 更新统计信息 - * 手动 `analyze table`,配合 crontab 定期 `analyze`,维持统计信息准确度。 - * 自动 `auto analyze`,调低 `analyze ratio` 阈值,提高收集频次,并设置运行时间窗口。示例如下: - * `set global tidb_auto_analyze_ratio=0.2;` - * `set global tidb_auto_analyze_start_time='00:00 +0800';` - * `set global tidb_auto_analyze_end_time='06:00 +0800';` -* 绑定执行计划 - * 修改业务 SQL,使用 `use index` 固定使用列上的索引。 - * 3.0 版本下,业务可以不用修改 SQL,使用 `create global binding` 创建 `force index` 的绑定 SQL。 - * 4.0 版本支持 SQL Plan Management,可以避免因执行计划不稳定导致的性能下降。 - -### PD 异常 - -**现象:** - -监控中 PD TSO 的 **wait duration** 异常升高。**wait duration** 代表从开始等待 PD 返回,到等待结束的时间。 - -**可能的原因:** - -* 磁盘问题。PD 所在的节点 I/O 被占满,排查是否有其他 I/O 高的组件与 PD 混合部署以及磁盘的健康情况,可通过监控 Grafana -> **disk performance** -> **latency** 和 **load** 等指标进行验证,必要时可以使用 fio 工具对盘进行检测,见案例 [case-292](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case292.md)。 - -* PD 之间的网络问题。PD 日志中有 `"lost the TCP streaming connection"`,排查 PD 之间网络是否有问题,可通过监控 Grafana -> **PD** -> **etcd** 的 **round trip** 来验证,见案例 [case-177](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case177.md)。 - -* 系统负载高,日志中能看到 `"server is likely overloaded"`,见案例 [case-214](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case214.md)。 - -* 选举不出 leader。PD 日志中有 `"lease is not expired"`,见 issues [https://github.com/etcd-io/etcd/issues/10355](https://github.com/etcd-io/etcd/issues/10355)。v3.0.x 版本和 v2.1.19 版本已解决该问题,见案例 [case-875](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case875.md)。 - -* 选举慢。Region 加载时间长,从 PD 日志中 `grep "regions cost"`(例如日志中可能是 `load 460927 regions cost 11.77099s`),如果出现秒级,则说明较慢,v3.0 版本可开启 Region Storage(设置 `use-region-storage` 为 `true`),该特性能极大缩短加载 Region 的时间,见案例 [case-429](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case429.md)。 - -* TiDB 与 PD 之间的网络问题,应排查网络相关情况。通过监控 Grafana -> **blackbox_exporter** -> **ping latency** 确定 TiDB 到 PD leader 的网络是否正常。 - -* PD 报 `FATAL` 错误,日志中有 `"range failed to find revision pair"`。v3.0.8 中已经解决问题,见 PR [https://github.com/pingcap/pd/pull/2040](https://github.com/pingcap/pd/pull/2040)。详情请参考案例 [case-947](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case947.md)。 - -* 使用 `/api/v1/regions` 接口时 Region 数量过多可能会导致 PD OOM。已于 v3.0.8 版本修复,见 [https://github.com/pingcap/pd/pull/1986](https://github.com/pingcap/pd/pull/1986)。 - -* 滚动升级的时候 PD OOM,gRPC 消息大小没限制,监控可看到 TCP InSegs 较大,已于 v3.0.6 版本修复,见 [https://github.com/pingcap/pd/pull/1952](https://github.com/pingcap/pd/pull/1952)。 - -* PD panic,请[提交 bug](https://github.com/tikv/pd/issues/new?labels=kind/bug&template=bug-report.md)。 - -* 其他原因,通过 `curl http://127.0.0.1:2379/debug/pprof/goroutine?debug=2` 抓取 goroutine,并[提交 bug](https://github.com/pingcap/pd/issues/new?labels=kind%2Fbug&template=bug-report.md)。 - -### TiKV 异常 - -**现象:** - -监控中 **KV Cmd Duration** 异常升高。KV Cmd Duration 是 TiDB 发送请求给 TiKV 到收到回复的延迟。 - -**可能的原因:** - -* 查看 gRPC duration。gRPC duration 是请求在 TiKV 端的总耗时。通过对比 TiKV 的 gRPC duration 以及 TiDB 中的 KV duration 可以发现潜在的网络问题。比如 gRPC duration 很短但是 TiDB 的 KV duration 显示很长,说明 TiDB 和 TiKV 之间网络延迟可能很高,或者 TiDB 和 TiKV 之间的网卡带宽被占满。 - -* TiKV 重启了导致重新选举 - * TiKV panic 之后又被 `systemd` 重新拉起正常运行,可以通过查看 TiKV 的日志来确认是否有 `panic`,这种情况属于非预期,需要报 bug。 - * 被第三者 `stop`/`kill`,被 `systemd` 重新拉起。查看 `dmesg` 和 `TiKV log` 确认原因。 - * TiKV 发生 OOM 导致重启了。 - * 动态调整 `THP` 导致 hung 住,见案例 [case-500](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case500.md)。 - -* 查看监控:Grafana -> **TiKV-details** -> **errors** 面板 `server is busy` 看到 TiKV RocksDB 出现 write stall 导致发生重新选举。 - -* TiKV 发生网络隔离导致重新选举。 - -* `block-cache` 配置太大导致 OOM,在监控 Grafana -> **TiKV-details** 选中对应的 instance 之后查看 RocksDB 的 `block cache size` 监控来确认是否是该问题。同时请检查 `[storage.block-cache] capacity = # "1GB"` 参数是否设置合理,默认情况下 TiKV 的 `block-cache` 设置为机器总内存的 `45%`。在容器化部署时需要显式指定该参数,因为 TiKV 获取的是物理机的内存,可能会超出单个 container 的内存限制。 - -* Coprocessor 收到大量大查询,返回的数据量太大,gRPC 发送速度跟不上 Coprocessor 向客户端输出数据的速度导致 OOM。可以通过检查监控:Grafana -> **TiKV-details** -> **coprocessor overview** 的 `response size` 是否超过 `network outbound` 流量来确认是否属于这种情况。 - -### TiKV 单线程瓶颈 - -TiKV 中存在一些单线程线程,可能会成为瓶颈。 - -* 单个 TiKV Region 过多导致单个 gRPC 线程成为瓶颈(查看 Grafana -> TiKV-details -> `Thread CPU/gRPC CPU Per Thread` 监控),v3.x 以上版本可以开启 Hibernate Region 特性来解决,见案例 [case-612](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case612.md)。 -* v3.0 之前版本 Raftstore 单线程或者 Apply 单线程到达瓶颈(Grafana -> TiKV-details -> `Thread CPU/raft store CPU 和 Async apply CPU` 超过 `80%`),可以选择扩容 TiKV(v2.x 版本)实例或者升级到多线程模型的 v3.x 版本。 - -### CPU Load 升高 - -**现象:** - -CPU 资源使用到达瓶颈 - -**可能的原因:** - -* 热点问题。 -* 整体负载高,排查 TiDB 的 slow query 和 expensive query。对运行的 query 进行优化,如果缺索引就加索引,如果可以批量执行就批量执行。另一个方案是对集群进行扩容。 - -## 其它原因 - -### 集群维护 - -通常大多数的线上集群有 3 或 5 个 PD 节点,如果维护的主机上有 PD 组件,需要具体考虑节点是 leader 还是 follower,关闭 follower 对集群运行没有任何影响,关闭 leader 需要先切换,并在切换时有 3 秒左右的性能抖动。 - -### 少数派副本离线 - -TiDB 集群默认配置为 3 副本,每一个 Region 都会在集群中保存 3 份,它们之间通过 Raft 协议来选举 Leader 并同步数据。Raft 协议可以保证在数量小于副本数(注意:不是节点数)一半的节点挂掉或者隔离的情况下,仍然能够提供服务,并且不丢失任何数据。对于 3 副本集群,挂掉一个节点可能会导致性能抖动,可用性和正确性理论上不会受影响。 - -### 新增索引 - -由于创建索引在扫表回填索引的时候会消耗大量资源,甚至与一些频繁更新的字段会发生冲突导致正常业务受到影响。大表创建索引的过程往往会持续很长时间,所以要尽可能地平衡执行时间和集群性能之间的关系,比如选择非高频更新时间段。 - -**参数调整:** - -目前主要使用 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 这两个参数来动态调整索引创建速度,通常来说它们的值越小对系统影响越小,但是执行时间越长。 - -一般情况下,先将值保持为默认的 `4` 和 `256` ,观察集群资源使用情况和响应速度,再逐渐调大 `tidb_ddl_reorg_worker_cnt` 参数来增加并发,观察监控如果系统没有发生明显的抖动,再逐渐调大 `tidb_ddl_reorg_batch_size` 参数,但如果索引涉及的列更新很频繁的话就会造成大量冲突造成失败重试。 - -另外还可以通过调整参数 `tidb_ddl_reorg_priority` 为 `PRIORITY_HIGH` 来让创建索引的任务保持高优先级来提升速度,但在通用 OLTP 系统上,一般建议保持默认。 - -### GC 压力大 - -TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。GC 的任务便是清理不再需要的旧数据。 - -* Resolve Locks 阶段在 TiKV 一侧会产生大量的 scan_lock 请求,可以在 gRPC 相关的 metrics 中观察到。`scan_lock` 请求会对全部的 Region 调用。 -* Delete Ranges 阶段会往 TiKV 发送少量的 `unsafe_destroy_range` 请求,也可能没有。可以在 gRPC 相关的 metrics 中和 GC 分类下的 GC tasks 中观察到。 -* Do GC 阶段,默认每台 TiKV 会自动扫描本机上的 leader Region 并对每一个 leader 进行 GC,这一活动可以在 GC 分类下的 GC tasks 中观察到。 +--- +title: 读写延迟增加 +summary: 介绍读写延时增加、抖动时的排查思路,可能的原因和解决方法。 +--- + +# 读写延迟增加 + +本文档介绍读写延迟增加、抖动时的排查思路,可能的原因和解决方法。 + +## 常见原因 + +### TiDB 执行计划不对导致延迟增高 + +查询语句的执行计划不稳定,偶尔执行计划选择错误的索引,导致查询延迟增加。 + +**现象:** + +* 如果慢日志中输出了执行计划,可以直接查看执行计划。用 `select tidb_decode_plan('xxx...')` 语句可以解析出具体的执行计划。 +* 监控中的 key 扫描异常升高;慢日志中 SQL 执行时间 `Scan Keys` 数目较大。 +* SQL 执行时间相比于其他数据库(例如 MySQL)有较大差距。可以对比其他数据库执行计划,例如 `Join Order` 是否不同。 + +**可能的原因:** + +* 统计信息不准确 + +**解决方案:** + +* 更新统计信息 + * 手动 `analyze table`,配合 crontab 定期 `analyze`,维持统计信息准确度。 + * 自动 `auto analyze`,调低 `analyze ratio` 阈值,提高收集频次,并设置运行时间窗口。示例如下: + * `set global tidb_auto_analyze_ratio=0.2;` + * `set global tidb_auto_analyze_start_time='00:00 +0800';` + * `set global tidb_auto_analyze_end_time='06:00 +0800';` +* 绑定执行计划 + * 修改业务 SQL,使用 `use index` 固定使用列上的索引。 + * 3.0 版本下,业务可以不用修改 SQL,使用 `create global binding` 创建 `force index` 的绑定 SQL。 + * 4.0 版本支持 SQL Plan Management,可以避免因执行计划不稳定导致的性能下降。 + +### PD 异常 + +**现象:** + +监控中 PD TSO 的 **wait duration** 异常升高。**wait duration** 代表从开始等待 PD 返回,到等待结束的时间。 + +**可能的原因:** + +* 磁盘问题。PD 所在的节点 I/O 被占满,排查是否有其他 I/O 高的组件与 PD 混合部署以及磁盘的健康情况,可通过监控 Grafana -> **disk performance** -> **latency** 和 **load** 等指标进行验证,必要时可以使用 fio 工具对盘进行检测,见案例 [case-292](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case292.md)。 + +* PD 之间的网络问题。PD 日志中有 `"lost the TCP streaming connection"`,排查 PD 之间网络是否有问题,可通过监控 Grafana -> **PD** -> **etcd** 的 **round trip** 来验证,见案例 [case-177](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case177.md)。 + +* 系统负载高,日志中能看到 `"server is likely overloaded"`,见案例 [case-214](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case214.md)。 + +* 选举不出 leader。PD 日志中有 `"lease is not expired"`,见 issues [https://github.com/etcd-io/etcd/issues/10355](https://github.com/etcd-io/etcd/issues/10355)。v3.0.x 版本和 v2.1.19 版本已解决该问题,见案例 [case-875](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case875.md)。 + +* 选举慢。Region 加载时间长,从 PD 日志中 `grep "regions cost"`(例如日志中可能是 `load 460927 regions cost 11.77099s`),如果出现秒级,则说明较慢,v3.0 版本可开启 Region Storage(设置 `use-region-storage` 为 `true`),该特性能极大缩短加载 Region 的时间,见案例 [case-429](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case429.md)。 + +* TiDB 与 PD 之间的网络问题,应排查网络相关情况。通过监控 Grafana -> **blackbox_exporter** -> **ping latency** 确定 TiDB 到 PD leader 的网络是否正常。 + +* PD 报 `FATAL` 错误,日志中有 `"range failed to find revision pair"`。v3.0.8 中已经解决问题,见 PR [https://github.com/pingcap/pd/pull/2040](https://github.com/pingcap/pd/pull/2040)。详情请参考案例 [case-947](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case947.md)。 + +* 使用 `/api/v1/regions` 接口时 Region 数量过多可能会导致 PD OOM。已于 v3.0.8 版本修复,见 [https://github.com/pingcap/pd/pull/1986](https://github.com/pingcap/pd/pull/1986)。 + +* 滚动升级的时候 PD OOM,gRPC 消息大小没限制,监控可看到 TCP InSegs 较大,已于 v3.0.6 版本修复,见 [https://github.com/pingcap/pd/pull/1952](https://github.com/pingcap/pd/pull/1952)。 + +* PD panic,请[提交 bug](https://github.com/tikv/pd/issues/new?labels=kind/bug&template=bug-report.md)。 + +* 其他原因,通过 `curl http://127.0.0.1:2379/debug/pprof/goroutine?debug=2` 抓取 goroutine,并[提交 bug](https://github.com/pingcap/pd/issues/new?labels=kind%2Fbug&template=bug-report.md)。 + +### TiKV 异常 + +**现象:** + +监控中 **KV Cmd Duration** 异常升高。KV Cmd Duration 是 TiDB 发送请求给 TiKV 到收到回复的延迟。 + +**可能的原因:** + +* 查看 gRPC duration。gRPC duration 是请求在 TiKV 端的总耗时。通过对比 TiKV 的 gRPC duration 以及 TiDB 中的 KV duration 可以发现潜在的网络问题。比如 gRPC duration 很短但是 TiDB 的 KV duration 显示很长,说明 TiDB 和 TiKV 之间网络延迟可能很高,或者 TiDB 和 TiKV 之间的网卡带宽被占满。 + +* TiKV 重启了导致重新选举 + * TiKV panic 之后又被 `systemd` 重新拉起正常运行,可以通过查看 TiKV 的日志来确认是否有 `panic`,这种情况属于非预期,需要报 bug。 + * 被第三者 `stop`/`kill`,被 `systemd` 重新拉起。查看 `dmesg` 和 `TiKV log` 确认原因。 + * TiKV 发生 OOM 导致重启了。 + * 动态调整 `THP` 导致 hung 住,见案例 [case-500](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case500.md)。 + +* 查看监控:Grafana -> **TiKV-details** -> **errors** 面板 `server is busy` 看到 TiKV RocksDB 出现 write stall 导致发生重新选举。 + +* TiKV 发生网络隔离导致重新选举。 + +* `block-cache` 配置太大导致 OOM,在监控 Grafana -> **TiKV-details** 选中对应的 instance 之后查看 RocksDB 的 `block cache size` 监控来确认是否是该问题。同时请检查 `[storage.block-cache] capacity = # "1GB"` 参数是否设置合理,默认情况下 TiKV 的 `block-cache` 设置为机器总内存的 `45%`。在容器化部署时需要显式指定该参数,因为 TiKV 获取的是物理机的内存,可能会超出单个 container 的内存限制。 + +* Coprocessor 收到大量大查询,返回的数据量太大,gRPC 发送速度跟不上 Coprocessor 向客户端输出数据的速度导致 OOM。可以通过检查监控:Grafana -> **TiKV-details** -> **coprocessor overview** 的 `response size` 是否超过 `network outbound` 流量来确认是否属于这种情况。 + +### TiKV 单线程瓶颈 + +TiKV 中存在一些单线程线程,可能会成为瓶颈。 + +* 单个 TiKV Region 过多导致单个 gRPC 线程成为瓶颈(查看 Grafana -> TiKV-details -> `Thread CPU/gRPC CPU Per Thread` 监控),v3.x 以上版本可以开启 Hibernate Region 特性来解决,见案例 [case-612](https://github.com/pingcap/tidb-map/blob/master/maps/diagnose-case-study/case612.md)。 +* v3.0 之前版本 Raftstore 单线程或者 Apply 单线程到达瓶颈(Grafana -> TiKV-details -> `Thread CPU/raft store CPU 和 Async apply CPU` 超过 `80%`),可以选择扩容 TiKV(v2.x 版本)实例或者升级到多线程模型的 v3.x 版本。 + +### CPU Load 升高 + +**现象:** + +CPU 资源使用到达瓶颈 + +**可能的原因:** + +* 热点问题。 +* 整体负载高,排查 TiDB 的 slow query 和 expensive query。对运行的 query 进行优化,如果缺索引就加索引,如果可以批量执行就批量执行。另一个方案是对集群进行扩容。 + +## 其它原因 + +### 集群维护 + +通常大多数的线上集群有 3 或 5 个 PD 节点,如果维护的主机上有 PD 组件,需要具体考虑节点是 leader 还是 follower,关闭 follower 对集群运行没有任何影响,关闭 leader 需要先切换,并在切换时有 3 秒左右的性能抖动。 + +### 少数派副本离线 + +TiDB 集群默认配置为 3 副本,每一个 Region 都会在集群中保存 3 份,它们之间通过 Raft 协议来选举 Leader 并同步数据。Raft 协议可以保证在数量小于副本数(注意:不是节点数)一半的节点挂掉或者隔离的情况下,仍然能够提供服务,并且不丢失任何数据。对于 3 副本集群,挂掉一个节点可能会导致性能抖动,可用性和正确性理论上不会受影响。 + +### 新增索引 + +由于创建索引在扫表回填索引的时候会消耗大量资源,甚至与一些频繁更新的字段会发生冲突导致正常业务受到影响。大表创建索引的过程往往会持续很长时间,所以要尽可能地平衡执行时间和集群性能之间的关系,比如选择非高频更新时间段。 + +**参数调整:** + +目前主要使用 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 这两个参数来动态调整索引创建速度,通常来说它们的值越小对系统影响越小,但是执行时间越长。 + +一般情况下,先将值保持为默认的 `4` 和 `256` ,观察集群资源使用情况和响应速度,再逐渐调大 `tidb_ddl_reorg_worker_cnt` 参数来增加并发,观察监控如果系统没有发生明显的抖动,再逐渐调大 `tidb_ddl_reorg_batch_size` 参数,但如果索引涉及的列更新很频繁的话就会造成大量冲突造成失败重试。 + +另外还可以通过调整参数 `tidb_ddl_reorg_priority` 为 `PRIORITY_HIGH` 来让创建索引的任务保持高优先级来提升速度,但在通用 OLTP 系统上,一般建议保持默认。 + +### GC 压力大 + +TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。GC 的任务便是清理不再需要的旧数据。 + +* Resolve Locks 阶段在 TiKV 一侧会产生大量的 scan_lock 请求,可以在 gRPC 相关的 metrics 中观察到。`scan_lock` 请求会对全部的 Region 调用。 +* Delete Ranges 阶段会往 TiKV 发送少量的 `unsafe_destroy_range` 请求,也可能没有。可以在 gRPC 相关的 metrics 中和 GC 分类下的 GC tasks 中观察到。 +* Do GC 阶段,默认每台 TiKV 会自动扫描本机上的 leader Region 并对每一个 leader 进行 GC,这一活动可以在 GC 分类下的 GC tasks 中观察到。 diff --git a/troubleshoot-hot-spot-issues.md b/troubleshoot-hot-spot-issues.md index 82cc3de3d970..5c839b9235ef 100644 --- a/troubleshoot-hot-spot-issues.md +++ b/troubleshoot-hot-spot-issues.md @@ -1,170 +1,170 @@ ---- -title: TiDB 热点问题处理 ---- - -# TiDB 热点问题处理 - -本文介绍如何定位和解决读写热点问题。 - -TiDB 作为分布式数据库,内建负载均衡机制,尽可能将业务负载均匀地分布到不同计算或存储节点上,更好地利用上整体系统资源。然而,机制不是万能的,在一些场景下仍会有部分业务负载不能被很好地分散,影响性能,形成单点的过高负载,也称为热点。 - -TiDB 提供了完整的方案用于排查、解决或规避这类热点。通过均衡负载热点,可以提升整体性能,包括提高 QPS 和降低延迟等。 - -## 常见热点场景 - -### TiDB 编码规则回顾 - -TiDB 对每个表分配一个 TableID,每一个索引都会分配一个 IndexID,每一行分配一个 RowID(默认情况下,如果表使用整数型的 Primary Key,那么会用 Primary Key 的值当做 RowID)。其中 TableID 在整个集群内唯一,IndexID/RowID 在表内唯一,这些 ID 都是 int64 类型。 - -每行数据按照如下规则进行编码成 Key-Value pair: - -```text -Key: tablePrefix{tableID}_recordPrefixSep{rowID} -Value: [col1, col2, col3, col4] -``` - -其中 Key 的 `tablePrefix` 和 `recordPrefixSep` 都是特定的字符串常量,用于在 KV 空间内区分其他数据。 - -对于 Index 数据,会按照如下规则编码成 Key-Value pair: - -```text -Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue -Value: rowID -``` - -Index 数据还需要考虑 Unique Index 和非 Unique Index 两种情况,对于 Unique Index,可以按照上述编码规则。但是对于非 Unique Index,通过这种编码并不能构造出唯一的 Key,因为同一个 Index 的 `tablePrefix{tableID}_indexPrefixSep{indexID}` 都一样,可能有多行数据的 `ColumnsValue` 是一样的,所以对于非 Unique Index 的编码做了一点调整: - -```text -Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue_rowID -Value: null -``` - -### 表热点 - -从 TiDB 编码规则可知,同一个表的数据会在以表 ID 开头为前缀的一个 range 中,数据的顺序按照 RowID 的值顺序排列。在表 insert 的过程中如果 RowID 的值是递增的,则插入的行只能在末端追加。当 Region 达到一定的大小之后会进行分裂,分裂之后还是只能在 range 范围的末端追加,永远只能在一个 Region 上进行 insert 操作,形成热点。 - -常见的 increment 类型自增主键就是顺序递增的,默认情况下,在主键为整数型时,会用主键值当做 RowID ,此时 RowID 为顺序递增,在大量 insert 时形成表的写入热点。 - -同时,TiDB 中 RowID 默认也按照自增的方式顺序递增,主键不为整数类型时,同样会遇到写入热点的问题。 - -### 索引热点 - -索引热点与表热点类似,常见的热点场景出现在时间顺序单调递增的字段,或者插入大量重复值的场景。 - -## 确定存在热点问题 - -性能问题不一定是热点造成的,也可能存在多个因素共同影响,在排查前需要先确认是否与热点相关。 - -- 判断写热点依据:打开监控面板 TiKV-Trouble-Shooting 中 Hot Write 面板,观察 Raftstore CPU 监控是否存在个别 TiKV 节点的指标明显高于其他节点的现象。 - -- 判断读热点依据:打开监控面板 TIKV-Details 中 Thread_CPU,查看 coprocessor cpu 有没有明显的某个 TiKV 特别高。 - -## 使用 TiDB Dashboard 定位热点表 - -[TiDB Dashboard](/dashboard/dashboard-intro.md) 中的[流量可视化](/dashboard/dashboard-key-visualizer.md)功能可帮助用户缩小热点排查范围到表级别。以下是流量可视化功能展示的一个热力图样例,该图横坐标是时间,纵坐标是各个表和索引,颜色越亮代表其流量越大。可在工具栏中切换显示读或写流量。 - - - -当图中写入流量图出现以下明亮斜线(斜向上或斜向下)时,由于写入只出现在末端,随着表 Region 数量变多,呈现出阶梯状。此时说明该表构成了写入热点: - - - -对于读热点,在热力图中一般表现为一条明亮的横线,通常是有大量访问的小表,如下图所示: - - - -将鼠标移到亮色块上,即可看到是什么表或索引具有大流量,如下图所示: - - - -## 使用 SHARD_ROW_ID_BITS 处理热点表 - -对于主键非整数或没有主键的表或者是联合主键,TiDB 会使用一个隐式的自增 RowID,大量 INSERT 时会把数据集中写入单个 Region,造成写入热点。 - -通过设置 SHARD_ROW_ID_BITS,可以把 RowID 打散写入多个不同的 Region,缓解写入热点问题。但是设置的过大会造成 RPC 请求数放大,增加 CPU 和网络开销。 - -``` -SHARD_ROW_ID_BITS = 4 表示 16 个分片\ -SHARD_ROW_ID_BITS = 6 表示 64 个分片\ -SHARD_ROW_ID_BITS = 0 表示默认值 1 个分片 -``` - -语句示例: - -```sql -CREATE TABLE:CREATE TABLE t (c int) SHARD_ROW_ID_BITS = 4; -ALTER TABLE:ALTER TABLE t SHARD_ROW_ID_BITS = 4; -``` - -`SHARD_ROW_ID_BITS` 的值可以动态修改,每次修改之后,只对新写入的数据生效。 - -对于含有 `CLUSTERED` 主键的表,TiDB 会使用表的主键作为 RowID,因为 `SHARD_ROW_ID_BITS` 会改变 RowID 生成规则,所以此时无法使用 `SHARD_ROW_ID_BITS` 选项。而对于使用 `NONCLUSTERED` 主键的表,TiDB 会使用自动分配的 64 位整数作为 RowID,此时也可以使用 `SHARD_ROW_ID_BITS` 特性。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 - -以下是两张无主键情况下使用 `SHARD_ROW_ID_BITS` 打散热点后的流量图,第一张展示了打散前的情况,第二张展示了打散后的情况。 - - - - - -从流量图可见,设置 `SHARD_ROW_ID_BITS` 后,流量热点由之前的只在一个 Region 上变得很分散。 - -## 使用 AUTO_RANDOM 处理自增主键热点表 - -使用 `AUTO_RANDOM` 处理自增主键热点表,适用于代替自增主键,解决自增主键带来的写入热点。 - -使用该功能后,将由 TiDB 生成随机分布且空间耗尽前不重复的主键,达到离散写入、打散写入热点的目的。 - -注意 TiDB 生成的主键不再是自增的主键,可使用 `LAST_INSERT_ID()` 获取上次分配的主键值。 - -将建表语句中的 `AUTO_INCREMENT` 改为 `AUTO_RANDOM` 即可使用该功能,适用于主键只需要保证唯一,不包含业务意义的场景。示例如下: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b varchar(255)); -INSERT INTO t (b) VALUES ("foo"); -SELECT * FROM t; -``` - -```sql -+------------+---+ -| a | b | -+------------+---+ -| 1073741825 | b | -+------------+---+ -``` - -{{< copyable "sql" >}} - -```sql -SELECT LAST_INSERT_ID(); -``` - -```sql -+------------------+ -| LAST_INSERT_ID() | -+------------------+ -| 1073741825 | -+------------------+ -``` - -以下是将 `AUTO_INCREMENT` 表改为 `AUTO_RANDOM` 打散热点后的流量图,第一张是 `AUTO_INCREMENT`,第二张是 `AUTO_RANDOM`。 - - - - - -由流量图可见,使用 `AUTO_RANDOM` 代替 `AUTO_INCREMENT` 能很好地打散热点。 - -更详细的说明参见 [`AUTO_RANDOM`](/auto-random.md) 文档。 - -## 小表热点的优化 - -TiDB 的 Coprocessor Cache 功能支持下推计算结果缓存。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,对于小表读热点能起到比较好的效果。 - -更详细的说明参见[下推计算结果缓存](/coprocessor-cache.md#配置)文档。 - -**其他相关资料**: - -+ [TiDB 高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md) -+ [Split Region 使用文档](/sql-statements/sql-statement-split-region.md) +--- +title: TiDB 热点问题处理 +--- + +# TiDB 热点问题处理 + +本文介绍如何定位和解决读写热点问题。 + +TiDB 作为分布式数据库,内建负载均衡机制,尽可能将业务负载均匀地分布到不同计算或存储节点上,更好地利用上整体系统资源。然而,机制不是万能的,在一些场景下仍会有部分业务负载不能被很好地分散,影响性能,形成单点的过高负载,也称为热点。 + +TiDB 提供了完整的方案用于排查、解决或规避这类热点。通过均衡负载热点,可以提升整体性能,包括提高 QPS 和降低延迟等。 + +## 常见热点场景 + +### TiDB 编码规则回顾 + +TiDB 对每个表分配一个 TableID,每一个索引都会分配一个 IndexID,每一行分配一个 RowID(默认情况下,如果表使用整数型的 Primary Key,那么会用 Primary Key 的值当做 RowID)。其中 TableID 在整个集群内唯一,IndexID/RowID 在表内唯一,这些 ID 都是 int64 类型。 + +每行数据按照如下规则进行编码成 Key-Value pair: + +```text +Key: tablePrefix{tableID}_recordPrefixSep{rowID} +Value: [col1, col2, col3, col4] +``` + +其中 Key 的 `tablePrefix` 和 `recordPrefixSep` 都是特定的字符串常量,用于在 KV 空间内区分其他数据。 + +对于 Index 数据,会按照如下规则编码成 Key-Value pair: + +```text +Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue +Value: rowID +``` + +Index 数据还需要考虑 Unique Index 和非 Unique Index 两种情况,对于 Unique Index,可以按照上述编码规则。但是对于非 Unique Index,通过这种编码并不能构造出唯一的 Key,因为同一个 Index 的 `tablePrefix{tableID}_indexPrefixSep{indexID}` 都一样,可能有多行数据的 `ColumnsValue` 是一样的,所以对于非 Unique Index 的编码做了一点调整: + +```text +Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue_rowID +Value: null +``` + +### 表热点 + +从 TiDB 编码规则可知,同一个表的数据会在以表 ID 开头为前缀的一个 range 中,数据的顺序按照 RowID 的值顺序排列。在表 insert 的过程中如果 RowID 的值是递增的,则插入的行只能在末端追加。当 Region 达到一定的大小之后会进行分裂,分裂之后还是只能在 range 范围的末端追加,永远只能在一个 Region 上进行 insert 操作,形成热点。 + +常见的 increment 类型自增主键就是顺序递增的,默认情况下,在主键为整数型时,会用主键值当做 RowID ,此时 RowID 为顺序递增,在大量 insert 时形成表的写入热点。 + +同时,TiDB 中 RowID 默认也按照自增的方式顺序递增,主键不为整数类型时,同样会遇到写入热点的问题。 + +### 索引热点 + +索引热点与表热点类似,常见的热点场景出现在时间顺序单调递增的字段,或者插入大量重复值的场景。 + +## 确定存在热点问题 + +性能问题不一定是热点造成的,也可能存在多个因素共同影响,在排查前需要先确认是否与热点相关。 + +- 判断写热点依据:打开监控面板 TiKV-Trouble-Shooting 中 Hot Write 面板,观察 Raftstore CPU 监控是否存在个别 TiKV 节点的指标明显高于其他节点的现象。 + +- 判断读热点依据:打开监控面板 TIKV-Details 中 Thread_CPU,查看 coprocessor cpu 有没有明显的某个 TiKV 特别高。 + +## 使用 TiDB Dashboard 定位热点表 + +[TiDB Dashboard](/dashboard/dashboard-intro.md) 中的[流量可视化](/dashboard/dashboard-key-visualizer.md)功能可帮助用户缩小热点排查范围到表级别。以下是流量可视化功能展示的一个热力图样例,该图横坐标是时间,纵坐标是各个表和索引,颜色越亮代表其流量越大。可在工具栏中切换显示读或写流量。 + + + +当图中写入流量图出现以下明亮斜线(斜向上或斜向下)时,由于写入只出现在末端,随着表 Region 数量变多,呈现出阶梯状。此时说明该表构成了写入热点: + + + +对于读热点,在热力图中一般表现为一条明亮的横线,通常是有大量访问的小表,如下图所示: + + + +将鼠标移到亮色块上,即可看到是什么表或索引具有大流量,如下图所示: + + + +## 使用 SHARD_ROW_ID_BITS 处理热点表 + +对于主键非整数或没有主键的表或者是联合主键,TiDB 会使用一个隐式的自增 RowID,大量 INSERT 时会把数据集中写入单个 Region,造成写入热点。 + +通过设置 SHARD_ROW_ID_BITS,可以把 RowID 打散写入多个不同的 Region,缓解写入热点问题。但是设置的过大会造成 RPC 请求数放大,增加 CPU 和网络开销。 + +``` +SHARD_ROW_ID_BITS = 4 表示 16 个分片\ +SHARD_ROW_ID_BITS = 6 表示 64 个分片\ +SHARD_ROW_ID_BITS = 0 表示默认值 1 个分片 +``` + +语句示例: + +```sql +CREATE TABLE:CREATE TABLE t (c int) SHARD_ROW_ID_BITS = 4; +ALTER TABLE:ALTER TABLE t SHARD_ROW_ID_BITS = 4; +``` + +`SHARD_ROW_ID_BITS` 的值可以动态修改,每次修改之后,只对新写入的数据生效。 + +对于含有 `CLUSTERED` 主键的表,TiDB 会使用表的主键作为 RowID,因为 `SHARD_ROW_ID_BITS` 会改变 RowID 生成规则,所以此时无法使用 `SHARD_ROW_ID_BITS` 选项。而对于使用 `NONCLUSTERED` 主键的表,TiDB 会使用自动分配的 64 位整数作为 RowID,此时也可以使用 `SHARD_ROW_ID_BITS` 特性。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。 + +以下是两张无主键情况下使用 `SHARD_ROW_ID_BITS` 打散热点后的流量图,第一张展示了打散前的情况,第二张展示了打散后的情况。 + + + + + +从流量图可见,设置 `SHARD_ROW_ID_BITS` 后,流量热点由之前的只在一个 Region 上变得很分散。 + +## 使用 AUTO_RANDOM 处理自增主键热点表 + +使用 `AUTO_RANDOM` 处理自增主键热点表,适用于代替自增主键,解决自增主键带来的写入热点。 + +使用该功能后,将由 TiDB 生成随机分布且空间耗尽前不重复的主键,达到离散写入、打散写入热点的目的。 + +注意 TiDB 生成的主键不再是自增的主键,可使用 `LAST_INSERT_ID()` 获取上次分配的主键值。 + +将建表语句中的 `AUTO_INCREMENT` 改为 `AUTO_RANDOM` 即可使用该功能,适用于主键只需要保证唯一,不包含业务意义的场景。示例如下: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b varchar(255)); +INSERT INTO t (b) VALUES ("foo"); +SELECT * FROM t; +``` + +```sql ++------------+---+ +| a | b | ++------------+---+ +| 1073741825 | b | ++------------+---+ +``` + +{{< copyable "sql" >}} + +```sql +SELECT LAST_INSERT_ID(); +``` + +```sql ++------------------+ +| LAST_INSERT_ID() | ++------------------+ +| 1073741825 | ++------------------+ +``` + +以下是将 `AUTO_INCREMENT` 表改为 `AUTO_RANDOM` 打散热点后的流量图,第一张是 `AUTO_INCREMENT`,第二张是 `AUTO_RANDOM`。 + + + + + +由流量图可见,使用 `AUTO_RANDOM` 代替 `AUTO_INCREMENT` 能很好地打散热点。 + +更详细的说明参见 [`AUTO_RANDOM`](/auto-random.md) 文档。 + +## 小表热点的优化 + +TiDB 的 Coprocessor Cache 功能支持下推计算结果缓存。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,对于小表读热点能起到比较好的效果。 + +更详细的说明参见[下推计算结果缓存](/coprocessor-cache.md#配置)文档。 + +**其他相关资料**: + ++ [TiDB 高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md) ++ [Split Region 使用文档](/sql-statements/sql-statement-split-region.md)