1. 首页 > Oracle教程 > 正文

Oracle教程FG427-ORA-00054资源正忙

本文档风哥主要介绍Oracle ORA-00054资源正忙相关知识,包括ORA-00054的概念、ORA-00054的常见原因、ORA-00054分析方法、ORA-00054错误分析配置、ORA-00054错误监控、ORA-00054错误故障处理等内容,由风哥教程参考Oracle官方文档Troubleshooting内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-基础概念与理论知识

1.1 ORA-00054的概念

Oracle ORA-00054是Oracle数据库的资源正忙错误,表示试图以NOWAIT模式获取资源锁时资源正被其他会话占用。ORA-00054错误通常发生在DDL操作时,对象正被其他会话锁定。ORA-00054错误需要等待锁释放或终止占用锁的会话才能解决。更多视频教程www.fgedu.net.cn

Oracle ORA-00054的特点:

  • 资源正忙:资源正被其他会话占用
  • NOWAIT模式:以NOWAIT模式获取锁失败
  • DDL操作:DDL操作需要独占锁
  • 锁冲突:会话之间存在锁冲突
  • 立即返回:不等待直接返回错误

1.2 ORA-00054的常见原因

Oracle ORA-00054的常见原因:

  • DDL操作冲突:DDL操作时对象正被其他会话使用
  • 长时间事务:长时间运行的事务持有锁
  • 未提交事务:未提交的事务持有锁
  • 并发DDL操作:多个会话同时执行DDL操作
  • 索引创建冲突:创建索引时表正被使用
  • 表结构修改冲突:修改表结构时表正被使用
  • 锁超时设置:锁超时设置过短

1.3 ORA-00054分析方法

Oracle ORA-00054分析方法:

  • 错误信息分析:分析错误信息含义
  • 锁信息分析:分析当前锁信息
  • 会话分析:分析占用锁的会话
  • 事务分析:分析未提交的事务
  • 等待事件分析:分析等待事件
  • DDL操作分析:分析DDL操作类型
风哥提示:ORA-00054是资源正忙错误,建议等待锁释放或终止占用锁的会话。

Part02-生产环境规划与建议

2.1 ORA-00054错误处理规划

Oracle ORA-00054错误处理规划要点:

# ORA-00054错误处理规划
– 错误监控:监控ORA-00054错误发生
– 错误记录:记录ORA-00054错误信息
– 错误分析:分析ORA-00054错误原因
– 错误处理:处理ORA-00054错误问题

# 错误监控规划
– 监控工具:选择监控工具
– 监控频率:设置监控频率
– 监控范围:定义监控范围
– 告警配置:配置告警规则

# 错误记录规划
– 记录方式:选择记录方式
– 记录格式:定义记录格式
– 记录保留:设置记录保留时间
– 记录备份:备份错误记录

# 错误分析规划
– 分析方法:选择分析方法
– 分析工具:选择分析工具
– 分析流程:定义分析流程
– 分析报告:生成分析报告

# 错误处理规划
– 处理流程:定义处理流程
– 处理优先级:设置处理优先级
– 处理责任人:指定处理责任人
– 处理验证:验证处理结果

2.2 ORA-00054错误分析工具

Oracle ORA-00054错误分析工具:

  • SQL*Plus:命令行工具
  • SQL Developer:图形化工具
  • Enterprise Manager:企业级管理工具
  • V$LOCK:锁信息视图
  • V$SESSION:会话信息视图
  • V$SESSION_WAIT:会话等待视图
# 工具使用建议
– SQL*Plus:快速查询错误信息
– SQL Developer:图形化分析错误
– Enterprise Manager:集中管理错误
– V$LOCK:查看锁信息
– V$SESSION:查看会话信息
– V$SESSION_WAIT:查看会话等待

2.3 ORA-00054错误处理最佳实践

Oracle ORA-00054错误处理最佳实践:

  • 定期监控:定期监控ORA-00054错误
  • 及时处理:及时处理ORA-00054错误
  • 文档记录:记录错误处理过程
  • 经验积累:积累错误处理经验
  • 预防措施:制定预防措施
