8月 042015
 

分布式事务

Innodb存储引擎支持XA事务,通过XA事务可以支持分布式事务的实现。分布式事务指的是允许多个独立的事务资源(transac         tional resources)参与一个全局的事务中。事务资源通常是关系型数据库系统,也可以是其它类型的资源。

 

全局事务要求在其中所有参与的事务要么全部提交,要么全部回滚,这对于事务原有的ACID要求又有了提高。另外,在使用分布式事务时候,InnoDB存储引擎的事务隔离级别必须设置成serialiable。

 

XA事务允许不同数据库之间的分布式事务,如:一台服务器是mysql数据库,一台是oracle的,又有可能还有一台是sqlserver的,只要参与全局事务中的每个节点都支持XA事务。分布式事务可能在银行系统的转帐中比较常见,如一个用户需要从上海转1000元到北京的一个用户账号上面:

# bank ofshanghai:

Updateuser_account set money=money – 10000 where user=’xiaozhang’;

# bank ofBeijing:

Updateuser_account set money= money + 10000 where user=’xiaoli’;

像这种情况一定需要分布式的事务,要不都提交,要么都回滚。在任何一个节点出问题都会造成严重的结果:1 xiaozhang的帐号被扣款,但是xiaoli没有收到钱;2 xiaozhang的帐号没有被扣款,但是xiaoli收到钱了。

 

分布式事务是由一个或者多个Resource Managerd,一个事务管理器Transaction Manager以及一个应用程序 Application Program组成。

资源管理器:提供访问事务资源的方法,通常一个数据库就是一个资源管理器。

事务管理器:协调参与全局事务中的各个事务。需要和参与全局事务中的资源管理器进行通信。

应用程序:定义事务的边界,指定全局事务中的操作。

在mysql中的分布式事务中,资源管理器就是mysql数据库,事务管理器为连接到mysql服务器的客户端。如下图所示:

 

分布式事务使用两段式提交(two-phase commit)的方式。在第一个阶段,所有参与全局事务的节点都开始准备,告诉事务管理器它们准备好提交了。第二个阶段,事务管理器告诉资源管理器执行rollback或者commit,如果任何一个节点显示不能commit,那么所有的节点就得全部rollback。

当前的java的jta java transaction API可以很好的支持mysql的分布式事务,可以仔细参考jta手册。下面的例子显示了如何使用jta支持调用mysql分布式事务。

参数innodb_support_xa可以查看是否启用了XA事务支持(默认为on开启状态):

  1. mysql> show variables like‘innodb_support%’;  
  2. +——————-+——-+  
  3. | Variable_name     | Value |  
  4. +——————-+——-+  
  5. | innodb_support_xa | ON    |  
  6. +——————-+——-+  
  7. 1 row in set (0.00 sec)  
  8.    
  9. mysql>  

[注意] 对于XA事务的支持,是在mysql体系结构的存储引擎层。因此即使不参与外部的XA事务,mysql事务内部不同存储引擎也会使用xa事务。假设我们用start  transaction开启了一个本地的事务,往NDB Cluster存储引擎的表t1插入一条记录,往innodb存储引擎的表t2插入一条记录,然后commit,在mysql内部也是通过xa事务来进行协调的,这样才可以保证2张表的原子性。

转自:http://blog.csdn.net/mchdba/article/details/13076803

spring分布式事务实现

 分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。如果使用WAS的JTA支持,把它的属性改为WebSphere对应的TransactionManager。 
    在tomcat下,是没有分布式事务的,不过可以借助于第三方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现,在spring中分布式事务是通过jta(jotm,atomikos)来进行实现。 
1、http://jotm.objectweb.org/ 
2、http://www.atomikos.com/Main/TransactionsEssentials 
一、使用JOTM例子 
(1)、Dao及实现 

Java代码  收藏代码

  1. public interface GenericDao {  
  2.   
  3.     public int save(String ds, String sql, Object[] obj) throws Exception;  
  4.       
  5.     public int findRowCount(String ds, String sql);  
  6.       
  7. }  

