科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Oracle中的数据锁定机制全面解析(2)

Oracle中的数据锁定机制全面解析(2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文详细介绍了数据的锁定:悲观锁和乐观锁的使用机制,供大家参考!

作者:dlxu 来源:IT专家网 2007年9月1日

关键字: ORACLE

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

第四种做法就是采用散列算法。这种做法和第一种做法有点类似,就是把当前数据内容进行传递,最后在提交的时候进行比较。但是区别还是比较大的,第一种做法把整个更新前的数据都copy了下来进行传递,而这种做法只是把数据做了一个散列码,所以传递的数据要小的多,网络负荷也会因此小很多。这种采用散列算法的做法如果在Oracle侧生成散列的话,有三种方法可以生成。第一种就是利用Oracle8i 8.1.5以后的OWA_OPT_LOCK.CHECKSUM函数来进行数据的散列生成比如下面的例子。

select owa_opt_lock.checksum (to_char(sysdate,'YYYYMMDDHHMISS') ) from dual

在这里我用这个OWA_OPT_LOCK.CHECKSUM函数对当前的系统时间进行了散列,用这个方法生成的出土的可能性是65536,因为生成的散列算法是一个16位置的值,所以值范围也就是65536个值而已。

第二种散列算法采用Oracle8i 8.1.7以后提供的DBMS_OBFUSCATION_TOOLKIT.MD5方法,不过这个方法不能直接在SQL语句里面使用,需要在存储过程中调用。所以可以先写一个共通的存储过程的Function,然后利用这个function去进行加密。

第三种散列方法就是用Oracle 10g Release1种提供的DBMS_CRYPTO.HASH方法。这个方法可以计算一个SHA-1或者是MD5摘要,所以如果实际情况下使用Oracle 10g的数据库,建议采用这个方法。不过和第二种类似,这个方法也是需要采用存储过程才能够编写,不能直接应用在SQL语句中的。

最后一种做法就是采用Oracle 10g所带有的ORA_ROWSCN函数来进行乐观锁。ORA_ROWSCN是根据系统最后更新时间来进行计算。这个ORA_ROWSCN在默认情况下是采用数据块为单位的,也就是一个数据库块(block)上共享一个ORA_ROWSCN,当数据更新的时候,这个block快的ORA_ROWSCN就会自动更新。所以在默认情况下的话,有可能出现假冲突的情况。比如A,B,C,D四条数据都在一个block上,这个时候A数据更新了,ORA_ROWSCN也会更新,这个时候因为ABCD四条数据存储在一个block上,所以BCD的ORA_ROWSCN也更新过了,其实BCD三条数据并没有更新过,这个就造成了假更新的情况出现。见下面的SQL语句:

select id, name, location, value, ora_rowscn from test

检索结果如下:

ID NAME LOCATION VALUE ORA_ROWSCN
10 ACCOUNTING NEW YORK 1 610795
20 RESEARCH DALLAS 1 610795
30 SALES CHICAGO 1 610795
40 OPERATIONS BOSTON 1 610795

然后执行如下的更新语句:

update test set value=2 where id = 20

在数据commit过后,会发现ORA_ROWSCN发生了变化,如下所示:

ID NAME LOCATION VALUE ORA_ROWSCN
10 ACCOUNTING NEW YORK 1 611151
20 RESEARCH DALLAS 1 611151
30 SALES CHICAGO 1 611151
40 OPERATIONS BOSTON 1 611151

对于这种情况还是可以有办法解决的,就是利用Oracle 9i提供的ROWDEPENDENCIES建表关键字,这个关键字在Oracle9i中是为了增加行依赖性跟踪特性的,支持推进复制。在Oracle10g中有可以用来做行级别的ORA_ROWSCN用了。用这个关键字建表以后,在每行会增加一个隐藏的COLUMN,所以每行会增加6个byte的开销。建表语句如下所示:

 CREATE TABLE TEST

(ID,

NAME,

LOCATION,

VALUE,

CONSTRAINT test_pk PRIMARY KEY(ID))

ROWDEPENDENCIES

AS SELECT deptno, dname, loc, 1 FROM scott.dept

同样再执行:

update test set value=2 where id = 20

语句后,我们再看一下commit过后检索的结果:

ID NAME LOCATION VALUE ORA_ROWSCN
10 ACCOUNTING NEW YORK 1 611370
20 RESEARCH DALLAS 1 611370
30 SALES CHICAGO 1 611370
40 OPERATIONS BOSTON 1 611370

可以看到这次只有id=20的数据的ORA_ROWSCN发生了更新。所以这个时候我们就可以利用ORA_ROWSCN作为乐观锁,用不着专门再增加一个额外的域了。而且这个域是Oracle负责维护的,开销也不是很大,不过需要Oracle 10g才可以使用。

总之,介绍了Oracle的锁定机制,究竟是悲观锁好还是乐观锁好,其实也是不一定的。Oracle中悲观锁还是很不错的,而且从开始的时候就把数据锁定。免除了后面的很多冲突处理。不过悲观锁需要保持一个Oracle连接,在我们常见的B/S应用中,特别是数据先取得,然后让用户再更新,再返回提交这种流程来说,悲观锁是不大可能的。首先是因为B/S应用中,一般是利用一个连接池,在两次Http Request请求都是不同的数据库Connection。而且也不能锁定一个数据太长时间,否则人人都这么锁定,应用很容易进入死锁状态,这个时候就要采用乐观锁了。而在乐观锁中,虽然采用散列的效果不错,网络传输数据会减少很多,而且不用在数据库中增加COLUMN,不过由于散列计算比较占用CPU,所以还是需要仔细考虑一下的。ORA_ROWSCN可以说是比较好的选择,不过第一需要重新建表,第二需要在Oracle10g下才有这个特性,所以也不是到处都可以使用,当一个万金油的。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章