这句话说的不太清楚,只有2个算子还是2个token?
是否可以理解为你的疑问是:
为何不在remain token count最多的时候canel掉语句(毕竟这个时候占用内存可能是最多的),而是在最后一个的时候cancel掉语句?
如果是这个问题,那么我理解是这样的:
首先oomAction行为是有优先级的,cancel、log、rateLimit越来越高。在你这个设置中同时具有tidb_mem_oom_action=CANCEL 和 tidb_enable_rate_limit_action=ON,那么会先触发优先级高的行为,也就是先触发rateLimit行为,这个行为是为distsql做流控(一个distsql只作用于一个表上),当最后被流控到可以获得的token 只有1个的时候会fallback到次优先级的oomAction上,也就是你这里设置的cancel。所以在remain token limit=1的时候如果评估此时整个语句占用内存还是比tidb_mem_quota_query大,那么会cancel掉当前这个语句。此时虽然token 只剩下1个,也就是去做copTask的并发执行数只能是1了,但是如果之前获取到的copTask还没有被消费完那么内存还是不会释放,也就是内存占用会超过tidb_mem_quota_query的设置值。
关于第二个SQL为何有这样的表现,我理解的是:
在通常情况下(没有包含很大的region),开启了chunk_rpc,那么一个region在tidb侧的大小大约300左右的MB空间。如果只有2个copTask的response通常情况下是不会导致语句OOM的,但是你这个SQL语句时join,要看join的行为是什么,可能是join占用了较多内存,还有就是这里的total token count只是一张表的,另一张的没有体现出来,最好看下explain analyze ,看内存时怎么消耗的。
另外,在实际执行中表的并发扫描不一定完全依赖tidb_distsql_scan_concurrency 这个参数,这个参数值通用情况下最大表扫描的并发数。如果需要扫描的region数量少于tidb_distsql_scan_concurrency 设置的值,那么就不会用这么多。还有,如果对于有序的数据请求,扫描并发数也不会这么多(固定为2,避免tidb侧缓存太多数据等待有序执行导致增加oom概率)。