问题描述
我试图了解Spring事务的隔离级别.这是我正在使用的示例:
I am trying to understand isolation levels of Spring transactions. Here is the example I am using:
@Component
public class BookShop {
private Object lockObj = new Object();
@Autowired
private BookDao bookDao;
@Transactional
public void increaseStock(int isbn, int increment){
String threadName = Thread.currentThread().getName();
synchronized (lockObj) {
Book book = bookDao.findByIsbn(isbn);
System.out.println(threadName+" about to increment the stock");
bookDao.updateStock(book, 5);
}
System.out.println(threadName+" has increased the stock ");
sleep(threadName);
System.out.println(threadName+" rolled back stock");
throw new RuntimeException("Stock increased by mistake");
}
@Transactional
public int checkStock(int isbn){
int stock = 0;
String threadName = Thread.currentThread().getName();
synchronized (lockObj) {
System.out.println(threadName+" checking for the stock");
stock = bookDao.getStock(isbn);
}
System.out.println(threadName+": Stock is: "+stock);
sleep(threadName);
return stock;
}
private void sleep(String threadName){
System.out.println(threadName+" sleeping");
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
}
System.out.println(threadName+" wakeup!");
}
}
这就是我调用上述方法的方式:
And this is the way I am invoking the above:
public void testIsolationLevels(final BookShop bookShop, final int isbn){
Thread t1 = new Thread(){
public void run() {
bookShop.increaseStock(isbn, 5);
};
};
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
Thread t2 = new Thread(){
public void run() {
bookShop.checkStock(isbn);
};
};
t2.setPriority(Thread.MIN_PRIORITY);
t2.start();
}
这是交易配置:
<tx:advice id="bookTxn" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="updateStock" isolation="READ_UNCOMMITTED"/>
<tx:method name="getStock" isolation="READ_UNCOMMITTED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.pramati.springIdol.dao.BookDao+.*(..))" id="bookPC"/>
<aop:advisor advice-ref="bookTxn" pointcut-ref="bookPC"/>
</aop:config>
但是当我运行示例时,这是我得到的结果:
But when I run the example, here is the o/p I am getting:
Thread-2 about to increment the stock// Initially it is 99
Thread-2 has increased the stock // Now it is 104(99+5)
Thread-2 sleeping
Thread-3 checking for the stock
Thread-3: Stock is: 99//Why is it not 104 even if isolation level is read_uncommitted??
Thread-3 sleeping
Thread-2 wakeup!
Thread-2 rolled back stock
Thread-3 wakeup!
Exception in thread "Thread-2" java.lang.RuntimeException: Stock increased by mistake
我认为Thread-3将能够读取更新后的值.但事实并非如此.有人可以让我知道我要去哪里了吗?
I thought Thread-3 will be able to read the updated value. But it is not. Can someone please let me know where I am going wrong?
预先感谢!
推荐答案
这里的问题是我正在从另一个事务方法(BookShop的方法)中调用DAO的事务方法.
The problem here is I am calling DAO's transactional methods from another transactional method(BookShop's methods).
由于我尚未为BookShop的方法指定隔离级别,因此默认隔离级别为Isolation.READ_COMMITTED.
As I have not specified the isolation level for BookShop's method, the default isolation level is Isolation.READ_COMMITTED.
还要注意,我没有为Dao的方法指定传播行为,默认行为是Propagation.REQUIRED.因此,dao方法使用与BookShop相同的事务.因此,将Isolation.READ_COMMITTED的隔离应用于事务.
Also note that I have not specified propagation behavior for Dao's method and the default behavior is Propagation.REQUIRED. Hence dao methods uses the same transaction as of BookShop's. So the isolation of Isolation.READ_COMMITTED gets applied for the transaction.
解决方法是:将BookShop方法的隔离级别指定为READ_UNCOMMITTED
Solution is: Specify the isolation level for BookShop methods as READ_UNCOMMITTED
这篇关于隔离级别READ_UNCOMMITTED不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!