数据库管理 2023-06-20
- 第八十三期 抄点冷饭
- 1 ORA-04031
- 2 Shared Pool
- 3 Library Cache
- 4 Doc ID 2590172.1
- 5 Bug 34832725
- 总结
第八十三期 抄点冷饭
上周,借着剩余的两天年假,又从300多个小时中拿了3天出来,加上前后两个周末,去泰国完了一圈,整体还是很爽的,这里分享一些照片,具体游记后面详见公众号:
1 ORA-04031
ORA-04031: unable to allocate xx bytes of shared memory(“xxx”,“xxx”,“xxx”,“xxx”),是一个Oracle数据库中比较典型的报错,从报错的字面意思就能很好理解,数据库语句执行无法从SGA的shared pool中获取需要的内存,大多数情况只会偶发出现(毕竟硬件资源是有限的);但是我也遇到过一直触发,语句无法执行的情况,这一般就涉及BUG、配置错误等原因了。
2 Shared Pool
只要是影响语句的报错,我们都应该尽量避免出现,毕竟你不知道那些开发有没有做好失败重试机制,更有甚者一个报错会拖垮整个应用。但从4031这个报错来看,就需要回过头看看Shared Pool到底是用来干什么的:
首先Shared Pool是SGA中的一个组成部分,无论是基于自动管理还是手动管理,在SGA中都需要考虑与其他组件之间的关系,尤其是与Buffer Cache之间的关系(毕竟更多的数据刷到内存性能相对更好)。
- Library Cache
是一种共享内存结构,用于存放可执行的SQL和PL/SQL代码。简单点来说,SQL执行的时候会尝试使用以前执行过的信息,诸如已解析的SQL、SQL执行计划、解析过和编译过的PL/SQL程序单元等信息就存放在这里。 - Data Dictionary Cache
是存放数据库元数据的地方,比如表或视图的结构和用户信息。 - Server Result Cache
用于存放SQL执行结果和PL/SQL函数结果缓存。
其他Shared Pool中的组件就不太重要了。在Shared Pool中其实Library Cache往往是占用内存空间最大的地方,那么控制Library Cache大小就是减少出现4031的重要手段。
3 Library Cache
无论是Shared SQL Area还是Private SQL Area,里面存放的都是已解析的SQL、SQL执行计划、解析过和编译过的PL/SQL程序单元等信息。减少Library Cache中记录的SQL信息就可以极大减少内存空间占用,从一般优化建议来看就是使用绑定变量来减少:
SQL1:
select * from daily_sales where shipped_from='WAREHOUSE1';
SQL2:
select * from daily_sales where shipped_from='WAREHOUSE2';
SQL3:
select * from daily_sales where shipped_from=:A;
对于数据库来说,SQL1和SQL2不是一条语句,在Library Cache用会生成两条SQL信息,且不同语句之间无法复用执行计划会产生硬解析,这样不仅增大了内存占用,也增加了内存消耗。如果将shipped_from的匹配内容像SQL3那样传入变量A中,那么在Library Cache中就只会生成一条信息,也可以很方便的复用执行计划。
当然还有一些看似完全一样的操作也会增加占用:
SQL4:
create table x1 (id number,name varchar2(20));
drop table x2 [purge];
SQL5:
create table x1 (id number,name varchar2(20));
SQL4和SQL5语句完全一样,但是因为对应表的object_id产生了变化,在Library Cache中也会生成不同version的信息,增加占用。我这里处理过的一个业务就是因为每天大量的此类操作,导致自动管理的SGA,总计120GB,db cache被shared pool积压到了不足5GB,要不是因为是Exadata,可能早卡崩了。
4 Doc ID 2590172.1
ORA-04031 on Multitenant Database with Excessive Amounts of KGLH0 and / or SQLA Memory and Parameter SHARED_POOL_SIZE or SGA_MIN_SIZE Set at the PDB Level
在第二十二期的时候我是遇到过这个问题的,莫名其妙报4031,就是因为在PDB内设置了shared_pool_size和sga_min_size,遇到了只能通过下面命令处理:
alter system flush shared_pool;
由于PDB只有2个,后面就通过在CDB层面控制db_cache_size和shared_pool_size处理该问题。
5 Bug 34832725
[SHRD CRSRS] ORA-4031 and / or High Shared Pool Latch Contention During Session Creation in 19.11 and Above
这也是一个经常出发4031的一个BUG,之前在一个省的一体机上的19.17触发了并且查了很久,我这里的19.16和19.17上并没有触发,从后台反馈来看主要涉及19.15和19.17两个版本。现在的处理方法要么是flush shared_pool,要么打one-off patch和升级到19.18、19.19的修复版本或19.20。
总结
休假回来整体浑浑噩噩的,这一期实际上还算是炒第二十二期的冷饭。
老规矩,知道写了些啥。