悲观锁乐观锁和一级缓存

 

悲观锁乐观锁和一级缓存

 

悲观锁和乐观锁
悲观锁和乐观锁就是为了解决数据库的并发性,数据库的隔离级别就是和并发性紧密相关的。数据库隔离级别越高,并发性性也越差。

悲观锁:在一个用户对一个数据进行查看或修改的时候,在他放弃对数据的占有前,其他用户无法操作该数据。加锁以后,lazy属性会失效。
悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改。如果在加锁期间有其他进程需要访问该数据,则会一直等待,直到锁被释放或者超时。
所以悲观锁的并发性不好。

乐观锁:不是锁,是一种冲突检测手段。任何人可以随便改,保存的时候再检查。乐观锁也支持lazy,大多采用版本控制Verson来进行。少数情况下也有用时间戳控制的。
每次更新数据时候对verson+1.如果当前Verson小于等于数据库中的Verson,就认为当前数据是老版本数据,不准许提交。
通过版本来进行控制,每次对数据进行修改以后,数据库中数据都会有一个新的版本号。只有获得了当前最新的版本以后再修改的内容才可以保存进数据库并获得新的版本号。
比如A用户获得了版本1,再其操作过程中数据库中的版本被他人修改到了版本2.。这个时候A用户就不能直接提交他修改后的版本1了,他必须获得当前最新的版本2,在版本2的基础上重新修改才可以提交到数据库。

A,B两个用户同时从数据库取得了相同的数据C(版本0),然后A没有操作,B将C修改以后重新保存入数据库,这个时候数据库中C(版本1),注意版本变成了1.。这个时候A回来了,他也对自己的数据进行了修改以后试图保存进数据库,这个时候就会保存失败,因为他所修改的数据的版本低于当前版本。


Hibernate性能优化策略---缓存
cache和pool的区别
共同点:都是为了提高性能。
区别
Pool的特点
池中的对象通常创建比较耗时,是重量级的。
各个对象间状态相同,比如数据库连接,任何一个数据库连接之间并没有什么区别。从pool中随意取哪一个对象并没有区别,取到就可以。

Cache的特点
其中的数据彼此各不相同。是轻量级的
经常会需要使用。


一级缓存
一级缓存就是Hibernate的session级的缓存。其生命周期也和session一致。

一级缓存很短和session的生命周期一致,一级缓存也叫session级的缓存或事务级缓存

一级缓存中只放实体对象,查询普通属性是不会放到一级缓存里的。
而且不同session间不能共享一级缓存中的数据,因为session中的数据会伴随session的生命周期存在和消亡

Save方法也使用缓存,save的数据也会保存进缓存。

那些方法支持一级缓存:
  get()
  load()
  iterate(查询实体对象)
这些方法支持缓存,当使用他们加载实体对象的时候,都先去缓存中查询是否有匹配数据,如果有就在直接取出使用,如果没有就发sql加载,然后把加载到的数据保存到自己的缓存中。在 session.clear(),session.evict()或者commit以后,缓存中的数据会被清空。
 
如何管理一级缓存:
  session.clear(),session.evict()

一级缓存无法去除或者进行配置,这种情况下可能会出现下面问题:如果我们有大量数据需要一次保存进数据库,如果正常使用一级缓存,一级缓存就会试图把这些数据先全部保存进一级缓存再一次保存进数据库,这样可能导致我们的电脑内存溢出。
 


如何避免一次性大量的实体数据入库导致内存溢出
  先flush,再clear
例如下面代码
public void testCache7() {
  Session session = null;
  try {
   session = HibernateUtils.getSession();
   session.beginTransaction();
   一次性保存1000条数据
   for (int i=0; i<1000; i++) {
    Student student = new Student();
    student.setName("s_" + i);
    session.save(student);
    //每20条数据就强制session将数据持久化
    //同时清除缓存,避免大量数据造成内存溢出
    if ( i % 20 == 0) {
//注意:flush只就缓存中当前数据发出sql,并不会清理缓存
     session.flush();
     session.clear();
    }
   }
   
   session.getTransaction().commit();
  }catch(Exception e) {
   e.printStackTrace();
   session.getTransaction().rollback();
  }finally {
   HibernateUtils.closeSession(session);
  }
 } 
 
如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值