生产环境建议:ORA-00054错误处理需要建立完善的监控和处理机制,建议定期监控、及时处理、文档记录。学习交流加群风哥微信: itpux-com

Part03-生产环境项目实施方案

3.1 ORA-00054错误分析配置

3.1.1 配置锁管理

# 1. 查看当前锁信息
SQL> select
s.sid,
s.serial#,
s.username,
s.osuser,
s.machine,
l.type,
l.lmode,
l.request,
o.object_name
from v$session s
join v$lock l on s.sid = l.sid
left join dba_objects o on l.id1 = o.object_id
where l.type in (‘TM’, ‘TX’)
order by s.sid;

SID SERIAL# USERNAME OSUSER MACHINE TY LMODE REQUEST OBJECT_NAME
———- ———- ———- ——— ———- — ———- ———- —————-
150 1234 SCOTT oracle dbserver TM 3 0 EMP
150 1234 SCOTT oracle dbserver TX 6 0

# 2. 查看锁定的对象
SQL> select
o.object_name,
o.object_type,
l.session_id,
l.locked_mode,
s.username,
s.osuser,
s.machine
from dba_objects o
join v$locked_object l on o.object_id = l.object_id
join v$session s on l.session_id = s.sid
order by o.object_name;

OBJECT_NAME OBJECT_TYPE SESSION_ID LOCKED_MODE USERNAME OSUSER MACHINE
—————————— ——————- ———- ———– ———- ——— ———-
EMP TABLE 150 3 SCOTT oracle dbserver

# 3. 查看阻塞会话
SQL> select
s1.sid as blocking_sid,
s1.serial# as blocking_serial,
s1.username as blocking_user,
s2.sid as waiting_sid,
s2.serial# as waiting_serial,
s2.username as waiting_user,
s2.event as wait_event
from v$session s1, v$session s2
where s1.sid in (
select blocking_session from v$session where blocking_session is not null
)
and s2.blocking_session = s1.sid;

BLOCKING_SID BLOCKING_SERIAL BLOCKING_USER WAITING_SID WAITING_SERIAL WAITING_USER WAIT_EVENT
———— ————— ————- ———– ————– ———— —————-
150 1234 SCOTT 160 5678 HR enq: TX – row lock contention

# 4. 查看DDL锁
SQL> select
s.sid,
s.serial#,
s.username,
d.name,
d.type,
d.mode_held
from v$session s
join dba_ddl_locks d on s.sid = d.session_id
where s.username is not null
order by s.sid;

SID SERIAL# USERNAME NAME TYPE MODE_HELD
———- ———- ———- —————————— ——— ———
150 1234 SCOTT EMP Table/Procedure/Type Exclusive

# 5. 设置DDL锁等待时间
SQL> alter session set ddl_lock_timeout = 60;

Session altered.

# 6. 查看DDL锁等待设置
SQL> show parameter ddl_lock_timeout;

NAME TYPE VALUE
———————————— ———– ——————————
ddl_lock_timeout integer 60

# 7. 设置系统级DDL锁等待时间
SQL> alter system set ddl_lock_timeout = 60 scope=both;

System altered.

# 8. 查看DML锁等待时间
SQL> show parameter dml_locks;

NAME TYPE VALUE
———————————— ———– ——————————
dml_locks integer 1416

3.1.2 配置锁监控

# 1. 创建锁监控视图
SQL> create or replace view lock_monitor as
select
s.sid,
s.serial#,
s.username,
s.osuser,
s.machine,
s.program,
s.status,
s.last_call_et as seconds_in_wait,
l.type as lock_type,
l.lmode,
l.request,
l.ctime as time_held,
o.object_name,
o.object_type
from v$session s
join v$lock l on s.sid = l.sid
left join dba_objects o on l.id1 = o.object_id
where s.username is not null
and l.type in (‘TM’, ‘TX’, ‘UL’);

View created.

# 2. 查询锁监控信息
SQL> select * from lock_monitor where rownum <= 10;

