主题:   最近在看Hibernate的缓存,有一点没搞清楚

精华帖 (0) :: 良好帖 (0) :: 入门帖 (13) :: 隐藏帖 (0) 
作者 正文
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 15:18    关键字:   Hibernate           

我想问一下,hibernate在事务提交后一级缓存的实例是如何和二级缓存同步的?用到那些机制哪?










声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。

相关文章:   对robbin所说Hibernate缺陷的一些不理解   Hibernate中如何通过父节点查询所有子节点?

推荐链接:   免费下载IBM社区版软件,体验高效开发.   京沪穗蓉四地免费注册,SOA技术高手汇聚交锋.
返回顶端  1楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:18  
alex22222
等级: 初级会员
alex22222的博客:alex22222

文章: 3
积分: 4

       时间: 2007-06-01 15:20    评级:   11111 (0位会员评分)          

这个问题我也想搞清楚

返回顶端  2楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:20   我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 15:34    评级:   11111 (0位会员评分)          

事务提交后,一级缓存中的数据会被更新到数据库,如果二级缓存设置为读写,那么这份数据会同时更新到二级缓存。
你问的问题相当于:事务提交后一级缓存中的数据怎么同步到数据库。

返回顶端  3楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:34  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 15:41    评级:   11111 (0位会员评分)          

不是的 一级缓存的数据,其实在h执行相关的save,insert的时候已经提交到数据库的脏数据里面了。
我想问的是一级缓存是利用什么机制 来同步二级缓存的,有谁知道吗?

返回顶端  4楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:41  
我来评分:  请先 登录
抛出异常的爱
等级: 5钻会员
抛出异常的爱的博客:天使不喜欢看代码

文章: 5237
积分: 2512
来自: 北京
圈子: 盘古党

       时间: 2007-06-01 15:45    评级:   11111 (1位会员评分)          

查询。
脏了丢掉/

返回顶端  5楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 21:15  
我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 15:51    评级:   11111 (0位会员评分)          

ellie4c 写道
不是的 一级缓存的数据,其实在h执行相关的save,insert的时候已经提交到数据库的脏数据里面了。
我想问的是一级缓存是利用什么机制 来同步二级缓存的,有谁知道吗?

你说hibernate在执行save操作时会提交数据到数据库,你在哪里看到的结论,你用的是什么数据库,支持事务吗,你不会用的mysql的myisam吧
返回顶端  6楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:51  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 15:54    评级:   11111 (0位会员评分)          

你的意思是不是指 拿一级缓存的PO去查数据库,如果返回对象的话则 更新数据库,如果没返回则 通知二级缓存 丢掉数据?是不是这样的?hibernate也是这样的马?

返回顶端  7楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:54  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 15:54    评级:   11111 (0位会员评分)          

你的意思是不是指 拿一级缓存的PO去查数据库,如果返回对象的话则 更新二级缓存,如果没返回则 通知二级缓存 丢掉数据?是不是这样的?hibernate也是这样的马?

返回顶端  8楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:54  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 15:59    评级:   11111 (0位会员评分)          

ahuaxuan 写道
ellie4c 写道
你说hibernate在执行save操作时会提交数据到数据库,你在哪里看到的结论,你用的是什么数据库,支持事务吗,你不会用的mysql的myisam吧

这里的提交是脏提交,是提交到事务本身的数据空间里面,真正的提交是在执行tx.commit

返回顶端  9楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 15:59  
我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 16:00    评级:   11111 (0位会员评分)          

ellie4c 写道
你的意思是不是指 拿一级缓存的PO去查数据库,如果返回对象的话则 更新二级缓存,如果没返回则 通知二级缓存 丢掉数据?是不是这样的?hibernate也是这样的马?

第一,如果你的数据库支持事务,而且默认隔离级别是读写已提交的话(大部分数据库是这样),是不会出现什么脏数据的。可以仔细阅读一下事务和隔离级别,和不同隔离级别所能解决的情况。读写已提交就是解决脏读问题的
第二,一级缓存中存放的就是持久对象,那为什么要查数据库呢,看来你对hibernate管理的对象的3种状态理解不深刻,持久状态的对象就代表数据库中的记录




主题:   最近在看Hibernate的缓存,有一点没搞清楚

精华帖 (0) :: 良好帖 (0) :: 入门帖 (13) :: 隐藏帖 (0) 
作者 正文
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 16:12    评级:   11111 (0位会员评分)          

