oracle中锁表 for update 、for update nowait

场景

业务操作需要在数据库尝试先锁表,然后事务内更新。

概述

1)、加锁查询:查询时并锁定记录,锁定记录后其他线程不可以更新记录,只能自己失误内更新,但是其他线程可以查询功能。
2)、不加锁查询:查询时没有不锁定记录。
3)、目的:select …for update 的功能目的是为了本事务内锁表,避免出现脏数据。

定义

如果在select语句后加入了for update, 则Oracle一旦发现(符合查询条件的)这批数据正在被修改,则不会发出该select语句查询,直到数据被修改结束(被commit),马上自动执行这个select语句;同样,如果该查询语句发出后,其他线程需要修改这批数据(中的一条或几条),它也必须等到查询结束后(commit)后,才能修改。

一、相似点

1、都是用来修改数据
纯update修改数据操作,如果有其他事务锁表,则会进入无任何提示等待,就好像页面一直加载没有提示一样。
2、都会形成锁
2.1)、都是查询锁,可以锁定行记录,出于某种目的不让别人在纯粹过程改事务或者commit的之前内修改记录。
2.2)、锁住记录,在自己的事务内一样可以更新。
2.3)、for update 和 for update nowait 加上的是一个行级锁,也就是只有符合where条件的数据被加锁。(for update 和 for update nowait 如果对应的select语句有where条件时,只会锁住对应的where条件下的数据,而不会锁住整张表中的所有数据。)

二、不同点

1)、for update锁住表或者锁住行,只允许当前事务进行操作(读写),其他事务被阻塞,直到当前事务提交或者回滚,被阻塞的事务自动执行。
2)、for update nowait 锁住表或者锁住行,只允许当前事务进行操作(读写),其他事务被拒绝,事务占据的statement连接也会被断开。
3)、for update nowait 和 for update 都会对所查询到得结果集进行加锁,不同的是,如果另外一个线程正在修改结果集中的数据,for update nowait 不会进行资源等待,只要发现结果集中有些数据被加锁,立刻返回 “ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”,并且关闭statement。

三、总结

1)、for update nowait 防止无限期的等待。
2)、select … for update/for update nowait 感觉纯粹就是用来查询锁定记录的,本身没有做任何操作,保证数据的一致性。
3)、用update语句来更改数据时,可能会因为加不上锁而没有响应地、莫名其妙地等待,如果在此之前,用 for update NOWAIT查询语句将要更改的数据尝试性地加锁,不需要等待的加锁,就可以通过立即返回的错误,并关闭statement连接。

四、拓展

1)、select rowid from table_name; 属于不加锁查询,但是在plsql中可以更新记录和for update 效果相同,都可以更新记录,更新的时候锁定表中的行。
2)、rowid是oracle中伪劣,是用来快速定位数据,比序列还快。常常用来大批量更新,删除数据。
3)、select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update of a.pkid 只锁定Table1中满足条件的行
for update 是把所有的表都锁定,但是 for update of 是根据of 后表的条件锁定相对应的表记录。
4)、select * from TTable1 for update 锁定表的所有行,其他线程只能读不能写
5)、select * from Table1 a join Table2 b on a.pkid=b.pkid for update 锁定两个表的所有记录
select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update 锁定两个表的中满足条件的行

发布了66 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq125281823/article/details/103943011