Java代码  收藏代码

  1. public class GenericDaoImpl implements GenericDao{  
  2.   
  3.     private  JdbcTemplate jdbcTemplateA;  
  4.     private  JdbcTemplate jdbcTemplateB;  
  5.   
  6.     public void setJdbcTemplateA(JdbcTemplate jdbcTemplate) {  
  7.         this.jdbcTemplateA = jdbcTemplate;  
  8.     }  
  9.   
  10.     public void setJdbcTemplateB(JdbcTemplate jdbcTemplate) {  
  11.         this.jdbcTemplateB = jdbcTemplate;  
  12.     }  
  13.       
  14.     public int save(String ds, String sql, Object[] obj) throws Exception{  
  15.         if(null == ds || “”.equals(ds)) return –1;  
  16.         try{  
  17.             if(ds.equals(“A”)){  
  18.                 return this.jdbcTemplateA.update(sql, obj);  
  19.             }else{  
  20.                 return this.jdbcTemplateB.update(sql, obj);  
  21.             }  
  22.         }catch(Exception e){  
  23.             e.printStackTrace();  
  24.             throw new Exception(“执行” + ds + “数据库时失败!”);  
  25.         }  
  26.     }  
  27.   
  28.     public int findRowCount(String ds, String sql) {  
  29.         if(null == ds || “”.equals(ds)) return –1;  
  30.           
  31.         if(ds.equals(“A”)){  
  32.             return this.jdbcTemplateA.queryForInt(sql);  
  33.         }else{  
  34.             return this.jdbcTemplateB.queryForInt(sql);  
  35.         }  
  36.     }  
  37.   
  38. }  

(2)、Service及实现 

Java代码  收藏代码

  1. public interface UserService {  
  2.       
  3.     public void saveUser() throws Exception;  
  4.       
  5. }  

Java代码  收藏代码

  1. public class UserServiceImpl implements UserService{  
  2.   
  3.     private GenericDao genericDao;  
  4.       
  5.     public void setGenericDao(GenericDao genericDao) {  
  6.         this.genericDao = genericDao;  
  7.     }  
  8.   
  9.     public void saveUser() throws Exception {  
  10.         String userName = “user_” + Math.round(Math.random()*10000);  
  11.         System.out.println(userName);  
  12.           
  13.         StringBuilder sql = new StringBuilder();  
  14.         sql.append(” insert into t_user(username, gender) values(?,?); “);  
  15.         Object[] objs = new Object[]{userName,“1”};  
  16.           
  17.         genericDao.save(“A”, sql.toString(), objs);  
  18.           
  19.         sql.delete(0, sql.length());  
  20.         sql.append(” insert into t_user(name, sex) values(?,?); “);  
  21.         objs = new Object[]{userName,“男的”};//值超出范围  
  22.         genericDao.save(“B”, sql.toString(), objs);  
  23.     }  
  24.   
  25. }  

(3)、applicationContext-jotm.xml 

