Oracle for update 加锁

Oracle SELECT FOR UPDATE详解
本文详细介绍了Oracle数据库中SELECT FOR UPDATE语句的不同选项及其应用场景。包括标准SELECT FOR UPDATE、NOWAIT选项、WAIT选项以及SKIP LOCKED特性。这些特性能够帮助开发者实现更高级别的数据一致性控制。
select for update

select for update 当oracle发现select的当前结果集中的一条或多条正在被修改(注意:当数据被修改时,此时的数据行是被加锁的),那么他就会等到当前当前结果集被修改完毕并且commit之后才进行select操作,并对结果集进行加锁。同样的,如果查询语句发出后,其他会话需要修改结果集中的一条(或几条数据)也许要等到查询结束(commit)之后,才可以执行修改操作。

select for update nowait

select for update nowait for update和for update nowait都会对查询到的当前结果集进行加锁,所不同的是,当有另外的会话在修改当前结果集中的数据,select for nowait所进行的查询操作不会进行等待,当发现结果集中的一些数据被加锁,立刻返回 “ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。

select for update wait

select for update wait 它也会对查询到的结果集进行加锁,select for update wait与select for update nowait不同的地方是,当有另外的会话对它的查询结果集中的某一行数据进行了加锁,那么它不会像nowait一样,立即返回"ORA-00054错误",而是它支持一个参数,设定等待的时间,当超过了设定的时间,那一行数据还处于加锁的状态,那么它也会返回“ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。

skip locked

skip locked是oracle 11g引入的。通过skip locked可以使select for update语句可以查询出(排除已经被其他会话加锁了的数据行)剩下的数据集,并给剩下的数据集,进行加锁操作。

for update 和 rowid
  1. 在ORACLE中用ROWID来定位记录是最快的,比索引还快,所以如果先用SELECT ROWID选出要更新的行,放入COLLECTION中,再用 FORALL UPDATE 来批量更新可以提高速度。从这点来讲是比其他方法好一点。 运行后并未给数据加上行级锁(通过物理地址去确定某一行数据),但可以编辑数据,提交事务的瞬间完成上锁、提交、解锁等动作,不易发生锁表。
  2. SELECT FOR UPDATE在更新前会锁定记录,这在复杂的并行查询更新程序中是必要的,比如要求数据一致性,在过滤数据时不允许他人改动数据,会用FOR UPDATE或SET TRANSACTION READ ONLY来加锁。另外像 CURSOR里的WHERE CURRENT OF CURSOR语句要求SELECT中必须加FOR UPDATE。当语句运行时,会在对应行(where子句)加上行级锁,无where子句等于全表上锁。若遇到客户端断网、测试人员忘记提交\回滚事务,则会发生锁表。

转载于:https://my.oschina.net/MyoldTime/blog/2050255

### Oracle 数据库中 `FOR UPDATE` 语句的用法 #### 语法结构 在Oracle数据库中,`FOR UPDATE` 子句用于锁定查询返回的数据行,防止其他事务在此期间修改这些数据。基本语法如下: ```sql SELECT column_name(s) FROM table_name WHERE condition FOR UPDATE [OF column_list] [NOWAIT | WAIT n | SKIP LOCKED]; ``` - **`column_name(s)`**: 表中的列名。 - **`table_name`**: 查询的目标表。 - **`condition`**: 过滤条件。 #### 锁定机制说明 当使用 `FOR UPDATE` 后,所选记录会被加上排他锁,这意味着在同一时间只有一个会话可以持有该锁并进行更改操作[^1]。 #### 参数解释 - **`OF column_list`**: 指定要锁定的具体字段列表,默认情况下会对所有涉及的列加锁。 - **`NOWAIT`**: 如果请求的资源已经被占用,则立即抛出异常而不是等待解锁。 - **`WAIT n`**: 设置最大等待时间为n秒来获取锁,超时则报错退出。 - **`SKIP LOCKED`**: 遇到已被锁定的行时跳过它们继续处理未被锁定的行[^2]。 #### 实际应用场景举例 假设有一个名为 `orders` 的订单表,在处理支付业务逻辑时需要确保同一笔订单不会被重复扣款。此时可以通过下面的方式实现安全的操作流程: ```sql BEGIN TRANSACTION; -- 加锁读取特定状态下的订单信息 SELECT * FROM orders o WHERE o.order_status = '待付款' AND ROWNUM <= 1 -- 假设只处理一条记录作为例子 FOR UPDATE NOWAIT; UPDATE orders o SET order_status='已付款', pay_time=SYSDATE() WHERE CURRENT OF orders; COMMIT; ``` 这段SQL先通过带 `FOR UPDATE NOWAIT` 的 `SELECT` 获取符合条件的第一条记录,并尝试对其加锁;如果成功获得锁,则紧接着执行更新操作改变其状态为“已付款”,最后提交整个交易过程[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值