zoukankan      html  css  js  c++  java
  • 乐观锁和悲观锁(个人认为是对数据库锁的机制的一个宏观应用)

    悲观锁与乐观锁
    ----------
    悲观锁【Pessimistic Locking】
    顾名思义就是采用一种悲观的态度来对待事务并发问题,我们认为系统中的并发更新会非常频繁,并且事务失败 了以后重来的开销很大,这样以来,我们就需要采用真正意义上的锁来进行实现。悲观锁的基本思想就是每次一 个事务读取某一条记录后,就会把这条记录锁住,这样其它的事务要想更新,必须等以前的事务提交或者回滚解 除锁
    假如我们数据库事务的隔离级别设置为读取已提交或者更低,那么通过悲观锁,我们控制了不可重复读的问题, 但是不能避免幻影读的问题,因为要想避免我们就需要设置数据库隔离级别为Serializable,而一般情况下我们都 会采取读取已提交或者更低隔离级别,并配合乐观或者悲观锁来实现并发控制,所以幻影读问题是不能避免的,如 果想避免幻影读问题,那么你只能依靠数据库的serializable隔离级别(幸运的是幻影读问题一般情况下不严重)
    悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
    实现方式
    JDBC方式:在JDBC中使用悲观锁,需要使用select for update语句,假如我们系统中有一个Account的类,我们可以采用如下的方式来进行:Select * from Account where ...(where condition).. for update.
    当使用了for update语句后,每次在读取或者加载一条记录的时候,都会锁住被加载的记录,那么当其他事务如果要更新或者是加载此条记录就会因为不能获得锁而阻塞,这样就避免了不可重复读以及脏读的问题,但是其他事务还是可以插入和删除记录,这样也许同一个事务中的两次读取会得到不同的结果集,但是这不是悲观锁锁造成的问题,这是我们数据库隔离级别所造成的问题。
    最后还需要注意的一点就是每个冲突的事务中,我们必须使用select for update 语句来进行数据库的访问,如果一 些事务没有使用select for update语句,那么就会很容易造成错误,这也是采用JDBC进行悲观控制的缺点。
    乐观锁【Optimistic Locking】
    乐观锁是在同一个数据库事务中我们常采取的策略,因为它能使得我们的系统保持高的性能的情况下,提高很好的并发 访问控制。乐观锁,顾名思义就是保持一种乐观的态度,我们认为系统中的事务并发更新不会很频繁,即使冲突了也没事, 大不了重新再来一次。它的基本思想就是每次提交一个事务更新时,我们想看看要修改的东西从上次读取以后有没有被其 它事务修改过,如果修改过,那么更新就会失败。(因此能够解决第二类丢失修改问题)
    因为乐观锁其实并不会锁定任何记录,所以如果我们数据库的事务隔离级别设置为读取已提交或者更低的隔离界别,那么 是不能避免不可重复读问题的(因为此时读事务不会阻塞其它事务),所以采用乐观锁的时候,系统应该要容许不可重复 读问题的出现。
    需要注意的是,乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局限性,由于乐观锁机制是在我们的系统中 实现,来自外部系统的用户更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。在系统设计阶段,我 们应该充分考虑到这些情况出现的可能性,并进行相应调整(如将乐观锁策略在数据库存储过程中实现,对外只开放基于此 存储过程的数据更新途径,而不是将数据库表直接对外公开)。
    实现方式:
    大多是基于数据版本 ( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解 决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。 
    读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的 当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
    假如系统中有一个Account的实体类,我们在Account中多加一个version字段,那么我们JDBC Sql语句将如下写:
    Select a.version....from Account as a where (where condition..)
    Update Account set version = version+1.....(another field) where version =?...(another contidition)
    理解死锁:http://www.cnblogs.com/happyhippy/archive/2008/11/14/1333922.html 
  • 相关阅读:
    docker学习1--dockerfile
    关于java php go 中AES加解密秘钥长度问题
    API设计中响应数据格式用json的优点
    mac air中编译安装swoole
    跟踪填写表单重复信息
    JS简单实现点赞操作
    JS验证码生成(入门级别)
    注册页面(入门)
    登录表单(入门简单)
    简单的UDP编程1
  • 原文地址:https://www.cnblogs.com/malaikuangren/p/2435392.html
Copyright © 2011-2022 走看看