SID SERIAL# USERNAME OSUSER MACHINE PROGRAM STATUS SECONDS_IN_WAIT LOCK_TYPE LMODE REQUEST TIME_HELD OBJECT_NAME OBJECT_TYPE
———- ———- ———- ——— ———- —————– ——— ————— ———- ———- ———- ———- —————————— ——————-
150 1234 SCOTT oracle dbserver sqlplus@dbserver ACTIVE 300 TX 6 0 300
150 1234 SCOTT oracle dbserver sqlplus@dbserver ACTIVE 300 TM 3 0 300 EMP TABLE

# 3. 创建阻塞会话监控视图
SQL> create or replace view blocking_session_monitor as
select
s1.sid as blocking_sid,
s1.serial# as blocking_serial,
s1.username as blocking_user,
s1.machine as blocking_machine,
s1.program as blocking_program,
s1.last_call_et as blocking_seconds,
s2.sid as waiting_sid,
s2.serial# as waiting_serial,
s2.username as waiting_user,
s2.machine as waiting_machine,
s2.program as waiting_program,
s2.event as wait_event,
s2.seconds_in_wait as wait_seconds
from v$session s1, v$session s2
where s1.sid in (
select blocking_session from v$session where blocking_session is not null
)
and s2.blocking_session = s1.sid;

View created.

# 4. 查询阻塞会话信息
SQL> select * from blocking_session_monitor;

BLOCKING_SID BLOCKING_SERIAL BLOCKING_USER BLOCKING_MACHINE BLOCKING_PROGRAM BLOCKING_SECONDS WAITING_SID WAITING_SERIAL WAITING_USER WAITING_MACHINE WAITING_PROGRAM WAIT_EVENT WAIT_SECONDS
———— ————— ————- —————- —————- —————- ———– ————– ———— —————- ————— ————————- ————
150 1234 SCOTT dbserver sqlplus@dbserver 300 160 5678 HR dbserver sqlplus@dbserver enq: TX – row lock contention 60

# 5. 创建事务监控视图
SQL> create or replace view transaction_monitor as
select
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
t.start_time,
t.status,
t.used_urec as undo_records,
t.used_ublk as undo_blocks,
round(t.used_ublk * 8 / 1024, 2) as undo_mb
from v$session s
join v$transaction t on s.saddr = t.ses_addr
where s.username is not null;

View created.

# 6. 查询事务监控信息
SQL> select * from transaction_monitor;

SID SERIAL# USERNAME MACHINE PROGRAM START_TIME STATUS UNDO_RECORDS UNDO_BLOCKS UNDO_MB
———- ———- ———- ———- —————– ——————– ——– ———— ———– ———-
150 1234 SCOTT dbserver sqlplus@dbserver 03/31/26 10:00:00 ACTIVE 100 10 0.08

3.2 ORA-00054错误监控

3.2.1 配置ORA-00054错误监控脚本

# 1. 创建ORA-00054错误监控脚本
$ vi /home/oracle/scripts/monitor_ora00054.sh

#!/bin/bash
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
# ORA-00054错误监控脚本

export ORACLE_HOME=/oracle/app/oracle/product/19c/dbhome_1
export ORACLE_SID=FGEDUDB
export PATH=$ORACLE_HOME/bin:$PATH

# 定义变量
ERROR_LOG=”/home/oracle/scripts/ora00054_errors.log”
EMAIL=”admin@fgedu.net.cn”

# 检查ORA-00054错误
check_ora00054_errors() {
local last_check_file=”/home/oracle/scripts/last_ora00054_check.txt”
local current_time=$(date +%s)

if [ -f “$last_check_file” ]; then
local last_check=$(cat “$last_check_file”)
local time_diff=$((current_time – last_check))

if [ $time_diff -lt 3600 ]; then
echo “Last check was $time_diff seconds ago, skipping…”
return 0
fi
fi

# 检查告警日志中的ORA-00054错误
local ora_errors=$(grep “ORA-00054” /oracle/app/oracle/diag/rdbms/fgedudb/FGEDUDB/trace/alert_FGEDUDB.log | tail -10)

if [ -n “$ora_errors” ]; then
echo “Found ORA-00054 errors:” >> “$ERROR_LOG”
echo “$ora_errors” >> “$ERROR_LOG”
echo “Timestamp: $(date)” >> “$ERROR_LOG”
echo “” >> “$ERROR_LOG”

# 发送告警邮件
echo “ORA-00054 error detected: resource busy” | mail -s “ORA-00054 Alert” “$EMAIL”

# 分析锁错误
analyze_lock_errors
fi

# 更新最后检查时间
echo “$current_time” > “$last_check_file”
}

