黄东旭解析 TiDB 的核心优势
685
2023-11-24
大家可能经历过这样一个场景,在某个正在熟睡的凌晨突然收到告警电话有 tidb-server 节点频繁重启,可能还伴随有内存告警,然后赶紧起来排查确认。上线一看发现不少节点出现了 OOM ,类似上图,在找到对应的 SQL 和业务一确认后,确定是凌晨偷偷新上的统计任务导致了这次的问题,赶紧让业务先停掉完,告知业务完成优化且经过 DBA 确认后再另外排期上线,之后骂骂咧咧的再次滚回被窝去。这个案例起码至少说明了几个问题:
开发能力和开发规范遵循问题
上线流程控制问题
数据库自身资源管控问题
在问题出现后数据库管理员总结排查方法,还可以针对性的做好开发手册指引和培训工作。
而我们在 TiDB 的使用过程中,尤其是访问大量数据的分析型业务场景,很难不会遇到 OOM 的问题。OOM 的问题一旦出现,集群必然会受到影响,所以,这就要求我们能够以尽快的速度完成排查和处理。本文这里总结一些日常管理 TiDB 集群的经验,方便后面遇到类似问题时可以作为一个排查思路和操作指引,协助快速处理 OOM 问题。
有收到内存告警、节点卡住或重启的情况,我们可以在脑海中有个初判会不会是 OOM 问题。TiDB 集群 OOM 通常出现在 tidb-server 节点上,也有少数情况出现在 tikv-server 节点。大致可以先通过下面的分析流程进行排查,确认是不是 OOM 的问题。
如上图所示,我们遇到问题后可以有下面的分析来确认是不是具体组件出现了 OOM 。
是不是 tidb server OOM 问题
业务侧、用户端:
部分访问有明显延迟
部分业务有lost connection 的报错
grafana监控:
uptime出现掉线重启
Overview->TiDB->Memory Usage 出现高峰急剧掉线重启
tidb server日志:
tidb.log 在问题时段出现Welcome 重启关键字
tidb_stderr.log有oom或can not allocate memory关键字
系统日志
tidb server节点系统日志 dmesg -T| grep tidb-server 在问题时段附近有OOM Killer出现
(图片来源https://tidb.net/blog/de9bf174)
是不是 tikv server OOM 问题
业务侧、用户端:
集群访问延迟有突增
业务QPS有明显抖动
grafana监控
tikv detail->cluster->uptime出现掉线重启
tikv detail->cluster->memory面板看到有tikv实例的内存剧烈上升后突然掉零再慢慢增加,可判断为tikv OOM重启了
tikv server日志
排查tikv.log日志,在问题时段附近有Welcome实例重启标记
系统日志
dmesg -T| grep tikv-server在问题时段有OOM-killer日志
当遇到OOM的问题之后,排查触发原因时,大致可以分为两类原因:
数据库原因导致的 OOM
非数据库原因导致的OOM
数据库本身导致的 OOM 问题,通常是统计信息不准确导致执行计划问题、集群配置参数使用不当等引起情况。非数据库原因导致的 OOM 问题,通常可以归类为硬件资源不足、混合部署等原因,比如其他应用进程抢占了过多的内存资源导致 TiDB 被系统的 oom-killer 直接干掉。
针对不同的 OOM 触发根因,我们会有不同的处理策略。
机器内存不足
确认部署 tidb server 的机器操作系统内存是否太少,导致内存不足。开发及测试环境建议值是16 GB+,生产环境建议值是48 GB+。
https://docs.pingcap.com/zh/tidb/v7.4/hardware-and-software-requirements
集群混部问题
排查是不是部署过多的实例节点,如果节点个数太多也容易引起 OOM。生成环境下内存 128 GB 的机器,通常建议部署 2 个 tidb server 节点就够了。可以考虑通过增加cgroup策略来进行资源划分。
排查tidb server 是不是和 tikv server 混合部署,如果是也有可能会有内存相互挤兑从而触发问题。可以考虑通过增加cgroup策略来进行资源划分。
确认是否有业务进程混合部署,导致内存资源挤兑。应该专机专用,不部署业务程序。
数据库原因如果发现内存正在上涨还没有出现 OOM 但是也有 OOM 的风险,可以根据下面的方式获取相关信息来分析:
查看当前链接的内存使用情况
执行 SELECT * FROM information_schema.processlist; 查看 SQL 对应的 MEM 列的值,定位到使用内存最多的语句。
执行以下命令收集内存使用率高的 tidb server 的 Profile 信息
curl -G http://{TiDBIP}:10080/debug/zip?seconds=10" > tidb_server_profile.zip
原因判断和处理:
问题 SQL 定位
获取可能的问题 SQL,可以查看 INFORMATION_SCHEMA 中的 SLOW_QUERY 和 CLUSTER_SLOW_QUERY 。
也可以通过 tidb dashboard的 慢SQL和 SQL语句找到问题附近的 SQL并分析,定位到具体的问题 SQL,从 SQL 语句分析、慢查询的具体内容,可以详细查看内存使用量。
同时 grep expensive_query tidb.log 辅助定位问题时间点的 SQL 情况。
如果确认是 SQL 的执行计划有问题,如缺少合适索引、统计信息过期、优化器 bug 等原因,很可能会导致选错执行计划而导致大量中间结果数据累积在内存,出现 OOM。
可以添加合适索引、使用 analyze 重新收集统计信息等措施进行处理。
如果确认 OOM 时是系统在收集和加载统计信息的过程中消耗太多内存。
可以指定采样率、指定只收集特定列的统计信息、减少 ANALYZE 并发度等方式减少内存使用。
v6.1.0 以后引入了系统变量 tidb_stats_cache_mem_quota对统计信息的内存使用进行限制,引入了系统变量 tidb_mem_quota_analyze控制 TiDB 更新统计信息时的最大总内存占用。
如果OOM 问题发生时间附近,tidb session 的并发度过高或者某些节点的连接数过多。
需要扩容或优化负载均衡策略。
查看执行计划,如果发现存在算子 HashAgg 处理大量数据。
HashAgg 是多线程并发执行,虽然执行速度较快,但会消耗较多内存,可以尝试使用 STREAM_AGG() 替代。
如果出现 OOM 问题时段附近,业务访问有大事务或大写入,导致消耗太多内存。
tidb server 在执行事务时 TiDB 进程的内存消耗相对于事务大小会存在一定程度的放大,最大可能达到提交事务大小的 2 到 3 倍以上。
所以针对单个大事务,可以通过拆分的方式调小事务,可能需要和业务沟通调整程序。
排查和调整 tidb server 的配置参数
设置单条 SQL 使用的内存上限。
可以调整 session 级别参数 tidb_memory_quota_query 参数限制单条SQL语句的内存使用量,默认值为 1GB。
设置单个 tidb-server 节点使用的内存上限。
v6.5.0以后可以通过系统变量 tidb_server_memory_limit 设置 tidb-server 实例的内存使用阈值,默认为总内存的80%。
TiDB 会在内存用量达到该限制时对当前内存用量最高的 SQL 语句 Cancel,然后会尝试调用 Golang GC 立刻回收内存,以最快速度缓解内存压力。
一次只能 Cancel 一条 SQL 语句。如果 TiDB 完全 Cancel 掉一条 SQL 语句并回收资源后,内存使用仍然大于该变量所设限制,TiDB 会开始下一次 Cancel 操作。被强制终止的 SQL 操作会向客户端返回报错信息 Out Of Memory Quota!。
使用系统变量 tidb_mem_oom_action 来控制单条查询超过内存限制后所采取的操作是 CANCEL 还是 LOG。
CANCEL 则会中断查询并打印相关日志。
LOG 则不会中断查询,仅仅记录相关内存使用信息。
设置数据落盘
HashAgg 落盘功能目前不支持 distinct 聚合函数。使用 distinct 函数且内存占用过大时,无法进行落盘。
当 SQL 的内存使用超过 Memory Quota 时,tidb-server 可以通过落盘执行算子的中间数据,缓解内存压力。可以启用临时磁盘 oom_tmp_storage ,指定路径tmp_storage_path 和使用外部磁盘的空间上限tmp_storage_size。
当包含 HashAgg 算子的 SQL 语句引起内存 OOM 时,TiDB 默认不触发落盘,可以通过设置系统变量 tidb_executor_concurrency = 1 来触发 HashAgg 落盘的功能。
机器内存不足
确认部署 tikv server 的机器操作系统内存是否太少,导致内存不足。开发及测试环境建议值是32 GB+,生产环境建议值是 64 GB+。
https://docs.pingcap.com/zh/tidb/v7.4/hardware-and-software-requirements
集群混部问题
排查是不是部署过多的实例节点,如果节点个数太多也容易引起 OOM。可以考虑通过增加cgroup策略来进行资源划分。
排查 tikv server 是不是和 tidb server 混合部署,如果是也有可能会有内存相互挤兑从而触发 OOM 问题。可以考虑通过增加cgroup策略来进行资源划分。
确认是否有业务进程混合部署,导致内存资源挤兑。其他进程占用过多内存,也可能会导致系统误杀 tikv 进程。应该专机专用,不部署业务程序。
数据库原因排查 block cache 参数配置是否合理。通过查看 TiKV Detail -> RocksDB KV -> Block cache size 面板查看内存使用变化。
如果是block cache的问题,则合理调整storage.block-cache.capacity参数大小,默认为系统内存的45%,通常可以设置范围为45%-60%,配置过高导致容易OOM。如果是多个节点同时部署的时候,尤其要注意该参数的配置,可以设置 storage.block-cache.capacity = (MEM_TOTAL * 0.5 / TiKV 实例数量)。
https://docs.pingcap.com/zh/tidb/stable/hybrid-deployment-topology
在 v6 以后的版本支持在MySQL终端在线修改该参数set config tikv xxxx=xxxx (推荐);或者tiup cluster edit-confg xx 编辑修改再reload重启tikv实例。
确认是否因为读取大量数据导致 OOM 。查看 tikv details 的copprocessor 面板,以及查看 node-exporter的network面板查看 gRPC的网络传输量,确认是不是远远小于copprocessor读取的数据量。
如果是 copprocessor 读取大量数据而gRPC来不及消费传送到TiDB server,说明有大 SQL 出现导致 copprocessor 读取大量数据到 tikv 的 block cache 中而 gRPC 来不及消费传送到 tidb,会导致数据堆积过多而 OOM。此时可以采取下面的处理措施:
优化SQL使得一次性不读取大量数据。
如果机器使用的是千兆网卡,则建议升级为万兆网卡。
对于 TiKV OOM 的分析,社区里 h5n1 大佬的这篇文章也非常推荐阅读 https://tidb.net/blog/ab528ebf 。
TiDB 出现 OOM 问题,最频繁的节点是在 tidb server 中,而引起问题的最多原因是因为大 SQL 或执行计划不准。
而 tikv 出现 OOM 的问题,大多数是因为 block cache 配置问题引起,在部署和排查时可以重点关注该方面问题。
我们在日常运维管理工作中,针对这些场景有一定的提前规划和准备,即可从容应对大部分的 OOM 问题。
社区也有不少很不错的 OOM 排查实践案例,在遇到问题时可以一并参考。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。