扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:dlxu 来源:IT专家网 2007年9月1日
关键字: ORACLE
在本页阅读全文(共2页)
第四种做法就是采用散列算法。这种做法和第一种做法有点类似,就是把当前数据内容进行传递,最后在提交的时候进行比较。但是区别还是比较大的,第一种做法把整个更新前的数据都copy了下来进行传递,而这种做法只是把数据做了一个散列码,所以传递的数据要小的多,网络负荷也会因此小很多。这种采用散列算法的做法如果在Oracle侧生成散列的话,有三种方法可以生成。第一种就是利用Oracle8i 8.1.5以后的OWA_OPT_LOCK.CHECKSUM函数来进行数据的散列生成比如下面的例子。
|
在这里我用这个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语句:
|
检索结果如下:
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 |
然后执行如下的更新语句:
|
在数据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的开销。建表语句如下所示:
|
同样再执行:
|
语句后,我们再看一下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领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者