# 分析锁错误
analyze_lock_errors() {
# 查询锁信息
local lock_info=$(sqlplus -s / as sysdba < exit
EOF
)

echo “Lock Information:” >> “$ERROR_LOG”
echo “$lock_info” >> “$ERROR_LOG”
echo “” >> “$ERROR_LOG”
}

# 主函数
main() {
check_ora00054_errors

echo “ORA-00054 error monitoring completed at $(date)” >> “$ERROR_LOG”
}

# 执行主函数
main

# 2. 设置脚本权限
$ chmod +x /home/oracle/scripts/monitor_ora00054.sh

# 3. 测试脚本
$ /home/oracle/scripts/monitor_ora00054.sh

# 4. 设置定期监控
$ crontab -e

# 每小时检查ORA-00054错误
0 * * * * /home/oracle/scripts/monitor_ora00054.sh >> /home/oracle/scripts/monitor_ora00054.log 2>&1

3.2.2 配置数据库监控

# 1. 创建锁等待监控视图
SQL> create or replace view lock_wait_monitor as
select
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
s.event,
s.seconds_in_wait,
s.blocking_session,
s.wait_class,
sw.p1text,
sw.p1,
sw.p2text,
sw.p2,
sw.p3text,
sw.p3
from v$session s
join v$session_wait sw on s.sid = sw.sid
where s.wait_class = ‘Application’
and s.event like ‘%lock%’;

View created.

# 2. 查询锁等待信息
SQL> select * from lock_wait_monitor where rownum <= 10;

SID SERIAL# USERNAME MACHINE PROGRAM EVENT SECONDS_IN_WAIT BLOCKING_SESSION WAIT_CLASS P1TEXT P1 P2TEXT P2 P3TEXT P3
———- ———- ———- ———- —————– —————————— ————— —————- ———- ———- ———- ———- ———- ———-
160 5678 HR dbserver sqlplus@dbserver enq: TX – row lock contention 60 150 Applicatio name|mode 1415053318 usn<<16 | slot 196611 sequence 12345 # 3. 创建DDL锁监控视图 SQL> create or replace view ddl_lock_monitor as
select
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
d.name,
d.type,
d.mode_held,
d.mode_requested
from v$session s
join dba_ddl_locks d on s.sid = d.session_id
where s.username is not null;

View created.

# 4. 查询DDL锁信息
SQL> select * from ddl_lock_monitor where rownum <= 10;

SID SERIAL# USERNAME MACHINE PROGRAM NAME TYPE MODE_HELD MODE_REQUESTED
———- ———- ———- ———- —————– —————————— ——— —————– —————
150 1234 SCOTT dbserver sqlplus@dbserver EMP Table/Procedure/Type Exclusive None

# 5. 创建ORA-00054错误告警
SQL> create or replace procedure ora00054_error_alert as
v_lock_count number;
v_blocking_count number;
v_long_transaction_count number;
begin
— 获取锁数量
select count(*) into v_lock_count
from v$lock
where type in (‘TM’, ‘TX’);

— 获取阻塞会话数量
select count(*) into v_blocking_count
from v$session
where blocking_session is not null;

— 获取长时间事务数量
select count(*) into v_long_transaction_count
from v$transaction
where (sysdate – to_date(start_time, ‘MM/DD/YY HH24:MI:SS’)) * 24 * 60 > 30;

dbms_output.put_line(‘Active locks: ‘ || v_lock_count);
dbms_output.put_line(‘Blocked sessions: ‘ || v_blocking_count);
dbms_output.put_line(‘Long transactions (>30min): ‘ || v_long_transaction_count);

