You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle19c中PL/SQL的DBMS_LOCK机制疑问:多线程是否重复取P_NUMBER

多线程调用下P_NUMBER的唯一性保障分析

这段代码可以确保多线程调用时不会获取到相同的P_NUMBER,具体分析如下:

核心机制:全局排他锁的串行化控制

代码通过DBMS_LOCK实现了全局排他锁的控制:

  • DBMS_LOCK.ALLOCATE_UNIQUE('LOCK5', HANDLE)为名为LOCK5的锁生成唯一句柄,所有线程都会请求这同一把锁。
  • DBMS_LOCK.REQUEST(..., DBMS_LOCK.X_MODE)请求排他模式锁,同一时间只有一个线程能成功获取锁,其他线程会阻塞在这一步,直到锁被释放。

锁保护下的原子操作

在持有锁的期间,查询与更新操作是原子性的:

  1. 通过SELECT TR into P_NUMBER from T_MONITORING where PROCESS_S=0 and ROWNUM=1获取一条未处理的记录ID。
  2. 立刻执行UPDATE T_MONITORING td set td.PROCESS_S=1 where td.TR=P_NUMBER and td.PROCESS_S =0将这条记录标记为已处理。

因为排他锁的存在,这两步操作不会被其他线程打断,确保只有当前线程能拿到这条记录;后续线程再查询时,这条记录已被标记为已处理,不会被重复获取。

潜在性能问题

虽然代码能保证唯一性,但全局排他锁会导致并发性能极低——所有线程必须排队等待同一把锁,1000万条记录的处理速度会被限制在单线程水平。

优化建议:提升并发效率

如果需要更高的并发处理能力,可以去掉全局锁,改用Oracle的FOR UPDATE SKIP LOCKED特性,直接在查询时锁定未处理的记录,让多个线程同时处理不同的记录:

SELECT TR INTO P_NUMBER 
FROM T_MONITORING 
WHERE PROCESS_S=0 
FOR UPDATE SKIP LOCKED 
ROWNUM=1;

UPDATE T_MONITORING td set td.PROCESS_S=1 where td.TR=P_NUMBER;

这个方式既保证了不会获取重复的P_NUMBER,又能让多个线程并行处理,大幅提升处理速度。

内容的提问来源于stack exchange,提问作者VJS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:55:25