你这个场景:
1、默认tidb_distsql_scan_concurrency=15,极端情况下会缓存15个region。
2、decimal、tinyint等字段都存在内存放大问题,尤其decimal(40个字节)如果字段特别多的话可能会导致占用太多的内存。
3、tidb_enable_rate_limit_action=ON,该版本默认开启限流,会优先限流导致tidb缓存太多数据,没有及时触发cancel等oom-action动作。
4、假设你这个pushsubscribe是一个视图,里面存在union all等,那么会被放大,默认最多5倍(受tidb_executor_concurrency参数影响),即5 * 15个region。
5、如果前端开启了cursor fetch游标读等会导致读读较慢,tidb后侧数据积压较多,如果前端获取数据更快那么后端更不容易积压数据,因此采用官方建议的流式更佳。
优化方法,在session级别设置:
1、set tidb_distsql_scan_concurrency=2; 缓存更少的region数据,同时保持性能
2、set tidb_enable_rate_limit_action=OFF; 保证内存尽量不会超出tidb_mem_quota_query,减少tidb-server oom风险。
3、检查region,是否存在大region,尽量做splitRegion操作。
4、set tidb_enable_chunk_rpc=OFF;关闭 chunk_rpc减少内存放大问题。
更推荐升级到6.5版本,通过paging代替整个region的数据返回,减少了语句OOM的风险。
在6.5版本paging默认是开启的:
mysql> show variables like '%paging%';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| tidb_enable_paging | ON |
| tidb_max_paging_size | 50000 |
| tidb_min_paging_size | 128 |
+----------------------+-------+
3 rows in set (0.00 sec)