if v_blocking_count > 0 then
dbms_output.put_line(‘— Blocked Sessions —‘);
for rec in (select * from blocking_session_monitor) loop
dbms_output.put_line(‘Blocking: ‘ || rec.blocking_sid || ‘,’ || rec.blocking_serial || ‘ – ‘ || rec.blocking_user);
dbms_output.put_line(‘Waiting: ‘ || rec.waiting_sid || ‘,’ || rec.waiting_serial || ‘ – ‘ || rec.waiting_user);
dbms_output.put_line(‘Wait Event: ‘ || rec.wait_event);
dbms_output.put_line(‘Wait Seconds: ‘ || rec.wait_seconds);
end loop;

dbms_output.put_line(‘Recommendation: Commit/rollback blocking transaction or kill session’);
else
dbms_output.put_line(‘No blocking sessions found’);
end if;
end ora00054_error_alert;
/

Procedure created.

# 6. 执行告警存储过程
SQL> set serveroutput on
SQL> exec ora00054_error_alert;

Active locks: 5
Blocked sessions: 1
Long transactions (>30min): 1
— Blocked Sessions —
Blocking: 150,1234 – SCOTT
Waiting: 160,5678 – HR
Wait Event: enq: TX – row lock contention
Wait Seconds: 60
Recommendation: Commit/rollback blocking transaction or kill session

PL/SQL procedure successfully completed.

# 7. 创建定时任务
SQL> begin
dbms_scheduler.create_job(
job_name => ‘ORA00054_ERROR_ALERT_JOB’,
job_type => ‘STORED_PROCEDURE’,
job_action => ‘ORA00054_ERROR_ALERT’,
start_date => systimestamp,
repeat_interval => ‘FREQ=HOURLY;INTERVAL=1’,
enabled => true
);
end;
/

PL/SQL procedure successfully completed.

3.3 ORA-00054错误故障处理

3.3.1 ORA-00054错误处理

# 问题现象
SQL> alter table emp add (phone varchar2(20));

alter table emp add (phone varchar2(20))
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

# 分析步骤

# 1. 查看锁定的对象
SQL> select
o.object_name,
l.session_id,
l.locked_mode,
s.username,
s.osuser,
s.machine,
s.program
from dba_objects o
join v$locked_object l on o.object_id = l.object_id
join v$session s on l.session_id = s.sid
where o.object_name = ‘EMP’;

OBJECT_NAME SESSION_ID LOCKED_MODE USERNAME OSUSER MACHINE PROGRAM
—————————— ———- ———– ———- ——— ———- —————-
EMP 150 3 SCOTT oracle dbserver sqlplus@dbserver

# 2. 查看会话详情
SQL> select sid, serial#, username, status, last_call_et, sql_id
from v$session
where sid = 150;

SID SERIAL# USERNAME STATUS LAST_CALL_ET SQL_ID
———- ———- ———- ——— ———— ————-
150 1234 SCOTT ACTIVE 300 7h3g8k2m9p1q

# 3. 查看会话执行的SQL
SQL> select sql_text
from v$sql
where sql_id = ‘7h3g8k2m9p1q’;

SQL_TEXT
————————————————————
update emp set sal = sal * 1.1 where deptno = 10

# 4. 分析错误原因
# 错误代码:ORA-00054
# 错误信息:resource busy and acquire with NOWAIT specified or timeout expired
# 锁定对象:EMP
# 锁定会话:SID=150, SERIAL#=1234
# 锁定用户:SCOTT
# 锁定程序:sqlplus@dbserver
# 错误原因:EMP表正被会话150锁定,无法执行DDL操作

# 5. 解决方案1:等待锁释放
SQL> alter session set ddl_lock_timeout = 60;

Session altered.

SQL> alter table emp add (phone varchar2(20));

Table altered.

# 6. 解决方案2:终止锁定会话
SQL> alter system kill session ‘150,1234’;

System altered.

SQL> alter table emp add (phone varchar2(20));

Table altered.

# 7. 解决方案3:联系用户提交事务
# 联系SCOTT用户提交或回滚事务

# 8. 预防措施
# – 在维护窗口执行DDL操作
# – 设置合理的DDL锁等待时间
# – 监控长时间运行的事务
# – 使用Online DDL选项

