spring事务隔离性问题

ppasky 2012-09-27 03:09:39
我用spring定义了两个事务:
事务1:查表a的第一条记录的id;
事务2:根据id做一些操作,然后删除表a的第一条记录。
两个事务在一个for循环中,不断的取表a的第一条记录,直到删除表中的所有记录。
for(){
事务1;
事务2;
}

但实际运行时出现了这样的情况,第n+1次循环读取了第n次循环中已经删除的id,进行了无效处理。也就是第n次循环中事务2的删除操作还没有commit,n+1次循环中的事务1就进行了查表操作,得到了删除前的数据。

之后我将两个事务合并为一个事务3,就不会出现这种情况。
for(){
事务3;
}

请问各位大牛,这里的事务1和事务2之间没有隔离性么?事务2的修改未提交,事务1就可以读取?
为什么合并成事务3后不同循环中的事务3就可以保证串行操作?

项目用的是Spring+Struts+hibernate,数据库为oracle
...全文
199 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
ppasky 2012-10-27
  • 打赏
  • 举报
回复
搞清楚原因了,是主从库的问题,写了主库还没有更新到从库就从从库读取了,感谢各位的回答。
渭水飞熊 2012-09-29
  • 打赏
  • 举报
回复
你先看下你的Spring定义的传播属性。如果不是每次都新开一个事物的话,你这个仍然不是事务嵌套,虽然是多个方法之间调用,但是却是在同一个事务中。
ppasky 2012-09-29
  • 打赏
  • 举报
回复
呃,没有人遇到过类似的问题么?
ppasky 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

引用 11 楼 的回复:
引用 10 楼 的回复:

你的事务是加在service上的吗?
事务1和事务2是不是分别对应两个service方法?


是的

两个事务不在同一个service也没多大关系吧,这两个事务执行是有先后顺序的,又是单线程,会不会事务2没有提交??
[/Quote]

应该不会,底层都写好了的
ppasky 2012-09-27
  • 打赏
  • 举报
回复
看了下事务传播属性是PROPAGATION_REQUIRED,隔离级别没有定义,应该是oracle默认的READ COMMITTED
user147258 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
引用 10 楼 的回复:

你的事务是加在service上的吗?
事务1和事务2是不是分别对应两个service方法?


是的
[/Quote]
两个事务不在同一个service也没多大关系吧,这两个事务执行是有先后顺序的,又是单线程,会不会事务2没有提交??
ppasky 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

你的事务是加在service上的吗?
事务1和事务2是不是分别对应两个service方法?
[/Quote]

是的
liangtu 2012-09-27
  • 打赏
  • 举报
回复
你的事务是加在service上的吗?
事务1和事务2是不是分别对应两个service方法?
user147258 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
引用 2 楼 的回复:

还有,你可以单步调试下,也就是在事务2执行完了,马上进入事务1时,查看一下数据库,看数据是否已被删除


我就是单步调试了一下才发现这个问题的,加了断点,一步一步调试就正常,每次都能删除当前id的数据,也能正常读取下一条,而去掉断点运行的时候前几次读到的都是第一条数据。。。
[/Quote]
那就有点怪了,如果是单线程不会这样吧,要不你在线程2后面sleep几秒,试试行不行
ppasky 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

是交给spring管理的吗?spring能很好的管理事物,不会出现你说的那种情况
[/Quote]

是的啊, 我就郁闷了...用的是spring2.5
  • 打赏
  • 举报
回复
是交给spring管理的吗?spring能很好的管理事物,不会出现你说的那种情况
ppasky 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

还有,你可以单步调试下,也就是在事务2执行完了,马上进入事务1时,查看一下数据库,看数据是否已被删除
[/Quote]

我就是单步调试了一下才发现这个问题的,加了断点,一步一步调试就正常,每次都能删除当前id的数据,也能正常读取下一条,而去掉断点运行的时候前几次读到的都是第一条数据。。。
ppasky 2012-09-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

理论上应该不会呀、你的两个事务是在同一个线程吗?
[/Quote]

是在同一个线程
晓风吹雾 2012-09-27
  • 打赏
  • 举报
回复
假设2个线程 并行

thread1 -> start transation1 -> begin -> delete data (id = 1110)

当thread1没有commit的时候, thread2 就开始读取了,所有有问题了。
thread2 -> start transation2 -> begin -> select data (id = 1110)


如果你保证transation1和2 完全按照串行顺序执行,肯定不会有问题了。 如下所示。
start transation1 -> begin -> select or delete -> commit transation1-> start transation2 -> begin -> select or delete -> commit transation2
a8509190 2012-09-27
  • 打赏
  • 举报
回复
事务最麻烦的东西,建议你看看SPRING的事务机制,事务隔离级别,去看看~是不是这个没设置
user147258 2012-09-27
  • 打赏
  • 举报
回复
还有,你可以单步调试下,也就是在事务2执行完了,马上进入事务1时,查看一下数据库,看数据是否已被删除
user147258 2012-09-27
  • 打赏
  • 举报
回复
理论上应该不会呀、你的两个事务是在同一个线程吗?

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