事务隔离级别READ_UNCOMMITTED测试

有个方法想使用read_uncommitted,但是一直不起作用,排查了半天终于发现了原因。

结论

情景一:
这种情况下是可以读取到未commit的数据的。

public class AService{
    @Transactional(isolation=Isolation.READ_UNCOMMITTED)
    public void fun(){
        //这里可以读到脏数据
    }
}

情景二:
AService的一个READ_COMMITTED方法调用BService的一个READ_UNCOMMITTED方法,这个时候是读取不到未commit的数据的。

public class AService{
    @Autowired
    private BService bService;
    @Transactional(isolation=Isolation.READ_COMMITTED)
    public void fun2(){
        bService.fun2();
    }
}
public class BService{
    @Transactional(isolation=Isolation.READ_UNCOMMITTED)
    public void fun2(){
        //这里不能读取到脏数据
    }
}

另外:我用的是jpa hibernate来保存的数据,在新增完的时候还需要flush一下,否则上面两种情景都读取不到未提交数据。

下面是我的测试demo:

  • 首先新增,并且延迟30s后退出方法提交事务。
  • 按照上面两个情景做了两个读取操作。
  • *

代码

TestController.java

package com.channelsoft.apiplus.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.channelsoft.apiplus.po.AppDataResponsePo;
import com.channelsoft.apiplus.service.TestService;

@RestController("testController")
@RequestMapping(value = {"/myTest"})
public class TestController {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private TestService testService;

    @ResponseBody
    @RequestMapping(value = "/readUnCommitted2")
    public JSONObject readUnCommitted2(HttpServletRequest request, HttpServletResponse response) {
        logger.info("readUnCommitted2方法...");
        AppDataResponsePo result = new AppDataResponsePo();
        try{
            new Thread(){
                @Override
                public void run() {
                    try {
                        testService.addReadUnCommitted();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    try {
                        int i = 0;
                        while(i++<10){
                            testService.loadOneReadUnCommitted();
                            testService.loadOneReadUnCommitted2();
                            Thread.sleep(5 * 1000);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();;

        }catch(Exception e){
            logger.error("errro:", e);
        }
        logger.info("readUnCommitted2方法 end.");
        return (JSONObject) JSON.toJSON(result);
    }
}

TestService.java

package com.channelsoft.apiplus.service;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.channelsoft.apiplus.entity.MyTest;
import com.channelsoft.apiplus.po.support.ApiConstants;
import com.channelsoft.apiplus.repository.mysql.TestDao;

@Service("testService")
@Component
@Transactional
public class TestService {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private TestDao testDao;
    @Autowired
    private Test2Service test2Service;


    @Transactional(isolation=Isolation.READ_UNCOMMITTED)
    public void loadOneReadUnCommitted() throws Exception{
        MyTest test = null;
        test = testDao.findOne(333l);
        System.out.println(new Date() + "====TestService===" + test );
    }
    @Transactional
    public void loadOneReadUnCommitted2() throws Exception{
        test2Service.loadOneReadUnCommitted();
    }

    public void addReadUnCommitted() throws Exception{
        MyTest test = new MyTest();
        test.setOperationid(333l);
        test.setContext("readUncommitted:" + new Date().toString());
        test = testDao.save(test);
        testDao.flush();//一定要flush,否则两个情景都读不到脏数据
        System.out.println("after save=" + new Date() + test + "sleep 30s");
        Thread.sleep(30 * 1000);
    }
}

Test2Service.java

package com.channelsoft.apiplus.service;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.channelsoft.apiplus.entity.MyTest;
import com.channelsoft.apiplus.po.support.ApiConstants;
import com.channelsoft.apiplus.repository.mysql.TestDao;

@Service("test2Service")
@Component
//@Transactional
public class Test2Service {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private TestDao testDao;

    @Transactional(isolation=Isolation.READ_UNCOMMITTED)
    public void loadOneReadUnCommitted() throws Exception{
        MyTest test = null;
        test = testDao.findOne(333l);
        System.out.println(new Date() + "====TestService2===" + test );
    }
}

MyTest.java

package com.channelsoft.apiplus.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "OPERATION_LOG")
public class MyTest implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1668209570962416481L;
    @Id
    @Column(name = "operation_id")
    private Long operationid;
    @Column(name = "context")
    private String context;
    @Column(name = "operation_type")
    private String operationtype;



    @Column(name = "operation_time")
    private String operationtime;
    @Column(name = "operation_user")
    private String operationuser;
    @Column(name = "enterprise_id")
    private String enterpriseid;





    public String getOperationtime() {
        return operationtime;
    }
    public void setOperationtime(String operationtime) {
        this.operationtime = operationtime;
    }
    public String getOperationuser() {
        return operationuser;
    }
    public void setOperationuser(String operationuser) {
        this.operationuser = operationuser;
    }
    public String getEnterpriseid() {
        return enterpriseid;
    }
    public void setEnterpriseid(String enterpriseid) {
        this.enterpriseid = enterpriseid;
    }
    public Long getOperationid() {
        return operationid;
    }
    public void setOperationid(Long operationid) {
        this.operationid = operationid;
    }
    public String getContext() {
        return context;
    }
    public void setContext(String context) {
        this.context = context;
    }
    public String getOperationtype() {
        return operationtype;
    }
    public void setOperationtype(String operationtype) {
        this.operationtype = operationtype;
    }
    @Override
    public String toString() {
        return "MyTest [operationid=" + operationid + ", context=" + context + "]";
    }



}

日志

2016-10-14 15:52:31,065 [qtp1062664881-29] INFO  c.c.a.controller.TestController - readUnCommitted2方法...
2016-10-14 15:52:31,067 [qtp1062664881-29] INFO  c.c.a.controller.TestController - readUnCommitted2方法 end.
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:31 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
2016-10-14 15:52:31,221 [qtp1062664881-29] DEBUG c.c.q.i.ApiCountInterceptor - Api[/apiplus/myTest/readUnCommitted2] is not in limit list,ignored.
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:31 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: update OPERATION_LOG set context=?, enterprise_id=?, operation_time=?, operation_type=?, operation_user=? where operation_id=?
after save=Fri Oct 14 15:52:31 CST 2016MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]sleep 30s
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:36 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:36 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:41 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:41 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:46 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:46 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:51 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:51 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:56 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:52:56 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:40:39 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:01 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:01 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:06 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:06 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:11 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:11 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:16 CST 2016====TestService===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]
Hibernate: select mytest0_.operation_id as operatio1_6_0_, mytest0_.context as context2_6_0_, mytest0_.enterprise_id as enterpri3_6_0_, mytest0_.operation_time as operatio4_6_0_, mytest0_.operation_type as operatio5_6_0_, mytest0_.operation_user as operatio6_6_0_ from OPERATION_LOG mytest0_ where mytest0_.operation_id=?
Fri Oct 14 15:53:16 CST 2016====TestService2===MyTest [operationid=333, context=readUncommitted:Fri Oct 14 15:52:31 CST 2016]

你可能感兴趣的:(spring)