上周,我们生产环境的 AWR 报告里突然出现了一条醒目的 Top 5 Timed Events
:
Event Waits Time(s) Avg Wait(ms) %DB Time
------------------------ ------ ------- ------------ -------
ST enqueue 12,345 18,491 1,498 31.6
这条 ST enqueue
等待直接把数据库 CPU Idle 干到个位数,业务方反馈“DDL 偶尔卡顿、批量作业跑不动”。
T enqueue 究竟是什么?
- 只有一个 每个数据库实例只有 一把 ST 锁(Space Transaction Enqueue),串行化所有对数据字典中空间信息的修改。
- 谁来抢 只要执行会改动
UET$
(Used Extents)或FET$
(Free Extents)的操作就会申请 ST 锁,典型场景包括: •DROP / TRUNCATE / MOVE
表或分区 •ALTER TABLE … COALESCE
• 大批量INSERT
/UPDATE
/DELETE
触发动态扩展 • 临时段大量分配/回收(排序、hash join、索引创建) - 症状 • AWR/ASH 中
ST enqueue
占据大量 DB Time •v$session_wait
看到p1=1414332418
(enqueue 的 ID 对应 ST) • 业务会话event="enq: ST - contention"
,seconds_in_wait
累积
用下面一条 SQL 就能抓到“元凶”:
SELECT s.sid,
s.serial#,
s.username,
s.sql_id,
s.event,
l.type,
l.id1,
l.id2,
lo.object_name,
lo.object_type
FROM v$session s
JOIN v$lock l ON s.sid = l.sid
JOIN dba_objects lo ON l.id1 = lo.object_id
WHERE l.type = 'ST';
输出示例:
SID SERIAL# USERNAME SQL_ID EVENT TYPE OBJECT_NAME OBJECT_TYPE
---- ------- -------- ------------- --------------------- ---- ----------- -----------
123 45678 DW_BATCH 9q7x8y0g9z9z0 enq: ST - contention ST UET$ TABLE
拿到 SID 后,再去看 v$sqltext
或 DBMS_XPLAN.DISPLAY_CURSOR
就能定位到具体 SQL。 这次我们抓到的是一条 TRUNCATE PARTITION
语句,每小时跑一次,分区表字典管理 + 没开并行,导致 ST 锁长时间被占。
根因复盘
- 遗留表空间仍是 字典管理(Dictionary-Managed Tablespace, DMT)。 Oracle 9i 就支持 LMT,但老库“能跑就行”,一直没人改。
- 临时表空间不是
TEMPFILE
创建,而是早期CREATE TABLESPACE … TEMPORARY
的 DMT 临时表空间。 大量排序把临时段当“公共厕所”,频繁申请/释放 ST 锁。
五、根治方案:三板斧一次性解决
步骤 | 动作 | 备注 |
---|---|---|
1 | 把所有永久表空间改为 本地管理 | EXEC DBMS_SPACE_ADMIN.TABLESPACE_MIGRATE_TO_LOCAL('USERS'); |
2 | 重建临时表空间为 本地管理 + TEMPFILE | CREATE TEMPORARY TABLESPACE TEMP_LMT TEMPFILE '+DATA' SIZE 20G AUTOEXTEND ON; |
3 | 业务侧规范 | • 大表提前 ALTER TABLE … ALLOCATE EXTENT 预分配空间 • 批量 DDL 合并窗口,避免并发 |
• ST enqueue
99% 都是 字典管理表空间 的历史包袱。 • 一条 SQL 就能定位阻塞者,但根治必须 全库 LMT + 正确临时表空间。 • 如果你还在用 DMT,建议立刻排期整改,越晚越痛苦。