3.3.2 DDL操作冲突处理

# 1. 创建索引时使用ONLINE选项
SQL> create index idx_emp_ename on emp(ename) online;

Index created.

# 2. 修改表结构时使用ONLINE选项
SQL> alter table emp add (phone varchar2(20)) online;

Table altered.

# 3. 查看DDL操作进度
SQL> select
sid,
serial#,
opname,
target,
sofar,
totalwork,
time_remaining
from v$session_longops
where opname like ‘%DDL%’;

SID SERIAL# OPNAME TARGET SOFAR TOTALWORK TIME_REMAINING
———- ———- —————————— —————————— ———- ———- ————–
150 1234 DDL SCOTT.EMP 5000 10000 60

# 4. 查看DDL锁等待
SQL> select
s.sid,
s.serial#,
s.username,
s.event,
s.seconds_in_wait,
s.blocking_session
from v$session s
where s.event like ‘%DDL%’;

SID SERIAL# USERNAME EVENT SECONDS_IN_WAIT BLOCKING_SESSION
———- ———- ———- —————————— ————— —————-
160 5678 HR library cache lock 120 150

# 5. 处理DDL锁等待
SQL> alter system kill session ‘150,1234’;

System altered.

# 6. 查看DDL操作状态
SQL> select * from dba_ddl_locks where session_id = 160;

SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQUESTED
———- —– —————————— ——— —————– —————
160 SCOTT EMP Table/Procedure/Type Exclusive None

# 7. 使用DDL_TIMEOUT参数
SQL> alter session set ddl_lock_timeout = 300;

Session altered.

SQL> alter table emp add (address varchar2(200));

Table altered.

# 8. 查看DDL操作历史
SQL> select
object_name,
object_type,
last_ddl_time,
status
from dba_objects
where object_name = ‘EMP’
order by last_ddl_time desc;

OBJECT_NAME OBJECT_TYPE LAST_DDL_TIME STATUS
—————————— ——————- ——————- ———
EMP TABLE 2026-03-31 10:30:00 VALID

风哥提示:ORA-00054错误处理需要结合锁管理和会话管理,建议建立完善的错误处理流程。学习交流加群风哥QQ113257174

Part04-生产案例与实战讲解

4.1 ORA-00054错误分析案例

在生产环境中分析ORA-00054错误的完整案例:

4.1.1 场景描述

某企业生产数据库出现ORA-00054资源正忙错误,需要分析错误原因并解决问题。

4.1.2 分析步骤

# 1. 收集错误信息
SQL> alter table orders add (status varchar2(20));

alter table orders add (status varchar2(20))
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

# 2. 查看锁定的对象
SQL> select
o.object_name,
l.session_id,
l.locked_mode,
s.username,
s.machine,
s.program
from dba_objects o
join v$locked_object l on o.object_id = l.object_id
join v$session s on l.session_id = s.sid
where o.object_name = ‘ORDERS’;

OBJECT_NAME SESSION_ID LOCKED_MODE USERNAME MACHINE PROGRAM
—————————— ———- ———– ———- ———- —————-
ORDERS 150 3 FGFGFGAPP_USER appserver java@appserver

# 3. 查看会话详情
SQL> select sid, serial#, username, status, last_call_et, sql_id
from v$session
where sid = 150;

SID SERIAL# USERNAME STATUS LAST_CALL_ET SQL_ID
———- ———- ———- ——— ———— ————-
150 5678 FGFGFGAPP_USER ACTIVE 3600 8k2m9p1q7h3g

# 4. 查看会话执行的SQL
SQL> select sql_text
from v$sql
where sql_id = ‘8k2m9p1q7h3g’;

SQL_TEXT
————————————————————
insert into orders (order_id, customer_id, order_date) values (:1, :2, :3)

# 5. 分析错误原因
# 错误代码:ORA-00054
# 错误信息:resource busy and acquire with NOWAIT specified or timeout expired
# 锁定对象:ORDERS
# 锁定会话:SID=150, SERIAL#=5678
# 锁定用户:FGFGFGAPP_USER
# 锁定程序:java@appserver
# 错误原因:ORDERS表正被应用程序会话锁定,无法执行DDL操作

