https://tidb.net/blog/c9466c40#TiDB%E7%B3%BB%E7%BB%9F%E8%B0%83%E5%8F%82%E5%AE%9E%E6%88%98%E7%BB%8F%E9%AA%8C/%E5%9B%9B%E3%80%81%E6%80%BB%E7%BB%93
这次跟大家分享关于tidb软硬件调参方面的经验。
作为一名开源爱好者,go 语言开发者,笔者接触 TiDB 主要关注其对 MySQL 的高度兼容特性,分布式一致性保障等技术性的特点。得益于完善的生态工具支持,普通开发者想要体验 TiDB 十分容易。只需要使用 tiup playground 就可以迅速在本机启动一个仅供本机访问的TiDB集群。再或者恰好你有几台闲置的主机。编写好 deploy 文件。使用 tiup 一键发布也可以搭建起一个稍微正式的 TiDB 集群。但是笔者之前一直从未体验到一些不起眼的参数或者是系统设置会对 TiDB 系统的性能,稳定性造成如此大的影响。这些影响在实际大型项目中被数以十亿计的数据压力放大,从而影响到业务系统。笔者在解决这些问题中也积累了一点经验。遂记录一些要点与大家分享。
在 TiDB 实际生产落地时,检查硬件环境漏掉了 ntp 同步。马马虎虎地就把集群给启动起来并接入业务数据。之后查看监控所有面板都没有数据。
之后进行了长达 4 小时的排查过程。查监控组件日志,查系统日志等等,期间还重启了一次集群。都没有解决问题。在百思不得其解之际,笔者将 grafana 的监控时间选项调整为 “Last 7 days”。然后就看到面板上有数据,但是落后很长一段时间。遂检查集群中每个主机的时间。发现集群中主机时间不一致,都或多或少落后于标准时间。后续通过配置 ntp,指向统一的 ntp 服务器。之后 grafana 恢复正常,所有面板数据都能正常显示。
这一点主要在备份性能要求高时可能遇到,在使用 TiDB 的备份还原生态工具时,当备份程序打开文件数超过系统限制时,将中断备份还原操作。主要修改以下配置。
vi /etc/sysctl.conf
net.ipv4.tcp_tw_recycle: 0
net.ipv4.tcp_syncookies: 0
net.core.somaxconn: 32768
vm.swappiness: 0
vm.overcommit_memory: 0 or 1
fs.file-max: 1000000
vi /etc/security/limits.conf
<tidb-user> soft nofile 1000000
<tidb-user> hard nofile 1000000
<tidb-user> soft stack 32768
<tidb-user> hard stack 32768
其中<tidb-user>为发布集群时,设置的tidb用户
这一点可能会犯两个错,第一时忘记修改了这些配置,导致进行高速备份还原时,发生超出系统读取文件限制而中断。
另外一点就是即使配置了这些参数,调大了系统读取文件限制。但是没有用 tidb 的用户去操作备份还原工具,比如 br、dumpling、lightning,同样会报读取文件数超出限制。笔者就是在这里犯了错。发布时配置文件中写的用户是 tidb。备份还原使用的是 root 用户。
单条 SQL 语句可以占用的最大内存阈值,单位为字节。
官网文档:https://docs.pingcap.com/zh/tidb/stable/tidb-configuration-file#mem-quota-query
这个配置值默认为1GB,当一条查询语句超过这个值就会触发OOM,导致查询失败。我们在日常使用过程中可能不会遇到这个限制。但是当数据量达到亿级以上,sql语句中嵌套join等复杂情况时,就可能发生OOM。
与其对应的系统变量是 tidb_mem_quota_query
官网文档:https://docs.pingcap.com/zh/tidb/stable/system-variables#tidb_mem_quota_query
这是一个 SESSION 级别的变量,只对当前会话有效。对于因为默认 mem-quota-query 阈值太小而发生OOM的情况。可以先设置会话级别的变量 tidb_mem_quota_query
TiDB 单个事务大小限制,默认大小 100M。
https://docs.pingcap.com/zh/tidb/stable/tidb-configuration-file#txn-total-size-limit
笔者在进行亿级大表更新时,发生了事务超出最大限制错误。原因是集群还部署了 binlog,当发生大表更新时,binlog 组件 pump 将抓取这个时间段的 binlog,并保证事务性。但是事务默认最大值是 100M,更新亿级大表的事务远大于 100M,遂发生报错。
可以根据实际业务情况,修改该配置值。但是最大不能超过10GB。
在对一张表进行大批量导入数据操作时,将会导致热点问题。这是由于 TiDB 新建一个表后,默认单独切分出一个 Region 来存储这个表的数据,等这个region数据超过 Region 默认大小限制后才会分裂成2个 Region。这样在大批量写入一个新表时,不仅所有的写入流量都集中在一个 Region,并且期间 Region分裂也需要时间调度。所以最佳的实践就是在大批量操作之前为表切分出更多 Region。这样写入流量就不会受region数量过少的限制。
例如将一个表切分16个region:
SPLIT TABLE t BETWEEN (0) AND (9223372036854775807) REGIONS 16;
对于非整数主键或没有主键的表,TiDB 会使用一个隐式的自增 rowid。大量执行 INSERT 插入语句时会把数据集中写入单个 Region,造成写入热点。
通过设置 SHARD_ROW_ID_BITS 可以把 rowid 打散写入到多个不同的 Region 中,以及缓解写入热点问题。但是也不能设置过大,过大会导致RPC请求数偏大,增加系统负载压力。
例如,将一个表分4片:
CREATE TABLE: CREATE TABLE t (c int) SHARD_ROW_ID_BITS = 4;
ALTER TABLE: ALTER TABLE t SHARD_ROW_ID_BITS = 4;
调整分片数量需要根据实际表大小和业务情况酌情考虑,在笔者实际运维工作中,发现一张8亿大表出现写热点后,执行分片处理,分成3片就可以有效缓解写入热点问题了。
统计更新用于更新 TiDB 在表和索引上留下的统计信息。执行大批量更新或导入记录后,或查询执行计划不是最佳时就需要执行统计更新操作。
默认的统计更新速度比较慢,可以通过调整参数的方式大大加快统计更新的速度。
set session tidb_build_stats_concurrency=30;
set session tidb_distsql_scan_concurrency=30;
set session tidb_index_serial_scan_concurrency=2;
在 TiDB 数据迁移操作过程中经常会采取先迁移数据到目标库,然后在目标库上还原原本的索引。建立索引的速度可以通过调整两个参数来加快。
set global tidb_ddl_reorg_worker_cnt = 30
set global tidb_ddl_reorg_batch_size = 30
建立索引将占用大量的系统 I/O 资源,需要按经验适当调整参数来加快但不至于影响系统正常运行。
在实际的 TiDB 实施工作中,客户往往会提出一些性能或者功能上的要求。TiDB 要求的硬件很高,无论是 CPU 核数,内存,硬盘,网卡等。TiDB 常规默认的配置旨在维护系统正常运行,要释放出 TiDB 较高的性能,需要合理调整参数,提高使用 TiDB 的效率。
另外,除了对 TiDB 实践项目应用适配的工作,笔者也在为 TiDB 相关仓库贡献代码。