一般sql返回4013由以下几个原因触发:
1.内存泄漏,某个模块内存申请过大,其他模块申请不出内存了;
可以select * from __all_virtual_memory_info order by hold desc limit 20;看看有没有内存占用异常大的模块;
2.work area配比设的太小;
show variables like '%ob_sql_work_area_percentage%';
ob_sql_work_area_percentage默认值是5,即使用租户内存的5%,对于大sql可能不够,如果建议调成20后再执行sql看看;
3.误用了4013的错误码(误用的情况出现的概率比较小),一般通过排查日志判断;
4.sql执行过程中申请了过大的内存
sql执行过程中申请的内存sql执行完就释放了,这类问题只能通过日志排查;
通过日志排查ob内存问题的方法,可以参考https://open.oceanbase.com/docs/community/oceanbase-database/V3.1.0/sgco3g
具体:
grep ret=-4013 observer.log找到traceid,再根据traceid看最开始报分配不出内存的地方;
ex
[2021-12-15 11:09:10.295485] WARN alloc (ob_allocator_v2.cpp:51) [2887][1913][YB42AC14027E-0005D2B3AD6A5BD8] [lt=3] [dc=0] oops, alloc failed, tenant_id=1001, ctx_id=29, ctx_name=QUERY_EXEC_CTX_ID, ctx_hold=78966161408, ctx_limit=9223372036854775807, tenant_hold=81604378624, tenant_limit=81604378624
从这条日志看租户的内存的确被占满了,而 __all_virtual_memory_info又没看到内存占用特别大的模块,很可能是sql执行过程中申请了过大的内存;
可以搜索 grep MEMORY observer.log查看特定租户下的内存占用;
[2021-12-15 11:09:00.349386] INFO [LIB] ob_tenant_ctx_allocator.cpp:148 [1894][2][Y0-0000000000000000] [lt=2] [dc=0]
[MEMORY] tenant_id= 1001 ctx_id= QUERY_EXEC_CTX_ID hold= 73,096,232,960 used= 69,972,802,928
[MEMORY] hold= 71,065,629,728 used= 69,972,773,232 count= 1,059,210 avg_used= 66,061 mod=QueryExecCtx
sql执行中占用了太多的内存,咨询得知报错的sql一次涉及8000w行,而ob开源版本当前没有对multi part insert没做落盘,下面这条涉及8000w行的sql申请了近70G的内存是符合当前的设计的;
insert /*+ parallel(8)*/ into ifi_ipc_one
select t.id,t.date_produce,t.patenttype,t.pd,t.ipc,t.ti,t.ab_new abs_new,t.patentid from ifi_ipc t
where t.ipc is not null
and t.id not like 'CN%'
and t.pd between 19600101 and 20291231;
可以通过pdml来规避问题,pdml会流式的做dml,只缓存少量数据
insert /+ enable_parallel_dml parallel(4)*/ into ifi_ipc_one
select t.id,t.date_produce,t.patenttype,t.pd,t.ipc,t.ti,t.ab_new abs_new,t.patentid from ifi_ipc t
where t.ipc is not null
and t.id not like 'CN%'
and t.pd between 19600101 and 20291231;