# 6. 解决方案:使用ONLINE DDL
SQL> alter table orders add (status varchar2(20)) online;

Table altered.

# 7. 验证问题解决
SQL> desc orders;

Name Null? Type
—————————————– ——– —————————-
ORDER_ID NOT NULL NUMBER
CUSTOMER_ID NUMBER
ORDER_DATE DATE
STATUS VARCHAR2(20)

4.2 ORA-00054错误故障处理

在ORA-00054错误故障处理过程中的方法和技巧:

4.2.1 故障处理流程

# ORA-00054错误故障处理流程

# 1. 错误识别
# – 监控资源正忙错误
# – 检查错误信息
# – 确认错误参数

# 2. 错误分析
# – 查看锁定对象
# – 检查锁定会话
# – 分析锁定原因

# 3. 错误处理
# – 等待锁释放
# – 终止锁定会话
# – 使用ONLINE DDL

# 4. 错误预防
# – 在维护窗口执行DDL
# – 使用ONLINE DDL选项
# – 监控长时间事务

# 示例:ORA-00054错误处理

# 1. 错误识别
SQL> create index idx_emp_sal on emp(sal);

create index idx_emp_sal on emp(sal)
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

# 2. 错误分析
SQL> select * from lock_monitor where object_name = ‘EMP’;

SID SERIAL# USERNAME OSUSER MACHINE PROGRAM STATUS SECONDS_IN_WAIT LOCK_TYPE LMODE REQUEST TIME_HELD OBJECT_NAME OBJECT_TYPE
———- ———- ———- ——— ———- —————– ——— ————— ———- ———- ———- ———- —————————— ——————-
150 1234 SCOTT oracle dbserver sqlplus@dbserver ACTIVE 300 TM 3 0 300 EMP TABLE

# 3. 错误处理
SQL> create index idx_emp_sal on emp(sal) online;

Index created.

# 4. 验证处理结果
SQL> select index_name, status from user_indexes where table_name = ‘EMP’;

INDEX_NAME STATUS
—————————— ——–
PK_EMP VALID
IDX_EMP_SAL VALID

# 5. 错误预防
# – 在维护窗口执行DDL操作
# – 使用ONLINE DDL选项
# – 监控长时间运行的事务
# – 设置合理的DDL锁等待时间

4.3 ORA-00054错误优化

优化ORA-00054错误处理配置的最佳实践:

4.3.1 优化锁管理

# 1. 创建锁管理优化存储过程
SQL> create or replace procedure optimize_lock_management as
v_lock_count number;
v_blocking_count number;
v_long_transaction_count number;
begin
— 获取锁数量
select count(*) into v_lock_count
from v$lock
where type in (‘TM’, ‘TX’);

— 获取阻塞会话数量
select count(*) into v_blocking_count
from v$session
where blocking_session is not null;

— 获取长时间事务数量
select count(*) into v_long_transaction_count
from v$transaction
where (sysdate – to_date(start_time, ‘MM/DD/YY HH24:MI:SS’)) * 24 * 60 > 30;

dbms_output.put_line(‘Active locks: ‘ || v_lock_count);
dbms_output.put_line(‘Blocked sessions: ‘ || v_blocking_count);
dbms_output.put_line(‘Long transactions (>30min): ‘ || v_long_transaction_count);

— 显示长时间事务
if v_long_transaction_count > 0 then
dbms_output.put_line(‘— Long Transactions —‘);
for rec in (select * from transaction_monitor) loop
dbms_output.put_line(‘SID: ‘ || rec.sid || ‘, User: ‘ || rec.username);
dbms_output.put_line(‘Start Time: ‘ || rec.start_time);
dbms_output.put_line(‘Undo MB: ‘ || rec.undo_mb);
end loop;

dbms_output.put_line(‘Recommendation: Commit/rollback long transactions’);
end if;

