DB_BLOCK_SIZE建库后不可修改,唯一变通方案是创建非标准块表空间;但必须预先配置对应DB_nK_CACHE_SIZE参数并重启实例,否则创建时会报ORA-29339。
DB_BLOCK_SIZE 锁死后,非标准块是唯一可调的粒度
oracle 12c 中 db_block_size 一旦建库就不可修改,重启、alter system、甚至强制改 spfile 都无效。你看到的报错 ora-01122 或 ora-01110,基本就是数据文件头块大小和参数不一致导致实例起不来。所以别在运行库上打 db_block_size 的主意——真要换,只能导出重建。非标准块表空间(比如 blocksize 16384)是唯一能在已有库中“绕过”这个限制的路径,但它不是万能补丁,而是有明确前提的妥协方案。
CREATE TABLESPACE BLOCKSIZE 报 ORA-29339:缺 DB_nK_CACHE_SIZE 是主因
这个错误不是语法问题,是 Oracle 在创建时校验内存缓存池是否存在。常见触发场景:
- 执行了
CREATE TABLESPACE tbs_16k DATAFILE '/path/df.dbf' SIZE 100M BLOCKSIZE 16384,但DB_16K_CACHE_SIZE值为0 - 写了
BLOCKSIZE 16K(带单位),Oracle 只认纯数字,必须写16384 -
DB_16K_CACHE_SIZE设了但值太小(比如1M),Oracle 内部按 granule 对齐后仍为0,实际生效值可能跳到16M或32M(取决于 CPU 数和 SGA 总量)
查当前状态用:SHOW PARAMETER db_16k_cache_size;设缓存用:ALTER SYSTEM SET DB_16K_CACHE_SIZE = 64M SCOPE=BOTH。注意:该参数是静态的,SCOPE=BOTH 要求实例已启用了 MEMORY_TARGET 或手动管理 SGA;否则需加 DEFERRED 并重启。
DB_nK_CACHE_SIZE 设置后值“变大了”:granule 和 CPU 数决定真实分配
你设 DB_16K_CACHE_SIZE = 4M,结果 SHOW PARAMETER 显示 32M,这不是 bug,是 Oracle 的内存分配机制:
- Oracle 按
granule粒度分配 SGA,SELECT * FROM V$SGAINFO WHERE NAME = 'Granule Size'可查当前粒度(12c 通常为4M或16M) - 真实分配值 = MAX(用户指定值向上取整到 granule, granule × CPU_COUNT)
- 比如 2 CPU + 4M granule → 最小分配
8M;若设1M,也会被拉到8M -
DB_2K_CACHE_SIZE、DB_4K_CACHE_SIZE等互不干扰,但总和不能超SGA_MAX_SIZE
如果 SGA_MAX_SIZE 已满,再设新 DB_nK_CACHE_SIZE 会报 ORA-00371,得先腾出空间。
非标准块表空间能放什么、不能放什么
它不是通用替代品,Oracle 对用途做了硬性限制:
- ✅ 可存放普通表、索引、LOB、分区段(尤其适合大 LOB 或宽索引,避免
ORA-01450) - ❌ 不能存放 SYSTEM/SYSAUX 表空间对象,也不能放回滚段、数据字典基表
- ❌ 不能作为默认表空间(
ALTER DATABASE DEFAULT TABLESPACE不接受非标准块表空间) - ❌ 不能用
ALTER TABLESPACE ... RESIZE修改块大小,BLOCKSIZE是只读属性
最易忽略的一点:非标准块表空间的数据文件,无法直接跨平台传输到块大小不匹配的库——即使目标库也配了 DB_16K_CACHE_SIZE,但若其 DB_BLOCK_SIZE 不同(比如源库是 8K、目标库是 4K),TTS 仍会失败。块大小兼容性必须提前对齐。


















