背景
本文旨在相对全面集中的介绍 TiDB 的新版本及其新增特性。随着产品的迭代,TiDB 持续在性能优化、易用性、安全性等方面进行升级。目标是使小伙伴们能够全面集中的理解 TiDB 新版本的优势和功能,真正享受到TiDB新版本带来的提升和便利。
由于篇幅可能较长,作者能力有限,会分成几篇文章来写。
可靠性相关
TOP SQL
官方详细文档:TiDB Dashboard Top SQL 页面
这个功能简单来说是一个快速定位,当 tidb-server 或者 tikv-server 的 cpu 或者内存使用率很高的情况下,如何定位到相关 SQL。
因为无论计算节点还是存储节点,出现资源使用率较高的情况,大概率都是 SQL 导致的。
例如,当你发现一些 tikv 的 cpu 使用率,明显高于其他节点,想知道什么 SQL 导致就可以使用相关功能。当然即使没有这个情况,也可以查看,可以自导消耗资源搞得 SQL 是哪些。
在 grafana 监控中找到对应的 tikv 节点,xxx:20180 后,去 top sql 页面选择这个节点,去查看 事情了 即可。注意选择对应时间。
统计信息自动收集关闭
在一些简单但是核心的场景,有一些用户是关闭统计信息收集,然后 SQL 加 hint 的方式固定执行计划。在 6.1 版本开始 TiDB 提供了一键关闭自动收集统计信息功能,参数为:tidb_enable_auto_analyze
TiKV 配置 region split size
对于数据量存储较多,盘比较一般、想节约成本、热数据较少的情况下。可以将默认 96MB region,改到更大。
相关参数:使用 region-split-size 调整 Region 大小
SST 文件损坏自动恢复
官方说明:background-error-recovery-window
简单来说是 TiKV 故障恢复的加强,比如当手动删除了 TiKV 底层 sst 文件等极端情况,相关 region 上报到 pd,pd 会调度删除相关 region 的副本进行自我修复。相当于一个文件损坏不会影响 TiKV 实例运行,在默认 1h 之内尝试自我修复。
Auto Analyze 最大执行时间配置
支持设置统计信息自动采集任务的最长执行时间,默认为 12 小时。避免较大表统计信息收集时间过长,影响性能问题。
Online Recover 功能
官网说明:Online Unsafe Recovery 使用文档
主要使用场景是,当 TiDB 集群丢失了半数副本以上数据的时候,TiDB 集群是不提供服务的。因为不符合 raft 协议,数据库会拒绝读写。
这个时候 TiKV 需要做 Recover 操作,对现存的 TiKV 做 Recover 操作,进行服务恢复。在低版本过程中,恢复操作相对复杂。在高版本中,相对要简单很多。一键恢复。
具体使用可以看下之前写的一篇灾难恢复的文章:7.1 版本 DRAutoSync 非计划内切换小记
谁不想有一个快速救命的方法呢。
Flashback cluster
支持通过 FLASHBACK 命令将集群快速回退到特定的时间点(实验特性)
FLASHBACK CLUSTER TO TSO 445494839813079041;
可以将集群数据恢复到未 GC 的时间节点。数据需要刷一遍,注意需要足够空间。
tidb-server 实例使用内存的阈值
新增 tidb_server_memory_limit variable 配置,一个 tidb-server 的内存使用上限,触发是会 kill 内存使用最多的 SQL 进行自救。
当前 tidb_server_memory_limit
所设的内存限制不终止以下 SQL 操作:
- DDL 操作
- 包含窗口函数和公共表表达式的 SQL 操作
根据历史执行计划创建绑定
支持绑定历史执行计划(实验特性,7.1 开始 GA ),可以使用 plan_digest 为该 SQL 语句绑定一个历史的执行计划。
这个用法针对的是复杂 SQL,执行计划跳变,然后使用手动 hint 方式很难正确干扰执行计划的情况。找到历史的正确的执行计划,使用执行计划指纹码进行绑定。
目前,根据历史执行计划创建绑定有一些限制:
- 该功能是根据历史的执行计划生成 hint 而实现的绑定,历史的执行计划来源是 Statement Summary Tables,因此在使用此功能之前需开启系统变量
tidb_enable_stmt_summary
。 - 对于带有子查询的查询、访问 TiFlash 的查询、3 张表或更多表进行 Join 的查询,目前还不支持通过历史执行计划进行绑定。
新的代价模型 Cost Model Version 2
优化器引入更精准的代价模型 Cost Model Version 2 (GA)。新版本推荐使用新模型,版本升级也可以关注tidb_cost_model_version
参数变化,在内部测试中比 Version 1 版本的代价模型更加准确。
性能相关
缓存表
官网说明:缓存表
这个功能是 TiDB 特有功能。简单来说就是可以创建一个 t 表,数据存储在 TIKV,tidb-server 会将 t 表数据全加载到内存中,当 SQL 请求访问这个表时,不会和 TIKV 交互,直接 tidb-server 内存读取。
在这个设计下:
- 缓存表不推荐有高频变更
- 缓存表有租期限制,可以认为是 tidb-server 会定时去 TIKV 拿新数据。表更新受到租期影响。
- 不推荐表过大,不然会导致 tidb-server 有较大常驻内存。
内存悲观锁
TiDB 的锁开始是乐观锁,后面引入悲观锁。在悲观锁引入早期,TiDB 对于查锁和检查锁都是磁盘上操作的,这样其实有一些性能问题。
这个优化其实就是磁盘操作放内存中操作。性能会相对提升,这个配置无需手动修改。新版本默认开启。
RC 隔离级别优化 TSO 获取开销
读已提交隔离级别 (Read Committed)用于在读写冲突较少情况下,减少不必要 TSO 获取,会尝试使用前一个有效的时间戳进行数据读取。
因为在 RC 级别下,一个事务可以看到其他事务已经提交的修改。在这个需求下,如果一个事务有 300 个 SQL,读取有 290 条,那么每个 SQL 执行的时候,其实都需要取一次 TSO,这样 tidb-server 和 pd 的交互就很多。
对此对于读写冲突不明显的场景,针对性做了优化,相关控制参数可以查看 tidb_rc_write_check_ts
相当于先根据 key 值做点查,如果 key 存在再加锁,如果不存在则直接返回空集,而不是每次都获取一次 TSO。在一些事务中读取 SQL 非常多的场景有明显性能提升
索引热点优化
相关参数:TIDB_SHARD
先说下索引热点,在我们常说的热点中,多数是读/写热点。而写热点影响最大的、常遇到的其实是数据热点。因为数据一般更宽,所以有热点的情况下,数据热点会经常成为瓶颈。
索引从编码上来说是 tableId_indeValue: handle_Id 的形式,全局有序。比如当手机号都是 1 开头的字段上创建一个索引。
索引引起的热点导致性能整体到了一个短板效应是很难得。但是遇到了其实没什么好办法。tidb_shard 这个函数其实就是索引数据封装一层 shard 函数。这个使用场景较少,限制较多,特定场景下使用。
Raft Engine 存储引擎 GA
减少至多 40% 的 TiKV I/O 写流量和 10% 的 CPU 使用。以前 tikv 每个实例有两个 rocksdb 做落盘,也就是 data 和 log。
Raft engine 新的写 log 方式。写的更快、当然对盘的压力会更高。
对于盘较差的集群,raft log 可以独立出来。
MERGE hint
引入一个优化器提示 MERGE,允许对 CTE 内联进行展开。在含有公共表表达式的查询中使用 MERGE()
hint,可关闭对当前子查询的物化过程,并将内部查询的内联展开到外部查询。该 hint 适用于非递归的公共表表达式查询,在某些场景下,使用该 hint 会比默认分配一块临时空间的语句执行效率更高。
简单来说,对应数据库运维来说,完善了一个干扰执行计划的手段。
TiFlash Fast scan 存储
TiFlash 支持新版本的存储格式,v6.2 默认支持,v6.2+ 不支持降级到早期版本。
有使用 tiflash 的用户,可以尽快升级了。会获得更快的 tiflash 体验。
Fast DDL 功能 tidb_ddl_enable_fast_reorg
TiDB 添加索引的性能约提升为原来的 10 倍 (GA)(Ingest SST directly)。读取索引数据,在 tidb-server 的 DDL owner 节点,在硬盘上生成 SST 文件,直接 import 到 tikv 中,相当于 lighting 的 local 模式导入数据。以前是逻辑读取数据编码成索引数据逻辑写入 tikv。
在实际使用中,推荐单独部署有好盘的 tidb-server,然后配置 tidb_enable_ddl
来控制 tidb-server 可以选举为 DDL owner 的节点。这样节省了资源也更好的利用了这个特性。
TiFlash 查询结果物化
支持通过 INSERT INTO SELECT 语句物化 TiFlash 查询结果(实验特性),新版本已经 GA,简单来说就是 insert into select 语句中,select 部分可以使用 tiflash engine 加速分析,分析出的结果直接 insert 写入 TiKV。
在老版本,这种语句需要手动拆解为 insert + select 两条语句来享受 tiflash 的读取加速和 MPP。
Follower Read
简单可以认为 MySQL 的读写分离(读放 slave,写放 master)。减少热点影响。在跨机房多活读取也是很好的适用场景。
当系统中存在读取热点 Region 导致 leader 资源紧张成为整个系统读取瓶颈时,启用 Follower Read 功能可明显降低 leader 的负担,并且通过在多个 follower 之间均衡负载,显著地提升整体系统的吞吐能力
使用 closest-adaptive 更智能的为用户节约跨 zone 流量(Follower Read)in a real case, reduce 30%+ cross-az traffic。
Index Merge
索引合并(Index Merge),自动合并各列的索引以满足 AND 或 OR 组合的过滤条件,实现与复合索引相近的性能(新增支持 AND 条件)
分布式框架相关
TiFlash MPP 引擎支持分区表的动态裁剪模式
官网说明:动态裁剪模式
动态裁剪(Dynamic Pruning)是一种性能优化技术,特别是在处理分区表时。当查询涉及到分区表时,动态裁剪模式能够在运行时根据查询的条件动态地选择只访问相关的分区,从而避免全表扫描,减少I/O操作,提高查询效率。
这里注意下,修改动态裁剪相关参数后,手动收集下表的统计信息。
支持全局 kill 查询或连接
新增 enable-global-kill config 配置,在 6.1.0 版本之前,如果需要 kill SQL 是需要去对应 tidb-server 节点,在新版本中,默认开启支持全局 kill 查询或连接,增加运维易用性。
SQL 相关
支持 join order hint 语法
LEADING hint,STRAIGHT_JOIN hint 两种新的 hint 方式。
简单来说,就是在低版本,我们对于 SQL 执行计划不是最优,例如 join 顺序有一些问题,那么就可以单独使用这两个新 hint 来干扰关联顺序。
TiDB 支持 MySQL 5.7 中的大部分用户级锁函数
支持兼容 MySQL 的用户级别锁管理,支持 GET_LOCK、RELEASE_LOCK、RELEASE_ALL_LOCKS 函数
支持增删改多个列或索引
TiDB 支持使用一个 ALTER TABLE 语句增删改多个列或索引。
事务中支持 SAVEPOINT
v6.2.0 开始支持的特性,和 MySQL 用法基本类似。
需要注意点只有SAVEPOINT
特性不支持与 TiDB Binlog 一起使用,也不支持在关闭 tidb_constraint_check_in_place_pessimistic
的悲观事务中使用。
单调递增列优化
支持高性能、全局单调递增的 AUTO_INCREMENT 列属性。
TiDB 早期为了增加数据库的吞吐能力,对于自增列,每个 tidb-server 都是缓存一部分,然后本地分配。这样就导致 AUTO_INCREMENT 列只保证唯一,有后写入的数据数值比先写入的小的情况。
对于 v6.4.0 及以上版本,由于引入了中心化的分配服务,AUTO_INCREMENT 值的修改只是在 TiDB 服务进程中的一个内存操作,相较于之前版本更快。
要注意的是:当前能大部分情况下是保证 ID 唯一、单调递增,行为几乎跟 MySQL 完全一致。即使跨 TiDB 实例访问,ID 也不会出现回退。只有当中心化服务的“主” TiDB 实例异常崩溃时,才有可能造成少量 ID 不连续。这是因为主备切换时,“备” 节点需要丢弃一部分之前的“主” 节点可能已经分配的 ID,以保证 ID 不出现重复。
易用性
Placement Rules in SQL
使用 SQL 配置表的存储规则,比如 A 表所有数据放置机房 1,B 表所有数据放置机房 2 类似这种需求。
这里提醒下,需要使用较新版本,支持 SURVIVAL_PREFERENCE。这个属性会影响在规则下的数据存放容灾等级的优先级放置。如果没有这个属性,在容灾等级上可能会有问题。
在线修改集群配置
TiDB/TiKV/TiFlash 参数支持在线修改,无需重启,即可生效。需要注意的是在线修改 TiKV 配置项后,同时会自动修改 TiKV 的配置文件。但还需要使用 tiup edit-config
命令来修改对应的配置项,否则 upgrade
和 reload
等运维操作会将在线修改配置后的结果覆盖。
修改中控机信息后,可以刷一遍配置(并不重启进程):
tiup cluster reload <cluster-name> --skip-restart
TiDB Dashboard 监控页面
TiDB Dashboard 新增 Monitoring 页面,展示在业务性能调优中所需的核心指标。
这样在日常运维中,多数情况下就无需再开启 grafana,看更细致得监控指标,这里就可以看到常用的监控指标来分析集群当前状态。减少以前跳来跳去的烦恼。
图形化执行计划
TiDB Dashboard 支持图形化执行计划,更快理解复杂的大型查询语句
DATA_LOCK_WAITS 视图表
锁视图支持乐观事务被阻塞的信息, 查看锁冲突的关系。DATA_LOCK_WAITS
表展示了集群中所有 TiKV 节点上当前正在发生的等锁情况,包括悲观锁的等锁情况和乐观事务被阻塞的信息。
使用 TTL (Time to Live) 定期删除过期数据
可以使用 TTL (Time to Live) 来周期性地删除过期数据,用法举例:
- 使用
DEFAULT CURRENT_TIMESTAMP
来指定某一列的默认值为该行的创建时间,并用这一列作为 TTL 的时间列,创建时间超过 3 个月的数据将被标记为过期:
CREATE TABLE t1 (
id int PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TTL = created_at + INTERVAL 3 MONTH;
对于有数据定期回收需求的表,可以不用再外挂删除脚本或者创建分区表来清理了。直接使用 TTL 功能,配置表属性。数据库后台直接删除相关数据。
该功能已经 GA,可以直接使用。监控中有相关监控,监控其性能。有 tidb_ttl_scan_worker_count
和 tidb_ttl_delete_worker_count
参数来控制删除并行和读取并行。并且可以配置全局变量 tidb_ttl_job_schedule_window_start_time
和 tidb_ttl_job_schedule_window_end_time
来指定时间窗口进行数据回收。