— 显示阻塞会话
if v_blocking_count > 0 then
dbms_output.put_line(‘— Blocked Sessions —‘);
for rec in (select * from blocking_session_monitor) loop
dbms_output.put_line(‘Blocking: ‘ || rec.blocking_sid || ‘ – ‘ || rec.blocking_user);
dbms_output.put_line(‘Waiting: ‘ || rec.waiting_sid || ‘ – ‘ || rec.waiting_user);
dbms_output.put_line(‘Wait Event: ‘ || rec.wait_event);
end loop;

dbms_output.put_line(‘Recommendation: Resolve blocking sessions’);
end if;
end optimize_lock_management;
/

Procedure created.

# 2. 执行优化存储过程
SQL> set serveroutput on
SQL> exec optimize_lock_management;

Active locks: 5
Blocked sessions: 1
Long transactions (>30min): 1
— Long Transactions —
SID: 150, User: SCOTT
Start Time: 03/31/26 10:00:00
Undo MB: 10.5
— Blocked Sessions —
Blocking: 150 – SCOTT
Waiting: 160 – HR
Wait Event: enq: TX – row lock contention
Recommendation: Resolve blocking sessions

PL/SQL procedure successfully completed.

# 3. 创建定时任务
SQL> begin
dbms_scheduler.create_job(
job_name => ‘OPTIMIZE_LOCK_MANAGEMENT_JOB’,
job_type => ‘STORED_PROCEDURE’,
job_action => ‘OPTIMIZE_LOCK_MANAGEMENT’,
start_date => systimestamp,
repeat_interval => ‘FREQ=HOURLY;INTERVAL=1’,
enabled => true
);
end;
/

PL/SQL procedure successfully completed.

# 4. 创建自动终止长时间事务脚本
SQL> create or replace procedure kill_long_transactions as
v_sid number;
v_serial number;
begin
for rec in (
select s.sid, s.serial#
from v$session s
join v$transaction t on s.saddr = t.ses_addr
where (sysdate – to_date(t.start_time, ‘MM/DD/YY HH24:MI:SS’)) * 24 * 60 > 60
and s.username not in (‘SYS’, ‘SYSTEM’)
) loop
dbms_output.put_line(‘Killing session: ‘ || rec.sid || ‘,’ || rec.serial#);
execute immediate ‘alter system kill session ”’ || rec.sid || ‘,’ || rec.serial# || ””;
end loop;
end kill_long_transactions;
/

Procedure created.

# 5. 设置DDL锁等待时间
SQL> alter system set ddl_lock_timeout = 300 scope=both;

System altered.

# 6. 验证设置
SQL> show parameter ddl_lock_timeout;

NAME TYPE VALUE
———————————— ———– ——————————
ddl_lock_timeout integer 300

生产环境建议:ORA-00054错误优化需要建立完善的监控和处理机制,建议定期监控、及时处理、文档记录。更多学习教程公众号风哥教程itpux_com

Part05-风哥经验总结与分享

5.1 ORA-00054错误总结

Oracle ORA-00054错误是资源正忙错误,具有以下特点:

  • 资源正忙:资源正被其他会话占用
  • NOWAIT模式:以NOWAIT模式获取锁失败
  • DDL操作:DDL操作需要独占锁
  • 锁冲突:会话之间存在锁冲突
  • 立即返回:不等待直接返回错误

5.2 ORA-00054错误检查清单

Oracle ORA-00054错误检查清单:

  • 错误识别:识别错误信息和参数
  • 错误分析:分析锁定对象和会话
  • 错误处理:处理错误问题
  • 错误验证:验证处理结果
  • 错误预防:制定预防措施
  • 错误记录:记录处理过程

5.3 ORA-00054错误工具推荐

Oracle ORA-00054错误工具推荐:

  • SQL*Plus:命令行工具
  • SQL Developer:图形化工具
  • Enterprise Manager:企业级管理工具
  • V$LOCK:锁信息视图
  • V$SESSION:会话信息视图
  • V$SESSION_WAIT:会话等待视图
风哥提示:ORA-00054是资源正忙错误,建议等待锁释放或终止占用锁的会话,建立完善的错误处理流程。from:www.itpux.com www.fgedu.net.cn

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息