【Oracle】从select for update开始
2016-08-28 21:18
459 查看
从select for update开始
开发多用户、数据库驱动的应用时,最大的难点之一时:一方面要力争取得最大限度地并发访问,与此同时还要确保每个用户以一致的方式读取和修改数据。为此就有了锁定(locking)机制。AE锁是一个版本锁,这是oracle 11g新增的。
TX(事务处理锁):修改数据的事务在执行期间会获得这种锁。
TM(DML队列)锁和DDL锁:在你修改一个对象的内容(对应TM锁)或对象本身(对应DDL锁)时,这些锁可以确保对象的结构不被修改。
闩(latch)和Mutex:这是Oracle的内部锁,用来协调对其共享数据结构的访问。
数据库中有5条常见的DML语句可能会阻塞,具体是:INSERT、UPDATE、DELETE、MERGE和SELECT FOR UPDATE。对于一个阻塞的SELECT FOR UPDATE,解决的方案很简单:只需要增加NOWAIT子句,它就不会阻塞了。
下面我们看看测试用例。
User1连接数据库。
C:\Users\Administrator>sqlplus / as sysdba SQL*Plus: Release 11.2.0.1.0 Production on 星期日 8月 28 20:27:46 2016 Copyright (c) 1982, 2010, Oracle. All rights reserved. 连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> create table test(name varchar2(20)) 2 ; 表已创建。 SQL> insert into test values('testname'); 已创建 1 行。 SQL> commit; SQL> update test set name='nameupdate';
User1在如上的操作中,创建了表,对表进行了insert操作,提交(commit)事务。对表进行了update操作(并没有提交事务,此时,test表的这一行数据被锁住了)
User2连接数据库。再打开一个sqlplus.
C:\Users\Administrator>sqlplus / as sysdba SQL*Plus: Release 11.2.0.1.0 Production on 星期日 8月 28 20:31:04 2016 Copyright (c) 1982, 2010, Oracle. All rights reserved. 连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> select name from test for update;
发现,由于前一个session开始的事务没有结束,此时再开启一个事务后,尝试使用for update对test表进行锁定,但是数据库处于挂起状态。
User1回滚后,锁被释放。
SQL> rollback;
User2得到结果
NAME -------------------- testname
User1继续
SQL> update test set name='nameupdate';
User2继续,增加nowait,则立即返回了错误。
SQL> select name from test for update nowait; select name from test for update nowait * 第 1 行出现错误: ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
而如果我们想查询的数据正在被修改,那么不会产生脏读(脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的)的情况。
SQL> select name from test where name='testname' for update nowait; select name from test where name='testname' for update nowait * 第 1 行出现错误: ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
for update nowait这种锁,称作悲观锁。因为我们怀疑数据会被修改,所以使用它,如果数据正在被修改,那我们选择(select)该数据时立马能知道结果,如果某条数据正在被修改,那么会得到ORA-00054的错误,如果修改已提交,那么查不到老数据。(参考[1])
参考资料
(1)Oracle_Database_9i10g11g编程艺术深入数据库体系结构第2版181页,锁定问题,6.2.2悲观锁定
相关文章推荐
- 在客户端处理Oracle的数据行加锁问题(select for update)
- oracle Select For update语句浅析
- Oracle select for update & for update of
- oracle select语句中,不加for update和加 for update和for update nowait区别
- Oracle Select...for update作用
- Oracle编辑数据时提示:这些查询结果不可更新,请使用ROWI或者SELECT……FOR UPDATE获得可更新结果
- select ... for update在mysql和oracle间锁行为的比较
- Oracle中的select for update
- Oracle编辑数据时提示:这些查询结果不可更新,请使用ROWI或者SELECT……FOR UPDATE获得可更新结果。
- oracle的select for update
- Oracle中的select for update
- oracle用select for update 中断后无法操作表的处理:杀掉SESSION
- Oracle基础知识(二十四) - select for update
- Oracle数据之select * for update恢复小结(1)
- Oracle中select ... for update的用法
- 用锁实现SQLSERVER中并发控制--实现Oracle中select .... for update功能
- Oracle:for update 和select t.*,t.rowid编辑数据的区别
- Oracle的select for update
- oracle select for update
- SELECT ... FOR UPDATE(WAIT/NOWAIT)命令与ORACLE锁