Transaction 事务(锁数据行-1)

参考帖子:http://blog.csdn.net/winy_lm/article/details/50403264

 

举个例子: 假设商品表单products 内有一个存放商品数量的quantity ,在订单成立之前必须先确定quantity 商品数量是否足够(quantity>0) ,

然后才把数量更新为1。

不安全的做法:

SELECT quantity FROM products WHERE id=3;

UPDATE products SET quantity = 1 WHERE id=3;

为什么不安全呢?

少量的状况下或许不会有问题,但是大量的数据存取「铁定」会出问题。

如果我们需要在quantity>0 的情况下才能扣库存,假设程序在第一行SELECT 读到的quantity 是2 ,看起来数字没有错,但是当MySQL 正准备要UPDATE 的时候,可能已经有人把库存扣成0 了,但是程序却浑然不知,将错就错的UPDATE 下去了。

因此必须透过的事务机制来确保读取及提交的数据都是正确的。

实际测试:




loading很久后如下


 

 

 

 

 

项目中测试:

Xml:





 
 
 

Service:



 

在项目中无需另外写SET AUTOCOMMIT=0; BEGIN WORK; 只需在查询语句后面加上for update

因为@Transactional已经帮我们完成了这些操作

Controller:



 

测试方法

         同一个项目在两个Tomcat中启动,因为需要在其中一个方法内打断点,所以需要在两个eclipse中操作或者打成war包放入Tomcat/webapps中启动,同时开启两个Tomcat需要更改其中一个的端口号避免端口号占用的问题。

         两个项目都开启好之后,下面正式开启测试。

库存不足时,两个项目的显示:



 




 
 

 

 

库存为1时,其中一个进入方法打断点之后,另一个进行同样的操作:



 

在8081的这个上打上断点,断点打在findById(for update)之后



 

然后进入8080,发现8081断点不放开,这边就一直在加载中。。



 

放开断点之后,8081库存-1 成功,8080也加载完成,显示库存不足,达到我们的要求 



 

 

写在后面:

测试去除@Transactional注解之后的效果,在同样的操作下最后都显示“库存  -1 : success”,
这是因为没有Transactional注解下,没有SET AUTOCOMMIT=0; BEGIN WORK;的效果,
导致select..for update没有生效。

猜你喜欢

转载自whenjun.iteye.com/blog/2381706