Oracle数据库悲观锁与乐观锁详解
初三 其它 1430字 418人浏览 大雪61

这个时候我们发现update 语句就好像select for update语句一样也停住卡在这里,当你第一个session 放开锁定以后update 才能正常运行。当你update 运行后,数据又被你update 语句锁定住了,这个时候只要你update 后还没有commit ,别的session 照样不能对数据进行锁定更新等等。

总之,Oracle 中的悲观锁就是利用Oracle 的Connection 对数据进行锁定。在Oracle 中,用这种行级锁带来的性能损失是很小的,只是要注意程序逻辑,不要给你一不小心搞成死锁了就好。而且由于数据的及时锁定,在数据提交时候就不呼出现冲突,可以省去很多恼人的数据冲突处理。缺点就是你必须要始终有一条数据库连接,就是说在整个锁定到最后放开锁的过程中,你的数据库联接要始终保持住。与悲观锁相对的,我们有了乐观锁。乐观锁一开始也说了,就是一开始假设不会造成数据冲突,在最后提交的时候再进行数据冲突检测。

在乐观锁中,我们有3种常用的做法来实现:

[1]第一种就是在数据取得的时候把整个数据都copy 到应用中,在进行提交的时候比对当前数据库中的数据和开始的时候更新前取得的数据。当发现两个数据一模一样以后,就表示没有冲突可以提交,否则则是并发冲突,需要去用业务逻辑进行解决。

[2]第二种乐观锁的做法就是采用版本戳,这个在Hibernate 中得到了使用。采用版本戳的话,首先需要在你有乐观锁的数据库table 上建立一个新的column ,比如为number 型,当你数据每更新一次的时候,版本数就会往上增加1。比如同样有2个session 同样对某条数据进行操作。两者都取到当前的数据的版本号为1,当第一个session 进行数据更新后,在提交的时候查看到当前数据的版本还为1,和自己一开始取到的版本相同。就正式提交,然后把版本号增加1,这个时候当前数据的版本为2。

当第二个session 也更新了数据提交的时候,发现数据库中版本为2,和一开始这个session 取到的版本号不一致,就知道别人更新过此条数据,这个时候再进行业务处理,比如整个Transaction 都Rollback 等等操作。在用版本戳的时候,可以在应用程序侧使用版本戳的验证,也可以在数据库侧采用Trigger(触发器) 来进行验证。不过数据库的Trigger 的性能开销还是比较的大,所以能在应用侧进行验证的话还是推荐不用Trigger 。

[3]第三种做法和第二种做法有点类似,就是也新增一个Table 的Column ,不过这次这个column 是采用timestamp 型,存储数据最后更新的时间。在Oracle9i 以后可以采用新的数据类型,也就是timestamp with time zone类型来做时间戳。这种Timestamp 的数据精度在Oracle 的时间类型中是最高的,精确到微秒(还没与到纳秒的级别) ,一般来说,加上数据库处理时间和人的思考动作时间,微秒级别是非常非常够了,其实只要精确到毫秒甚至秒都应该没有什么问题。和刚才的版本戳类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK ,否则就是版本冲突。如果不想把代码写在程序中或者由于别的原因无法把代码写在现有的程序中,也可以把这个时间戳乐观锁逻辑写在Trigger 或者存储过程中。

来源:网络 编辑:联动北方技术论坛