Xml代码  收藏代码

  1. <?xml version=“1.0” encoding=“UTF-8”?>  
  2.   
  3. <beans xmlns=“http://www.springframework.org/schema/beans”   
  4.     xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”   
  5.     xmlns:context=“http://www.springframework.org/schema/context”   
  6.     xmlns:aop=“http://www.springframework.org/schema/aop”   
  7.     xmlns:tx=“http://www.springframework.org/schema/tx”   
  8.     xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  9.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd   
  10.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd   
  11.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”>  
  12.   
  13.     <description>springJTA</description>  
  14.   
  15.     <!–指定Spring配置中用到的属性文件–>   
  16.     <bean id=“propertyConfig”   
  17.             class=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>   
  18.         <property name=“locations”>   
  19.             <list>   
  20.                 <value>classpath:jdbc.properties</value>   
  21.             </list>   
  22.         </property>   
  23.     </bean>   
  24.       
  25.     <!– JOTM实例 –>  
  26.     <bean id=“jotm” class=“org.springframework.transaction.jta.JotmFactoryBean”>  
  27.           <property name=“defaultTimeout” value=“500000”/>  
  28.     </bean>  
  29.   
  30.     <!– JTA事务管理器 –>  
  31.     <bean id=“jtaTransactionManager” class=“org.springframework.transaction.jta.JtaTransactionManager”>     
  32.         <property name=“userTransaction” ref=“jotm” />     
  33.     </bean>  
  34.   
  35.     <!– 数据源A –>   
  36.     <bean id=“dataSourceA” class=“org.enhydra.jdbc.pool.StandardXAPoolDataSource” destroy-method=“shutdown”>   
  37.        <property name=“dataSource”>   
  38.            <bean class=“org.enhydra.jdbc.standard.StandardXADataSource” destroy-method=“shutdown”>   
  39.                <property name=“transactionManager” ref=“jotm”/>   
  40.                <property name=“driverName” value=“${jdbc.driver}”/>   
  41.                <property name=“url” value=“${jdbc.url}”/>   
  42.            </bean>   
  43.        </property>   
  44.        <property name=“user” value=“${jdbc.username}”/>   
  45.        <property name=“password” value=“${jdbc.password}”/>   
  46.     </bean>   
  47.   
  48.     <!– 数据源B –>   
  49.     <bean id=“dataSourceB” class=“org.enhydra.jdbc.pool.StandardXAPoolDataSource” destroy-method=“shutdown”>   
  50.        <property name=“dataSource”>   
  51.            <bean class=“org.enhydra.jdbc.standard.StandardXADataSource” destroy-method=“shutdown”>   
  52.                <property name=“transactionManager” ref=“jotm”/>   
  53.                <property name=“driverName” value=“${jdbc2.driver}”/>   
  54.                <property name=“url” value=“${jdbc2.url}”/>   
  55.            </bean>   
  56.        </property>   
  57.        <property name=“user” value=“${jdbc2.username}”/>   
  58.        <property name=“password” value=“${jdbc2.password}”/>   
  59.     </bean>   
  60.   
  61.     <bean id = “jdbcTemplateA”   
  62.          class = “org.springframework.jdbc.core.JdbcTemplate”>   
  63.          <property name = “dataSource” ref=“dataSourceA”/>   
  64.     </bean>  
  65.       
  66.     <bean id = “jdbcTemplateB”   
  67.          class = “org.springframework.jdbc.core.JdbcTemplate”>   
  68.          <property name = “dataSource” ref=“dataSourceB”/>   
  69.     </bean>      
  70.   
  71.     <!– 事务切面配置 –>   
  72.     <aop:config>   
  73.         <aop:pointcut id=“pointCut”  
  74.                 expression=“execution(* com.logcd.service..*.*(..))”/><!– 包及其子包下的所有方法 –>  
  75.         <aop:advisor pointcut-ref=“pointCut” advice-ref=“txAdvice”/>   
  76.           
  77.         <aop:advisor pointcut=“execution(* *..common.service..*.*(..))” advice-ref=“txAdvice”/>  
  78.     </aop:config>   
  79.   
  80.     <!– 通知配置 –>   
  81.     <tx:advice id=“txAdvice” transaction-manager=“jtaTransactionManager”>   
  82.        <tx:attributes>   
  83.           <tx:method name=“delete*” rollback-for=“Exception”/>   
  84.           <tx:method name=“save*” rollback-for=“Exception”/>   
  85.           <tx:method name=“update*” rollback-for=“Exception”/>   
  86.           <tx:method name=“find*” read-only=“true” rollback-for=“Exception”/>   
  87.        </tx:attributes>   
  88.     </tx:advice>   
  89.   
  90.     <bean id=“genericDao”   
  91.             class=“com.logcd.dao.impl.GenericDaoImpl” autowire=“byName”>  
  92.     </bean>  
  93.   
  94.     <bean id=“userService”   
  95.             class=“com.logcd.service.impl.UserServiceImpl” autowire=“byName”>  
  96.     </bean>  
  97.   
  98. </beans>  