[quote="ahuaxuan第一,如果你的数据库支持事务,而且默认隔离级别是读写已提交的话(大部分数据库是这样),是不会出现什么脏数据的。可以仔细阅读一下事务和隔离级别,和不同隔离级别所能解决的情况。读写已提交就是解决脏读问题的

这个我很清楚地,你大概没搞清楚我的问题,这个算了,
我想问你,事务里面的一二级缓存是怎么实现同步的,比如事务里面更新了一个对象,h什么时候通知二级缓存同步对象的状态,以及h是怎么知道什么时候更新二级缓存,什么时候从二级里面删除数据

返回顶端  11楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:12  
我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 16:22    评级:   11111 (0位会员评分)          

ellie4c 写道

这个我很清楚地,你大概没搞清楚我的问题,这个算了,
我想问你,事务里面的一二级缓存是怎么实现同步的,比如事务里面更新了一个对象,h什么时候通知二级缓存同步对象的状态,以及h是怎么知道什么时候更新二级缓存,什么时候从二级里面删除数据

1,之前你说的有一个脏提交的概念,这个我不知道你是什么意思,你是指发送sql语句给数据库吗。
但是调用save方法并不会发送sql语句到db,除非你再调用flush方法。

2,我说了:什么时候把数据同步到数据库,什么时候就把数据同步到二级缓存。

返回顶端  12楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:23  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 16:27    评级:   11111 (0位会员评分)          

ahuaxuan 写道
ellie4c 写道

这个我很清楚地,你大概没搞清楚我的问题,这个算了,
我想问你,事务里面的一二级缓存是怎么实现同步的,比如事务里面更新了一个对象,h什么时候通知二级缓存同步对象的状态,以及h是怎么知道什么时候更新二级缓存,什么时候从二级里面删除数据

1,之前你说的有一个脏提交的概念,这个我不知道你是什么意思,你是指发送sql语句给数据库吗。
但是调用save方法并不会发送sql语句到db,除非你再调用flush方法。

2,我说了:什么时候把数据同步到数据库,什么时候就把数据同步到二级缓存。

怎么同步法?我想知道的是算法,一级缓存里面有一堆对象,怎么通知二级缓存取去执行更新或删除?
返回顶端  13楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:27  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 16:29    评级:   11111 (0位会员评分)          

ellie4c 写道
ahuaxuan 写道
ellie4c 写道

这个我很清楚地,你大概没搞清楚我的问题,这个算了,
我想问你,事务里面的一二级缓存是怎么实现同步的,比如事务里面更新了一个对象,h什么时候通知二级缓存同步对象的状态,以及h是怎么知道什么时候更新二级缓存,什么时候从二级里面删除数据

1,之前你说的有一个脏提交的概念,这个我不知道你是什么意思,你是指发送sql语句给数据库吗。
但是调用save方法并不会发送sql语句到db,除非你再调用flush方法。

2,我说了:什么时候把数据同步到数据库,什么时候就把数据同步到二级缓存。

怎么同步法?我想知道的是算法,一级缓存里面有一堆对象,怎么通知二级缓存取去执行更新或删除?
讲的详细点就是 怎么让二级缓存知道,一级缓存里面的这个对象我应该更新,那个对象我应该删除?
返回顶端  14楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:30  
我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 16:41    评级:   11111 (0位会员评分)          

我 的理解是在事务提交的时候,首先在二级缓存中根据id找到对应的数据,然后通过session中的指令来判断是更新这个数据还是删除这个数据,通过这样的 方法,同步了二级缓存之后,再向db发送sql语句,随后向db发送事务提交指令,但我没有看过源代码,应该是类似这样的

也有可能是在事务提交之后更新二级缓存,这样也许更合理,因为如果事务回滚,二级缓存就根本都不会涉及到了

返回顶端  15楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:51  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 16:51    评级:   11111 (0位会员评分)          

这样的话 如果一个对象有多个操作指令的话 比如insert(a),update(a),delete(a)全部在一个事务里面的话,这样同步起来代价就太大了,不知道其他看过代码的人 有没有什么想法

返回顶端  16楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:51  
我来评分:  请先 登录
ahuaxuan
等级: 2钻会员
ahuaxuan的博客:ahuaxuan

性别:
文章: 499
积分: 1156
来自: 上海
圈子: JBPM @net

       时间: 2007-06-01 16:53    评级:   11111 (0位会员评分)          

ellie4c 写道
这样的话 如果一个对象有多个操作指令的话 比如insert(a),update(a),delete(a)全部在一个事务里面的话,这样同步起来代价就太大了,不知道其他看过代码的人 有没有什么想法

第一你要考虑到实际开发中有没有这种问题,第二,save之后的update只不过是操作一级缓存,没有同步的问题,delete也是如此,怎么会有同步的问题???
返回顶端  17楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:53  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-01 16:58    评级:   11111 (0位会员评分)          

这是算法里面应该考虑的一种情况,我们不要偏离主题,你上面的根据指令来判断 应该会有这种情况,我想听听有没有那位高手看懂过里面的算法实现?我一向觉得不能只会用。

返回顶端  18楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-01 16:58  
我来评分:  请先 登录
huangyiiiiii
等级: 初级会员
huangyiiiiii的博客:codeplayer

性别:
文章: 84
积分: 80
圈子: Python

       时间: 2007-06-03 01:31    评级:   11111 (0位会员评分)          

hibernate 没用过,不过根据我用另一个python下的类似hibernate的ORM的经验,你们所谓的一级二级缓存应该是这样的吧:

代码
  1. session = create_session()  
  2. user = User(name='hello',...) # 这个是所谓的二级缓存?  
  3. session.save(user) # 这里还没有实际操作数据库 莫非就是你们所谓的更新了一级缓存?  
  4. session.flush() # 这里修改了数据库了  

不过在我看来这里并没有两级缓存,user.save() 时只是让 ORM 记录下来有一个 user 需要 save 了。包括属性的修改也是如此,当修改一个属性的值时,ORM 会先记下这个需要更新的对象。
也就是说在 user.save() 后,session.flush() 前查询 user 表,应该是得不到刚创建的这个 user 对象的。
ORM 在最后 session.flush() 时要干比较多的事情,根据所记录下的对象的保存修改删除等变化,并通过分析各个表之间的外键关联等,得出一个合适的 SQL 实际执行的顺序,这里用到的算法叫做 topological sort。
另外 SQLAlchemy 里还有个像是缓存的东西:Identity Map(简单搜了一下,这个概念应该是来自 Hibernate 的),莫非这就是你们所说的一级缓存?不过我觉得这东西就作用来看应该不能算是缓存,只是用来保持数据一致性的。
返回顶端  19楼
浏览发表者的主页 阅读会员资料 发送站内短信   最后更新:2007-06-03 01:31  
我来评分:  请先 登录
ellie4c
等级: 初级会员
ellie4c的博客:ellie4c

文章: 20
积分: 27
圈子: Tapestry

       时间: 2007-06-03 10:26    评级:   11111 (0位会员评分)          

我最近在看它的源码,没什么用,不过我觉得这样的算法大家觉得行不行,就是orm框架 每次都记录一级缓存里面对象的最后的操作状态,不管它前面执行过么操作,在最后提交以后遍历整个一级缓存的map同步。
如果事
insert:新增到二级缓存
update:新增或更新到二级缓存
delete:查找二级缓存找到就删除
select:不做操作,
但是select操作会发生一种例外就是先insert/update再select所以
select操作只是从二级缓存到一级缓存或者DB到一级的时候记录select操作,如果这个对象再一级缓存里面已经存在,就算他再次被查找到也不去更新他的select操作。这样的算法大家看看有没有什么问题,还有其他的好点的算法吗?



session的一级缓存中的对象只有该session自己能取到,其他session是取不到的,所以不存在事务问题,实际所有操作都在一个事务中。

而sessionFactory的二级缓存是所有session共用的,所以要考虑事务问题,在一个session对数据进行操作时,需要保证对于 其他session不管是查询数据库还是查询二级缓存取得的数据必须是一致的,即如果二级缓存中有缓存的数据,那么该数据和数据库中的数据是一致的。

因此如果一个session中对数据进行了修改,那么只有在它把事务提交后才会把数据更新到二级缓存中(如果是读写的)。
具体来说,如果在一个session中修改了一条数据,在它还没有写到数据库时,此时数据库和二级缓存中的数据仍然是一致的,它不会去改变二级缓 存中的数据;在数据flush刷出,写到数据库中后,但还没有提交,此时如果有其他session要从数据库中读取该数据的话应该是等待该修改事务的提 交,因此该修改数据的session会将二级缓存中的该id对应的数据对象失效掉(或者说锁定),不让其他session从二级缓存中取该数据,以保持和 数据库的一致性;当session将事务提交后会将修改后的数据更新到二级缓存中。

对于没有修改的从数据库中读到的数据都会更新到二级缓存中(当然必须设定了该对象类使用二级缓存)。