oracle WAIT 和 NOWAIT

发布于:2025-04-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

在 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. 使用建议

  1. 事务设计

    • 在事务中及时提交或回滚,避免长时间持有锁。

    • 使用 NOWAIT 或 WAIT 减少锁争用。

  2. 高并发场景

    • 优先使用 WAIT 指定合理的等待时间,平衡并发性和响应速度。

  3. 错误处理

    • 捕获 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,仍需注意事务设计,避免死锁。