HIbernate——事务并发问题及处理(乐观锁悲观锁)

一、事物并发三种常见问题

1.dirty read 脏读
时间事物A事物B
T1开始事物开始事物
T2查询账户余额为1000
T3汇入100把余额变为1100
T4读取账户余额为1100
T5回滚
T6取款1100
T7提交事物失败

事物A读到了事物B还没有提交的数据

2.non-repeatable read 不可重复读
时间事物A事物B
T1开始事物
T2开始事物
T3查询账户余额为1000
T4汇入100把余额变为1100
T5提交事物
T6
T7查询余额为1100
T8提交事物

事物A第一次读余额为1000,B在中间提交了一次事物把余额改为了1100,事物A再读取余额变为了1100。读取同一个数据得到了了两个不同的结果

3.phantom read 幻读
时间事物A事物B
T1开始事物
T2开始事物
T3查询学生数为10人
T4插入一个学生
T5查询学生数为11人
T6提交事物
T7提交事物

事务A执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,是事务B在这两次查询中间插入或者删除了数据造成的。

不可重复读和幻读的区别在与一个是前者强调更新,后者强调插入和删除。

二、事物隔离机制

1.read uncommitted 可读未提交
2.read committed 可读已提交
3.repeatable read 可重复读
4.serializable 串行化

隔离级别是否脏读是否不可重复读是否幻读
read uncommitted
read committed
repeatable read
serializable

隔离级别越高,效率越低。

一般把事物级别设为2:read committed
如果不设置事物级别,则根据数据库的默认级别来设置,如MySQL默认级别是repeatable read
这里写图片描述

设定Hibernate的事物隔离机级别

1:read uncommitted;2:read committed;4:repeatable read;8:serializable

<property name="hibernate.connection.isolation">2</property>

三、乐观锁和悲观锁

当事务隔离级别设为2(read committed)时,任会出现non-repeatable read和phantom read(很少出现,可以忽略)问题。因此我们需要乐观锁或悲观锁来解决non-repeatable read 问题。

悲观锁

悲观锁假定当前事务操纵数据资源时,可能会有其他事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它影响并发性能,因此应该很谨慎地使用悲观锁。

select … for update

Hibernate3

User u =(User)session.get(User.class,1,LockMode.UPGRADE);

在Hibernate3.6以上的版本中”LockMode”已经不建议使用
Hibernate4

User u =(User)session.get(User.class,1,LockOptions.UPGRADE);

在读取数据时,借助数据库为这条数据上锁,即在sql语句后加上 for update,在这个事物提交前,其他事物无法对这条数据进行改动。

乐观锁

乐观锁假定当前事务操纵数据资源时,不会有其他事务同时访问该数据资源,因此不作数据库层次上的锁定。为了维护正确的数据,乐观锁使用应用程序上的版本控制(由程序逻辑来实现的)来避免可能出现的并发问题。

private int version;
@Version
    public int getVersion() {
        return version;
    }
    public void setVersion(int version) {
        this.version = version;
    }

在表里加上一个version字段,记录当前的版本号,更新数据时version会加1。将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库表当前版本号,则更新,否则就报错。
比如
事物A取出一条记录,当前版本号为0,更改记录后版本号增加1。如果在事物A提交前有个事物B更新了该数据,数据库内的版本号变为了1,A再提交时就会报错。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值