关于oracle锁机制(一悲观锁与乐观锁)
2014-03-10 14:03
239 查看
一.悲观锁
当用户想要修改一条数据时,根据键盘上的输入的数据,应用将提供绑定变量的值,然后重新利用这些绑定的变量的值作为过滤条件去查询这一行,这一次会锁定这一行,不允许其他会话更新。
在试图更新前就把记录锁住了,我们很悲观,对于这一行能不能保持未改变很是怀疑。
注意:
1.如果在查询这条数据和锁这条数据之间,有人做了修改,那么就会得到0行,说明屏幕上的数据是过时的。
2.如果在查寻这条数据时另一个用户正在更新,那么会得到ORA-00054:resource
busy。
应用范围:仅用于有状态或有连接的环境,也就是说你的应用和数据库有一条持续的连接,而且至少再事务生存期中只有你一个人使用这条连接。c/s模式。
因为根据屏幕的输入应用要反查数据库,看对应的数据有没有变化,没变化就加锁,在对这行的更新提交了后才释放锁,这个过程要求连接是连续的。
悲观锁的实现:
SQL> variable empno number
SQL> variable ename
vachar2(20)
SQL> variable ename varchar2(20)
SQL> variable sal number
SQL> exec :empno :=7934; :ename :='MILLER'; :sal :=1300;
--应用根据屏幕的输入绑定变量(empno,ename,sal)
select empno,ename,sal from emp where empno =:empno and decode(ename,:ename,1)=1 and decode(sal,:sal,1)=1 for update nowait
--反查数据库看相应的数据利用应用最初绑定的变量的值能查到不,如果能查到就给这行数据加锁。
update emp set ename= :ename,sal=:sal where empno=:empno;
commit;
--执行更新,释放锁。
二.乐观锁
乐观锁的实现(使用版本列的乐观锁定):
一.查询出要更新的字段的值,这里与悲观锁定有两个不同的地方:1.在表里多了一个字段(last_mod用于记录行的版本,如果有更新他业会更新)2.查处记录然后绑定变量但不锁定此行。
SQL> variable deptno number
SQL> variable dname varchar2(14)
SQL> variable loc varchar2(13)
SQL> variable last_mod varchar2(50)
SQL>
SQL> begin
2 :deptno
:=10;
3 select
dname,loc,to_char(last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR')
4 into
:dname,:loc,:last_mod
5 from
dept
6 where
deptno =:deptno;
7 end;
8 /
二.执行以下语句更新,要是更新一行的话说明在这个会话更新前没有人对此记录进行更新,这里主要靠第4行来验证记录是否被更新;但如果更新了0行,说明在此会话查询出记录但在修改记录前有会话对此记录做了修改(也利用此逻辑更新的),并将last_mod=systimestamp,所以last_mod
=to_timestamp_tz(:last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR')条件不满足。
SQL>
update dept
2 set
dname=initcap(:dname),last_mod=systimestamp
3 where
deptno =:deptno
4 and
last_mod =to_timestamp_tz(:last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR');
三。但是如果执行更新失败的话,应该怎么办呢。oracle推荐由存储过程来维护last_mod这一字段,更新返回0行时,抛给客户一个异常,让客户知道更新失败了。
乐观锁的实现(使用校验和的乐观锁定ORA_HASH):
一.查询要修改的行,并且算出这一行的散列值,并绑定在:hash。
SQL> variable
deptno number
SQL> variable dname varchar2(14)
SQL> variable loc varchar2(13)
SQL> variable hash number
SQL> begin
2 select
deptno,dname,loc,
3 ora_hash(dname
|| '/' || loc) hash
4 into
:deptno,:dname,:loc,:hash
5 from
dept
6 where
deptno=10;
7 end;
8 /
二。更新时检查这一行的散列值更更新之前查询出来的散列值是否一样。
SQL> exec :dname:=lower(:dname);
PL/SQL procedure successfully completed.
SQL> update dept
2 set
dname=:dname
3 where
deptno=:deptno and ora_hash(dname || '/' || loc) =:hash
4 /
1 row updated.
当用户想要修改一条数据时,根据键盘上的输入的数据,应用将提供绑定变量的值,然后重新利用这些绑定的变量的值作为过滤条件去查询这一行,这一次会锁定这一行,不允许其他会话更新。
在试图更新前就把记录锁住了,我们很悲观,对于这一行能不能保持未改变很是怀疑。
注意:
1.如果在查询这条数据和锁这条数据之间,有人做了修改,那么就会得到0行,说明屏幕上的数据是过时的。
2.如果在查寻这条数据时另一个用户正在更新,那么会得到ORA-00054:resource
busy。
应用范围:仅用于有状态或有连接的环境,也就是说你的应用和数据库有一条持续的连接,而且至少再事务生存期中只有你一个人使用这条连接。c/s模式。
因为根据屏幕的输入应用要反查数据库,看对应的数据有没有变化,没变化就加锁,在对这行的更新提交了后才释放锁,这个过程要求连接是连续的。
悲观锁的实现:
SQL> variable empno number
SQL> variable ename
vachar2(20)
SQL> variable ename varchar2(20)
SQL> variable sal number
SQL> exec :empno :=7934; :ename :='MILLER'; :sal :=1300;
--应用根据屏幕的输入绑定变量(empno,ename,sal)
select empno,ename,sal from emp where empno =:empno and decode(ename,:ename,1)=1 and decode(sal,:sal,1)=1 for update nowait
--反查数据库看相应的数据利用应用最初绑定的变量的值能查到不,如果能查到就给这行数据加锁。
update emp set ename= :ename,sal=:sal where empno=:empno;
commit;
--执行更新,释放锁。
二.乐观锁
乐观锁的实现(使用版本列的乐观锁定):
一.查询出要更新的字段的值,这里与悲观锁定有两个不同的地方:1.在表里多了一个字段(last_mod用于记录行的版本,如果有更新他业会更新)2.查处记录然后绑定变量但不锁定此行。
SQL> variable deptno number
SQL> variable dname varchar2(14)
SQL> variable loc varchar2(13)
SQL> variable last_mod varchar2(50)
SQL>
SQL> begin
2 :deptno
:=10;
3 select
dname,loc,to_char(last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR')
4 into
:dname,:loc,:last_mod
5 from
dept
6 where
deptno =:deptno;
7 end;
8 /
二.执行以下语句更新,要是更新一行的话说明在这个会话更新前没有人对此记录进行更新,这里主要靠第4行来验证记录是否被更新;但如果更新了0行,说明在此会话查询出记录但在修改记录前有会话对此记录做了修改(也利用此逻辑更新的),并将last_mod=systimestamp,所以last_mod
=to_timestamp_tz(:last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR')条件不满足。
SQL>
update dept
2 set
dname=initcap(:dname),last_mod=systimestamp
3 where
deptno =:deptno
4 and
last_mod =to_timestamp_tz(:last_mod,'DD-MON-YYYY HH.MI.SSXFF AM TZR');
三。但是如果执行更新失败的话,应该怎么办呢。oracle推荐由存储过程来维护last_mod这一字段,更新返回0行时,抛给客户一个异常,让客户知道更新失败了。
乐观锁的实现(使用校验和的乐观锁定ORA_HASH):
一.查询要修改的行,并且算出这一行的散列值,并绑定在:hash。
SQL> variable
deptno number
SQL> variable dname varchar2(14)
SQL> variable loc varchar2(13)
SQL> variable hash number
SQL> begin
2 select
deptno,dname,loc,
3 ora_hash(dname
|| '/' || loc) hash
4 into
:deptno,:dname,:loc,:hash
5 from
dept
6 where
deptno=10;
7 end;
8 /
二。更新时检查这一行的散列值更更新之前查询出来的散列值是否一样。
SQL> exec :dname:=lower(:dname);
PL/SQL procedure successfully completed.
SQL> update dept
2 set
dname=:dname
3 where
deptno=:deptno and ora_hash(dname || '/' || loc) =:hash
4 /
1 row updated.
相关文章推荐
- 【Oracle】悲观锁和乐观锁
- oracle 数据库悲观锁和乐观锁
- 事物处理机制---乐观锁(version详细使用)和悲观锁
- SQL Server 锁机制 悲观锁 乐观锁 实测解析
- Oracle 乐观锁、悲观锁
- Oracle创建悲观锁和乐观锁
- Oracle锁定:悲观与乐观锁详解
- Oracle悲观锁和乐观锁
- Hibernate优化(五) 之事务隔离机制(悲观锁、乐观锁)
- Oracle悲观锁和乐观锁
- Oracle的悲观锁和乐观锁---摘抄
- 关于Oracle归档进程的运行机制
- Oracle的悲观锁和乐观锁
- 关于高并发 悲观锁 乐观锁
- 909422229__Mysql与Oracle区别以及悲观锁与乐观锁机制
- oracle的悲观锁与乐观锁
- 关于Oracle的锁机制
- mysql 锁机制 悲观锁与乐观锁
- oracle的乐观锁和悲观锁
- 关于悲观锁和乐观锁的区别(最直观理解)