(4)、测试 

Java代码  收藏代码

  1. public class TestUserService{  
  2.   
  3.     private static UserService userService;  
  4.       
  5.     @BeforeClass  
  6.     public static void init(){  
  7.         ApplicationContext app = new ClassPathXmlApplicationContext(“applicationContext-jotm.xml”);  
  8.         userService = (UserService)app.getBean(“userService”);  
  9.     }  
  10.       
  11.     @Test  
  12.     public void save(){  
  13.         System.out.println(“begin…”);  
  14.         try{  
  15.             userService.saveUser();  
  16.         }catch(Exception e){  
  17.             System.out.println(e.getMessage());  
  18.         }  
  19.         System.out.println(“finish…”);  
  20.     }  
  21.       
  22. }  

二、关于使用atomikos实现 
(1)、数据源配置 

Xml代码  收藏代码

  1. <bean id=“dataSourceA” class=“com.atomikos.jdbc.SimpleDataSourceBean” init-method=“init” destroy-method=“close”>  
  2.     <property name=“uniqueResourceName”>  
  3.         <value>${datasource.uniqueResourceName}</value>  
  4.     </property>  
  5.     <property name=“xaDataSourceClassName”>   
  6.         <value>${database.driver_class}</value>   
  7.     </property>   
  8.     <property name=“xaDataSourceProperties”>  
  9.         <value>URL=${database.url};user=${database.username};password=${database.password}</value>   
  10.     </property>   
  11.     <property name=“exclusiveConnectionMode”>   
  12.         <value>${connection.exclusive.mode}</value>   
  13.     </property>  
  14.     <property name=“connectionPoolSize”>   
  15.         <value>${connection.pool.size}</value>  
  16.     </property>  
  17.     <property name=“connectionTimeout”>  
  18.         <value>${connection.timeout}</value>  
  19.     </property>  
  20.     <property name=“validatingQuery”>   
  21.         <value>SELECT 1</value>   
  22.     </property>   
  23. </bean>  

(2)、事务配置 

Xml代码  收藏代码

  1. <bean id=“atomikosTransactionManager” class=“com.atomikos.icatch.jta.UserTransactionManager”   
  2.     init-method=“init” destroy-method=“close”>   
  3.     <property name=“forceShutdown” value=“true”/>   
  4. </bean>   
  5.   
  6. <bean id=“atomikosUserTransaction” class=“com.atomikos.icatch.jta.UserTransactionImp”>   
  7.     <property name=“transactionTimeout” value=“${transaction.timeout}”/>   
  8. </bean>  
  9.   
  10. <!– JTA事务管理器 –>   
  11. <bean id=“springTransactionManager” class=“org.springframework.transaction.jta.JtaTransactionManager”>   
  12.     <property name=“transactionManager” ref=“atomikosTransactionManager”/>   
  13.     <property name=“userTransaction” ref=“atomikosUserTransaction”/>   
  14. </bean>  
  15.   
  16. <!– 事务切面配置 –>   
  17. <aop:config>   
  18.     <aop:pointcut id=“serviceOperation”  expression=“execution(* *..service*..*(..))”/>   
  19.     <aop:advisor pointcut-ref=“serviceOperation” advice-ref=“txAdvice”/>   
  20. </aop:config>  
  21.   
  22. <!– 通知配置 –>  
  23. <tx:advice id=“txAdvice” transaction-manager=“springTransactionManager”>   
  24.     <tx:attributes>  
  25.         <tx:method name=“*” rollback-for=“Exception”/>   
  26.     </tx:attributes>   
  27. </tx:advice>   

转自:http://log-cd.iteye.com/blog/807607

Sorry, the comment form is closed at this time.