
🔍 ORA-00387错误全面解析
错误信息结构说明
官方格式:
ORA-00387: Too many buffer pools specified
错误信息组成:
- 错误代码:ORA-00387(固定标识)
- 错误描述:Too many buffer pools specified
- 含义:指定的缓冲池过多
错误原因深度解析
根本原因
ORA-00387错误发生在尝试创建或配置超过Oracle数据库支持的缓冲池数量限制时。Oracle对不同类型的缓冲池数量有明确的限制。
具体原因分析
-
缓冲池数量超限
- 尝试创建超过Oracle允许的最大缓冲池数量
- 标准缓冲池(DEFAULT、KEEP、RECYCLE)配置冲突
-
多块大小配置错误
- 为不同的块大小配置过多缓冲池
- 非标准块大小缓冲池配置超出限制
-
参数配置冲突
- 在初始化参数中指定了冲突的缓冲池配置
- 动态修改缓冲池时超出系统限制
发生场景与相关原理
典型发生场景
-
初始化参数配置
-- 在参数文件中配置过多缓冲池 db_cache_size = 1024M db_keep_cache_size = 256M db_recycle_cache_size = 128M db_2k_cache_size = 64M db_4k_cache_size = 64M db_8k_cache_size = 64M db_16k_cache_size = 64M db_32k_cache_size = 64M -- 可能超出某些版本的限制 -
动态缓冲池创建
-- 尝试动态创建过多缓冲池 ALTER SYSTEM SET db_16k_cache_size = 64M; ALTER SYSTEM SET db_32k_cache_size = 64M; -- 在已经存在多个缓冲池的基础上继续添加 -
数据库创建过程
-- 在CREATE DATABASE语句中指定过多缓冲池参数 CREATE DATABASE mydb USER SYS IDENTIFIED BY password USER SYSTEM IDENTIFIED BY password LOGFILE GROUP 1 ('/u01/redo01.log') SIZE 100M, GROUP 2 ('/u01/redo02.log') SIZE 100M MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 CHARACTER SET AL32UTF8 NATIONAL CHARACTER SET AL16UTF16 EXTENT MANAGEMENT LOCAL DATAFILE '/u01/system01.dbf' SIZE 500M REUSE SYSAUX DATAFILE '/u01/sysaux01.dbf' SIZE 250M REUSE DEFAULT TABLESPACE users DATAFILE '/u01/users01.dbf' SIZE 100M REUSE DEFAULT TEMPORARY TABLESPACE temp TEMPFILE '/u01/temp01.dbf' SIZE 100M REUSE UNDO TABLESPACE undotbs DATAFILE '/u01/undotbs01.dbf' SIZE 200M REUSE -- 缓冲池参数可能过多
相关技术原理
Oracle缓冲池架构:
缓冲池类型:
- DEFAULT池:默认缓冲池,所有未指定缓冲池的对象都使用此池
- KEEP池:用于保留频繁访问的数据块
- RECYCLE池:用于临时或很少重复访问的数据块
多块大小支持:
-- 每个块大小都可以有自己的缓冲池
-- 标准块大小:由db_block_size决定
-- 非标准块大小:2K, 4K, 8K, 16K, 32K
-- 每个非标准块大小可以配置独立的缓冲池
系统限制:
- Oracle对缓冲池总数有内部限制
- 不同版本可能有不同的限制
- 32位和64位系统限制可能不同
定位原因与诊断流程
诊断步骤
-
检查当前缓冲池配置
-- 查看所有缓冲池相关参数 SHOW PARAMETER cache_size SHOW PARAMETER k_cache_size SHOW PARAMETER db_block_size -
查看缓冲池详细信息
-- 查看当前配置的缓冲池 SELECT id, name, block_size, buffers, target_size FROM v$buffer_pool; -- 查看缓冲池统计信息 SELECT name, block_size, buffers, target_size, resize_state FROM v$buffer_pool_statistics; -
检查参数文件设置
-- 检查当前使用的参数文件 SELECT value FROM v$parameter WHERE name = 'spfile'; -- 如果使用spfile,创建pfile进行检查 CREATE PFILE = '/tmp/check_pools.ora' FROM SPFILE; -
验证系统限制
-- 检查Oracle版本和限制 SELECT * FROM v$version; -- 查看当前缓冲池数量 SELECT COUNT(*) as current_pool_count FROM v$buffer_pool;
详细诊断SQL
-- 全面缓冲池配置分析
SET LINESIZE 200
SET PAGESIZE 1000
COLUMN "Parameter" FORMAT A25
COLUMN "Value" FORMAT A20
COLUMN "Description" FORMAT A50
SELECT
name as "Parameter",
value as "Value",
description as "Description"
FROM v$parameter
WHERE name LIKE '%cache_size%'
OR name LIKE '%keep_cache_size%'
OR name LIKE '%recycle_cache_size%'
ORDER BY name;
-- 缓冲池使用情况分析
SELECT
bp.name as "Pool_Name",
bp.block_size as "Block_Size",
bp.buffers as "Buffers",
ROUND(bp.target_size/1024/1024, 2) as "Target_Size_MB",
bs.name as "Statistic",
bs.value as "Value"
FROM v$buffer_pool bp, v$buffer_pool_statistics bs
WHERE bp.name = bs.name
AND bp.block_size = bs.block_size;
解决方案与操作方法
方法一:合并或移除冗余缓冲池
分析当前使用情况:
-- 查看各缓冲池的使用效率
SELECT name, block_size,
free_buffer_wait, buffer_busy_wait,
physical_reads, physical_writes
FROM v$buffer_pool_statistics
ORDER BY physical_reads DESC;
移除使用率低的缓冲池:
-- 移除不必要的非标准块缓冲池
ALTER SYSTEM SET db_2k_cache_size = 0;
ALTER SYSTEM SET db_4k_cache_size = 0;
-- 或者合并到默认缓冲池
ALTER SYSTEM SET db_cache_size = db_cache_size +
(SELECT value FROM v$parameter WHERE name = 'db_2k_cache_size')
WHERE name = 'db_2k_cache_size' AND value > 0;
方法二:优化现有缓冲池配置
重新分配缓冲池大小:
-- 减少小型缓冲池,增加主要缓冲池
ALTER SYSTEM SET db_16k_cache_size = 32M;
ALTER SYSTEM SET db_32k_cache_size = 32M;
ALTER SYSTEM SET db_cache_size = 2048M;
使用标准缓冲池:
-- 专注于标准缓冲池配置
ALTER SYSTEM SET db_cache_size = 2G SCOPE = BOTH;
ALTER SYSTEM SET db_keep_cache_size = 512M SCOPE = BOTH;
ALTER SYSTEM SET db_recycle_cache_size = 256M SCOPE = BOTH;
方法三:参数文件清理和重建
从SPFILE创建PFILE并清理:
-- 创建PFILE进行编辑
CREATE PFILE = '/tmp/clean_pools.ora' FROM SPFILE;
-- 手动编辑文件,移除过多的缓冲池参数
-- 然后重新创建SPFILE
CREATE SPFILE FROM PFILE = '/tmp/clean_pools.ora';
-- 重启数据库
SHUTDOWN IMMEDIATE;
STARTUP;
方法四:使用自动内存管理
启用自动内存管理:
-- 设置自动内存管理参数
ALTER SYSTEM SET memory_target = 8G SCOPE = SPFILE;
ALTER SYSTEM SET sga_target = 0 SCOPE = SPFILE;
ALTER SYSTEM SET pga_aggregate_target = 0 SCOPE = SPFILE;
-- 重启数据库
SHUTDOWN IMMEDIATE;
STARTUP;
-- 验证自动内存管理
SHOW PARAMETER memory_target;
SHOW PARAMETER sga_target;
预防措施
最佳实践
-
缓冲池规划策略
-- 只配置必要的缓冲池 -- 标准配置示例: db_cache_size = 70% of SGA db_keep_cache_size = 10% of SGA db_recycle_cache_size = 5% of SGA -- 非标准块缓存根据需要配置1-2个 -
监控缓冲池效率
-- 定期监控缓冲池命中率 SELECT name, ROUND(1 - (physical_reads / (db_block_gets + consistent_gets)), 3) * 100 as hit_ratio FROM v$buffer_pool_statistics WHERE (db_block_gets + consistent_gets) > 0; -
容量规划
-- 在添加新缓冲池前检查当前数量 SELECT COUNT(*) as current_pools FROM v$buffer_pool;
配置检查脚本
-- 缓冲池配置健康检查
SELECT
CASE
WHEN (SELECT COUNT(*) FROM v$buffer_pool) > 8 THEN 'WARNING: Too many buffer pools'
WHEN (SELECT COUNT(*) FROM v$buffer_pool) > 5 THEN 'INFO: Consider optimizing buffer pools'
ELSE 'OK: Buffer pool count is reasonable'
END as pool_count_check,
CASE
WHEN (SELECT SUM(value) FROM v$parameter
WHERE name LIKE '%cache_size%' AND value IS NOT NULL) >
(SELECT value FROM v$parameter WHERE name = 'sga_target') * 0.8
THEN 'WARNING: Cache sizes exceed 80% of SGA'
ELSE 'OK: Cache sizes within reasonable limits'
END as cache_size_check
FROM dual;
相关联的其他ORA错误
- ORA-00380: 无法指定db_name,因为数据库名已在使用
- ORA-00381: 不能同时使用新旧缓冲区缓存参数
- ORA-00382: 指定的块大小无效
- ORA-00383: 无法为缓存启用字符串
- ORA-00384: 内存不足,无法扩展缓存
通俗易懂的解释
可以把ORA-00387错误想象成停车场管理问题:
比喻情景:
- 缓冲池 = 停车场的不同停车区域
- 数据块 = 不同大小的车辆
- Oracle数据库 = 停车场管理员
错误发生:
当你对停车场管理员说:
- “我要划分这些专用停车区:”
- “普通轿车区、SUV区、跑车区、货车区、摩托车区”
- “还要按颜色分:红色车区、蓝色车区、黑色车区、白色车区”
- “还要按品牌分:丰田区、本田区、宝马区、奔驰区…”
管理员就说:
- “停!区域划分太多了,我管理不过来!”
- “ORA-00387: 指定的缓冲池过多”
具体到Oracle:
-- 错误:要了太多专用停车区
db_cache_size = 2G -- 普通轿车区
db_keep_cache_size = 512M -- VIP长期停车区
db_recycle_cache_size = 256M -- 临时停车区
db_2k_cache_size = 64M -- 摩托车区
db_4k_cache_size = 64M -- 小型轿车区
db_8k_cache_size = 64M -- 中型轿车区
db_16k_cache_size = 64M -- SUV区
db_32k_cache_size = 64M -- 大货车区
-- 总共8个专用区域,可能超出管理能力
合理的做法:
-- 正确:合并一些区域,保持合理数量
db_cache_size = 2G -- 主要停车区(包含大部分车辆)
db_keep_cache_size = 512M -- VIP长期停车区(只给重要客户)
db_recycle_cache_size = 256M -- 临时停车区(给临时访客)
db_16k_cache_size = 128M -- 大型车辆区(只给真正需要的大车)
-- 总共4个区域,管理起来更高效
实际工作建议:
- 大多数应用只需要DEFAULT缓冲池
- KEEP池只用于极少数热点表
- RECYCLE池用于临时表或ETL操作
- 非标准块缓存只在确实需要时配置
记住,缓冲池不是越多越好,就像停车场划分太多专用区域反而会降低利用率。合理的缓冲池配置应该在管理复杂性和性能优化之间找到平衡点。
欢迎关注我的公众号《IT小Chen》
6583

被折叠的 条评论
为什么被折叠?



