Oracle RAC临时表空间争用根源在于各实例未独占访问专属tempfile,必须为每个实例创建独立临时表空间及ASM路径带实例标识的tempfile,并逐实例验证dba_temp_files状态与默认设置。
oracle rac 下临时表空间争用,核心不是“要不要分片”,而是“每个实例必须有自己可独占访问的 tempfile”——不满足这点,加再多文件、建再大表空间都白搭。
为什么 enq: TS – contention 会反复出现
这不是配置没生效,而是多个实例在抢同一个 tempfile 的文件头(file header)锁。RAC 中临时段是实例本地的,但若所有实例共用一个 TEMP 表空间,且该表空间只含 1 个 tempfile(哪怕它在 ASM 共享盘上),所有实例的排序操作都会串行排队等待该文件头的 latch,表现为持续的 enq: TS – contention 等待事件。
常见误判:dba_temp_files 显示文件存在 ≠ 当前实例能真正写入。比如文件路径为 +DATA/temp01.dbf,但该 diskgroup 在某个节点未挂载或权限受限,status 可能是 OFFLINE 或 DISABLED,却仍被 DEFAULT_TEMP_TABLESPACE 指向。
- 检查每个实例是否真能访问自己的 tempfile:
SELECT tablespace_name, status, enabled FROM dba_temp_files—— 必须在每个实例上单独执行 - 确认实例级默认设置:
SELECT property_value FROM database_properties WHERE property_name = 'DEFAULT_TEMP_TABLESPACE'—— 同样需逐实例查,gv$视图不反映本实例实际生效值 - 别信“组名一致就负载均衡”:表空间组(
TABLESPACE GROUP)只是逻辑标签,不改变物理归属;组里只有一个表空间,等于没分片
正确做法:为每个实例创建专属 tempfile + 本地化临时表空间
不是简单地给 TEMP 表空间 ADD TEMPFILE,而是为每个实例新建一个独立命名的临时表空间,并确保其 tempfile 路径对本实例唯一、可写、不与其他实例冲突。
- 显式指定 ASM 路径带实例标识,例如:
+DATA/racdb_inst1/temp01.dbf,而不是笼统的+DATA/temp01.dbf - 禁用 OMF 自动路径生成,它默认不区分实例,极易导致多个实例往同一路径争抢 tempfile
- 创建时绑定逻辑组(可选但推荐):
CREATE TEMPORARY TABLESPACE temp_inst1 TEMPFILE '+DATA/...' SIZE 100M TABLESPACE GROUP 'TEMP_GROUP' - 设置本实例默认值:
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp_inst1—— 此命令只作用于当前实例,不会广播 - 验证 tempfile 状态:
SELECT file_name, status, enabled FROM dba_temp_files WHERE tablespace_name = 'TEMP_INST1',确保status = ONLINE且enabled = YES
临时文件数量 ≠ 实例数?看场景再决定
“每个表空间配 N 个 tempfile(N=实例数)”是过时建议。现代 Oracle(12c+ RAC)中,关键不是数量,而是隔离性:只要每个实例有自己专属的 tempfile(哪怕仅 1 个),且该文件不被其他实例访问,就能消除文件头争用。
多 tempfile 的真实价值在于:当单个 tempfile 扩展频繁、IO 瓶颈明显时,分散写压力。但这属于 IO 层优化,和 enq: TS 锁争用无直接关系。
- 若已按上一节完成实例级隔离,
TEMP_INST1里只放 1 个 tempfile 完全够用 - 若某实例排序负载极高(如跑 ETL),可为其
temp_inst1增加第二个 tempfile:ALTER TABLESPACE temp_inst1 ADD TEMPFILE '+DATA/...' SIZE 50M - 不要跨实例复用 tempfile 路径,即使用了 ASM;也不要让多个实例的 tempfile 指向同一磁盘或 LUN,否则换汤不换药
别跳过这步:清理残留 session 再重建或收缩
想通过 COALESCE、DROP_SEGMENTS 或重建来释放空间?先确认没有活跃 session 占着临时段,否则操作会卡住或失败。
- 查谁在用:
SELECT s.sid, s.serial#, s.username, su.tablespace, su.segtype FROM v$session s, v$sort_usage su WHERE s.saddr = su.session_addr - 杀掉非关键会话:
ALTER SYSTEM KILL SESSION 'sid,serial#' - 收缩前确保无活动排序:
ALTER TABLESPACE temp_inst1 COALESCE仅合并空闲 extent,不释放磁盘空间;真正释放需重建或重启(SMON 清理) - 诊断事件是最后手段:
ALTER SESSION SET EVENTS 'immediate trace name DROP_SEGMENTS level <ts>'</ts>,ts#需从sys.ts$查,填错会清错表空间
最易被忽略的点:以为改了 DEFAULT_TEMP_TABLESPACE 就万事大吉,却没验证该表空间的 tempfile 是否真在本实例上线、可写、且未被其他实例共享路径。争用根源永远在物理层隔离是否真正落地,不在 SQL 或参数层面。


















