Oracle数据库,for update 使用实践;行级锁;排它锁、共享锁

1 篇文章 0 订阅
1 篇文章 0 订阅

一、前提说明

数据库:Oracle

二、使用实践

1.批任务中,从任务表中查询数据,并对数据加锁(单表for update)

Sql 脚本如下(示例1):

select * from tableA a 
	where a.dealState = '0' 
	for update;

update tableA a 
	set dealState = '1' 
	where dealState = '0';

commit;

分析说明:

(1)“select … for update” 语句,会对查询结果集中的数据,加上行级锁。加行级锁后,当前事务提交或回滚前,其他事务不能修改这些被锁的数据。但是,不在结果集中的数据,没有加行级锁,其他事务可以修改。
(2)如果多个线程,同时执行对同一个表的 “for update” 语句,则只有一个线程可以执行,其他线程都会等待该线程,直到该线程的事务提交或回滚(多个线程串行执行"for update"语句);当该线程执行完成后,剩余线程中的一个线程会开始执行查询,另外的线程继续等待;依次类推,直到所有的线程都执行完成 。正是因为这样,才能保证多线程时,一条记录只会被一个线程抓到。

2.多表关联查询(多表for update)

Sql 脚本如下(示例2):

select * from tableA a ,tableB b
	where a.id = b.id 
	and a.id = '1' 
	for update;

分析说明:
(1)多表关联查询时,会对每个表被查询出来的数据行加行级锁。如示例2中,a.id=‘1’ 、 b.id=‘1’ 的数据,都会被加行级锁。
(2)多个线程同时执行示例2的SQL时,只有一个线程可以执行查询,其他线程都会等待,直到该线程的事务提交或回滚。
(3)当一个线程执行示例2的SQL时,其他线程也不能执行以下SQL :select * from tableA a for update 或 select * from tableB b for update ,即:也不能对单表tableA 或 tableB执行 “for update”,必须要等待当前线程的事务提交或回滚后,才能执行。


三、参考文献

1、for update的作用和用法

文献摘录:
for update仅适用于InnoDB,且必须在事务处理模块(BEGIN/COMMIT)中才能生效。
for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询、但不能更新被加锁的数据行。如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。
行锁永远是独占方式锁。只有当出现如下之一的条件,才会释放共享更新锁:
(1)执行提交(COMMIT)语句。
(2)退出数据库(LOG OFF)。
(3)程序停止运行。

2、ORACLE锁机制以及For update语句

文献摘录:
摘录一:
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。

摘录二:
锁在用户修改之前就发挥作用:
Select …for update(nowait)
Select * from tab1 for update
用户发出这条命令之后,oracle将会对返回集中的数据建立行级封锁,以防止其他用户的修改。
如果此时其他用户对上面返回结果集的数据进行dml或ddl操作都会返回一个错误信息或发生阻塞。
(1)对返回结果集进行update或delete操作会发生阻塞。
(2)对该表进行ddl操作将会报:Ora-00054:resource busy and acquire with nowait specified.
原因分析
此时Oracle已经对返回的结果集上加了排它的行级锁,所有其他对这些数据进行的修改或删除操作都必须等待这个锁的释放,产生的外在现象就是其他的操作将发生阻塞,等待当前这个操作commit或rollback.
同样这个查询的事务将会对该表加表级锁,不允许对该表的任何ddl操作,否则将会报出ora-00054错误::resource busy and acquire with nowait specified.

摘录三:
当一个用户发出select…for update的操作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞。需要等另一个会话结束之后才可继续执行。可以通过发出 select… for update nowait的语句来避免发生阻塞,如果资源已经被另一个会话锁定,则会返回以下错误:Ora-00054:resource busy and acquire with nowait specified.

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值