在 Oracle 数据库中,WAIT
和 NOWAIT
是与 锁(Lock) 相关的关键选项,用于控制事务或操作在请求资源时的等待行为。以下是它们的详细说明和应用场景。
1. NOWAIT
选项
作用:
当请求资源(如表、行)的锁时,如果资源已被其他会话锁定,立即返回错误(ORA-00054),而不是等待锁释放。适用场景:
避免长时间阻塞:需要快速失败(Fail Fast)的场景。
高并发系统中,防止事务因等待锁而堆积。
-- 尝试锁定某行,若被占用则立即报错
SELECT * FROM employees
WHERE employee_id = 100
FOR UPDATE NOWAIT; -- 立即检查锁状态
-- 结果:若行被其他会话锁定,抛出 ORA-00054
2. WAIT
选项
作用:
指定等待锁释放的时间(单位为秒)。如果在指定时间内锁未释放,则返回错误。适用场景:
允许短暂等待锁释放,平衡并发性和响应速度。
控制锁等待时间,避免无限期阻塞。
语法:
WAIT n -- n 为等待的秒数(Oracle 11g+)
-- 尝试锁定某行,最多等待 10 秒
SELECT * FROM employees
WHERE employee_id = 100
FOR UPDATE WAIT 10; -- 等待 10 秒
-- 结果:
-- 10 秒内锁释放 → 成功锁定
-- 超时 → 抛出 ORA-30006: resource busy; acquire with WAIT timeout expired
3. 在 DDL 语句中的使用
从 Oracle 11g 开始,部分 DDL 操作支持 WAIT
或 NOWAIT
选项,用于控制表级锁的等待行为。
-- 修改表结构时等待 60 秒获取锁
ALTER TABLE employees DROP COLUMN unused_column WAIT 60;
-- 立即尝试获取锁(不等待)
ALTER TABLE employees DROP COLUMN unused_column NOWAIT;
4. 默认行为
如果不指定 NOWAIT
或 WAIT
,Oracle 默认会无限期等待锁释放,直到以下情况之一发生:
锁被释放。
发生死锁(自动检测并抛出 ORA-00060)。
手动取消操作。
5. 核心区别
选项 | 行为 |
---|---|
NOWAIT |
立即检查锁状态,若资源被占用,直接报错(ORA-00054)。 |
WAIT n |
最多等待 n 秒,超时后报错(ORA-30006)。 |
默认行为 | 无限期等待,直到锁释放或发生死锁。 |
6. 使用建议
事务设计:
在事务中及时提交或回滚,避免长时间持有锁。
使用
NOWAIT
或WAIT
减少锁争用。
高并发场景:
优先使用
WAIT
指定合理的等待时间,平衡并发性和响应速度。
错误处理:
捕获
ORA-00054
或ORA-30006
错误,实现重试逻辑。
7. 实际应用示例
DECLARE
retry_count NUMBER := 3; -- 最大重试次数
BEGIN
FOR i IN 1..retry_count LOOP
BEGIN
-- 尝试锁定员工记录,最多等待 5 秒
SELECT salary INTO :old_salary
FROM employees
WHERE employee_id = 100
FOR UPDATE WAIT 5;
-- 执行更新
UPDATE employees SET salary = :new_salary
WHERE employee_id = 100;
COMMIT;
EXIT; -- 成功则退出循环
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -30006 THEN -- 锁等待超时
DBMS_OUTPUT.PUT_LINE('等待超时,重试 ' || i || '/' || retry_count);
CONTINUE;
ELSE
RAISE;
END IF;
END;
END LOOP;
END;
/
8. 注意事项
权限要求:
使用
FOR UPDATE
需要SELECT
和UPDATE
权限。DDL 操作需要
ALTER
权限。
版本兼容性:
WAIT n
语法从 Oracle 11g 开始支持,早期版本需通过DBMS_LOCK
包模拟。
死锁风险:
即使使用
NOWAIT
,仍需注意事务设计,避免死锁。