解决锁等待问题的第一步是准确定位阻塞会话与被锁对象,Oracle提供了多组动态性能视图用于排查:
V$LOCK视图查看当前锁的类型(如TX行级锁、TM表级锁)、持有状态(REQUEST=0表示持有者,REQUEST>0表示等待者),结合V$SESSION视图获取会话的SID、SERIAL#(杀会话必需)、USERNAME、SQL_ID(关联执行的SQL)、EVENT(等待事件)等信息。例如:SELECT DECODE(l.REQUEST,0,'Holder:','Waiter:') || s.inst_id || ':' || s.sid||','|| s.serial# sess,
l.id1, l.id2, l.type, l.lmode, l.request,
s.username, s.sql_id, s.event, s.service_name
FROM gv$lock l, gv$session s
WHERE (l.id1,l.id2,l.type) IN (
SELECT id1,id2,type FROM gv$lock WHERE request > 0
)
AND l.sid = s.sid AND l.inst_id = s.inst_id
ORDER BY l.id1, l.ctime DESC, l.request;
V$LOCKED_OBJECT(锁定的对象信息)、DBA_OBJECTS(对象元数据)关联查询,获取被锁对象的OWNER(所有者)、NAME(对象名)、OBJECT_TYPE(类型,如TABLE、INDEX)。例如:SELECT lo.session_id, lo.oracle_username, ao.object_name, lo.locked_mode,
'ALTER SYSTEM KILL SESSION ''' || lo.session_id || ',' || lo.serial# || '''' fsql
FROM v$locked_object lo, dba_objects ao
WHERE ao.object_id = lo.object_id;
V$SESSION的BLOCKING_SESSION字段(阻塞会话的SID)构建阻塞树,明确“谁阻塞了谁”。例如:SELECT s.sid, s.serial#, s.username, s.blocking_session, s.status,
s.sql_id, s.event
FROM v$session s
WHERE s.blocking_session IS NOT NULL;
定位到阻塞会话后,需立即干预以释放锁资源,避免影响其他业务:
ALTER SYSTEM KILL SESSION命令终止阻塞会话。语法为ALTER SYSTEM KILL SESSION '<SID>,<SERIAL#>' [IMMEDIATE],其中IMMEDIATE表示立即终止(默认是优雅终止,等待事务回滚)。例如:ALTER SYSTEM KILL SESSION '90,4213' IMMEDIATE;
V$PROCESS视图的ADDR字段(进程地址)关联V$SESSION的PADDR字段,获取阻塞会话的SPID(操作系统进程ID):SELECT p.spid
FROM v$session s, v$process p
WHERE s.sid = <阻塞会话SID> AND s.paddr = p.addr;
ps命令确认进程信息,再用kill -9强制结束:ps -ef | grep <SPID>
kill -9 <SPID>
注意:强制结束进程可能导致未提交事务的数据丢失,需谨慎使用。
临时解决仅能缓解当前问题,优化应用设计与数据库配置才是根本:
NOWAIT或WAIT选项:在SELECT FOR UPDATE语句中指定等待策略,避免无限期阻塞。NOWAIT表示立即返回错误(ORA-00054),WAIT n表示等待n秒后超时报错(ORA-30006)。例如:-- 立即尝试获取锁,失败则报错
SELECT * FROM employees WHERE employee_id = 100 FOR UPDATE NOWAIT;
-- 最多等待10秒,超时则报错
SELECT * FROM employees WHERE employee_id = 100 FOR UPDATE WAIT 10;
SELECT FOR UPDATE只锁定目标行,而非全表);避免全表扫描(通过创建合适的索引减少锁冲突)。READ COMMITTED(读已提交)比SERIALIZABLE(串行化)减少锁竞争,适用于大多数业务场景。ALTER SYSTEM SET LOCK_TIMEOUT = <seconds>命令设置锁等待的最长时间(如LOCK_TIMEOUT=30表示等待30秒后超报错),避免长时间阻塞。kernel.shmall、kernel.shmmax)、文件句柄(fs.file-max)、异步I/O(fs.aio-max-nr)等参数,提升数据库并发处理能力。AWR报告、OEM监控工具),设置锁等待阈值预警,及时发现并处理潜在问题。通过以上策略,可有效解决Linux环境下Oracle的锁等待问题,提升数据库并发性能与稳定性。需根据具体场景选择合适的解决方法,优先采用预防措施减少锁竞争的发生。