理解事务机制

1. 事务和线程
不论是JDBC还是Spring,在做事务处理的时候,都是和线程绑定的,可以猜想得到,事务的状态及其相关的变量都是存储在Thread对象的ThreadLocal中的。可以写一段代码来验证。


2. 分布式事务
那么如果要让事务来跨线程,需要怎么做呢?其实问题很简单,无论是跨线程还是跨进程,都需要一个共享区来存储事务相关的状态和变量,而且这个共享区是线程/进程之间共享的。那么,我们常说的分布式事务,它常采用的两段式提交,其核心思想就是在资源(数据库、文件等)管理器之上,抽象出一层事务管理器。资源提交是提交到事务管理器,我们称之为预交。事务管理器可以管理多个逻辑或者物理上分离的资源,所有资源提交的信息都由事务管理器来管理,通过资源管理器反馈的信息,事务管理器来决定是提交还是回滚。

3. 事务回滚
我们再发散一下,怎么实现事务回滚呢?假设你使用的是一个不支持事务的数据库,恰好有一个业务场景又需要事务,那么你需要怎么实现事务呢?事务提交可能比较好处理,比较简单的做法是,利用ThreadLocal来存储需要提交的SQL,当commit方法执行的时候,在按照顺序提交本线程的所有SQL给数据库来执行,存储结构使用队列(先进先出);那么,为了便于回滚操作,每当新增一条正想SQL,同时需要新增一个逆向操作,并且在ThreadLocal中维护,存储结构使用栈(后进先出),这样当rollback方法执行的时候,逆序回退即可。

4. 回滚逻辑
数据回滚一般是依靠数据库的Undo日志来保证的。写了一个简单的事务管理器和客户端测试类,可以帮助理解事务的提交、回滚机制。

package transaction;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程级事务
 * @date   2014-7-4
 */
public class TransactionManager {    
    // 单例对象
    private static final TransactionManager transactionManager = new TransactionManager();
    private TransactionManager(){}
    
    // 存储事务相关的变量
    public static final ThreadLocal context = new ThreadLocal(){
        private Map innerContext;
        
        @Override
        protected Map initialValue() { 
            innerContext = new HashMap();
            return innerContext;
        }

        @Override
        public void remove() {
            innerContext.clear();
        }
    };
    
    // 用于存储提交操作序列
    public static final ThreadLocal
      
      
       
        commitContext = new ThreadLocal
       
       
        
        (){
        private Queue
        
        
          queue; @Override protected Queue 
         
           initialValue() { queue = new LinkedBlockingQueue 
          
            (); return queue; } @Override public void remove() { queue.clear(); } }; // 用于存储回滚操作序列 public static final ThreadLocal 
           
             rollbackContext = new ThreadLocal 
            
              (){ private Stack 
             
               stack; @Override protected Stack 
              
                initialValue() { stack = new Stack 
               
                 (); return stack; } @Override public void remove() { stack.clear(); } }; public static TransactionManager getInstance(){ return transactionManager; } // 开始事务 public boolean start(){ context.get().put("state", "started"); return false; } // 提交事务 public boolean commit(){ Queue 
                
                  queue = commitContext.get(); for (String operation : queue){ System.out.println("线程"+Thread.currentThread().getName()+"提交操作:"+operation); } context.get().put("state", "commited"); return true; } // 回滚事务 public boolean rollback(){ Stack 
                 
                   stack = rollbackContext.get(); while(!stack.isEmpty()){ System.out.println("线程"+Thread.currentThread().getName()+"回滚操作:"+stack.pop()); } context.get().put("state", "rollbacked"); return true; } } 
                  
                 
                
               
              
             
            
           
          
        
       
       
      
      


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值