精华内容
下载资源
问答
  • q 显式事务:每个事务均以BEGIN TRANSACTION语句显式开始,以COMMIT或ROLLBACK语句显式结束。 q 隐性事务:在上个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句显式完成。 说明:还有一种...
    为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据。这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): 

    分布式访问一个单独的数据资源,以及从一个单独的应用构件访问分布式资源。 
    在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元(unit)。在一个工作单元中, 操作的所有部分一起成功或失败并恢复。在下面的情况下这个问题更加复杂: 

    通过一组分布式的、访问多个资源的数据的构件实现一个工作单元,和/或部分操作是被顺序执行的或在要求协调和/或同步的并行线程中。 

    在所有情况下, 都要求应用维护一个工作单元的成功或失败。在失败的情况下,所有资源要把数据状态返回到以前的状态 
    (比如说,工作单元开始前的状态)。 
    事务的概念和和事务管理器(或者一个事务处理服务)在一个工作单元中的维护数据完整性,这就简化了这样的企业级别分布式应用的构造。 

    一个事务是有下列属性的一个工作单元: 


    原子性(ATOMICITY): 
    一个事务要被完全的无二义性的做完或撤消。在任何操作出现一个错误的情况下,构成事务的所有操作的效果必须被撤消,数据应被回滚到以前的状态。 

    一致性(CONSISTENCY): 
    一个事务应该保护所有定义在数据上的不变的属性(例如完整性约束)。在完成了一个成功的事务时,数据应处于一致的状态。换句话说,一个事务应该把系统从一个一致-状态转换到另一个一致状态。举个例子,在关系数据库的情况下, 
    一个一致的事务将保护定义在数据上的所有完整性约束。 

    隔离性(ISOLATION): 
    在同一个环境中可能有多个事务并发执行,而每个事务都应表现为独立执行。串行的执行一系列事务的效果应该同于并发的执行它们。这要求两件事: 

    在一个事务执行过程中,数据的中间的(可能不一致)状态不应该被暴露给所有的其他事务。 
    两个并发的事务应该不能操作同一项数据。数据库管理系统通常使用锁来实现这个特征。 

    持久性(DURABILITY): 
    一个被完成的事务的效果应该是持久的。

     

    ****************************************************************************************************************************************************************************************************************************

     ****************************************************************************************************************************************************************************************************************************

    【考点】
    数据库事务基础知识。
    【出现频率】
    ★★★☆☆
    【解答】
    事务提供了一种机制,可用来将一系列数据库更改归入一个逻辑操作。更改数据库后,所做的更改可以作为一个单元进行提交或取消。事务可确保遵循原子性、一致性、隔离性和持续性(ACID)这几种属性,以使数据能够正确地提交到数据库中。
    使用事务机制的好处非常明显,例如银行转账之类的交易操作中,事务有着重要的作用。事务的成功取决于事务单元帐户相互依赖的操作行为是否能全部执行成功,只要有一个操作行为失败,整个事务将失败。例如:客户A和客户B的银行账户金额都是10000元人民币,客户A需要把自己帐户中的5000元人民币转到客户B的账户上。这个过程看似简单,实际上涉及了一系列的数据库操作,可以简单地视为两步基本操作,即从客户A帐户的金额中扣除5000元人民币,以及将客户B帐户中金额添加5000元人民币。假设第1步数据库操作成功,而第二步失败的话,将导致整个操作失败,并且客户A帐户金额将被扣除5000元人民币。事务机制可以避免此类情况,以保证整个操作的完成,如果某步操作出错,之前所作的数据库操作将全部失效。
    【分析】
    事务是单个的工作单元。如果某个事务成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分。如果事务遇到错误且必须取消或回滚,则所有数据更改均被清除。一个逻辑工作单元必须有ACID属性,只有这样才能成为一个事务。ACID属性有以下4个属性。
    1.原子性
    事务必须是原子工作单元。对于其数据修改,要么全都执行,要么全都不执行。
    2.一致性
    事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构都必须是正确的。
    3.隔离性
    由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务识别数据时数据所处的状态,或者是另一个并发事务修改它之前的状态,或者是第二个事务修改它之后的状态,事务不会识别中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
    4.持久性
    事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
    事务有以下3种运行模式。
    q      自动提交事务:每条单独的语句都是一个事务。
    q      显式事务:每个事务均以BEGIN TRANSACTION语句显式开始,以COMMIT或ROLLBACK语句显式结束。
    q      隐性事务:在上个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句显式完成。
    说明:还有一种批处理级事务模式,该模式仅应用于多活动结果集(MARS),在MARS会话中启动的Transact-SQL显式或隐式事务变为批处理级事务。当批处理完成时没有提交或回滚的批处理级事务自动由SQL Server进行回滚。
    展开全文
  • 本文就针对项目拆分后数据库的分布式事务问题,基于tcc-transaction分布式TCC型事务进行框架的搭建,同时引入相关的实战案例,来解决让人头疼的分布式事务问题。 二、tcc-transaction框架介绍 介绍:tcc-...

    一、背景

    有一定分布式开发经验的朋友都知道,产品/项目/系统最初为了能够快速迭代上线,往往不太注重产品/项目/系统的高可靠性、高性能与高扩展性,采用单体应用和单实例数据库的架构方式快速迭代开发;当产品/项目/系统做到一定规模的时候,原有的系统架构则不足以支撑义务发展需要,往往相同的业务则需要重复写很多次,导致代码大量冗余,难以维护和扩展,这时不得不对原有产品/项目/系统进行拆分,引入分布式的系统架构;而对原有产品/项目/系统进行拆分的过程中,对于业务和数据的拆分和迁移则成为了最为棘手的问题,尤其是在原有业务不能下线,拆分后的业务同时上线的场景下这种问题更加突出;项目拆分后,业务被拆分为多个独立的子业务分散到多个子系统中,而原有的单一数据库则被拆分到多个数据库中,拆分后的数据库则同样又面临着让人头疼的分布式事务的问题。

    本文就针对项目拆分后数据库的分布式事务问题,基于tcc-transaction分布式TCC型事务进行框架的搭建,同时引入相关的实战案例,来解决让人头疼的分布式事务问题。

    二、tcc-transaction框架介绍


    介绍:tcc-transaction是开源的TCC补偿性分布式事务框架,Git地址:https://github.com/changmingxie/tcc-transaction
    TCC为Try、Confirm、Cancel的缩写:try阶段预留资源尝试提交,confirm阶段确定提交,cancel取消提交释放资源。
    1.2.x项目指南地址:https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x
    本文的例子为引入一个本人实际工作中的一个开发场景:创建资产,将资产信息同时同步到Mongo与ES的流程(ES代码不列出了,与mongo类似),整个流程保证数据一致

    三、项目流程


    1.下载1.2.x版本源码,并可能需要修改部分代码


    因为是第三方包,所以需要自己打包到本地仓库。但包中spring版本为3.2.12.RELEASE,如果本地项目为4.x,比如本人的项目spring版本为4.3.4.RELEASE,如果不修改tcc中的spring版本,将报错无法启动,所以需要对原有框架源码进行相应的修改。
    源码修改比较简单,如下


    1.1 修改tcc-transaction总pom.xml文件 

    <!-- 第一处:修改版本为4.3.4  -->
    <springframework.version>4.3.4.RELEASE</springframework.version>
     
    <!-- 第二处:修改版本为2.2.1  -->
    <dependency>
          <groupId>org.quartz-scheduler</groupId>
          <artifactId>quartz</artifactId>
          <version>2.2.1</version>
          <exclusions>
              <exclusion>
                  <groupId>c3p0</groupId>
                  <artifactId>c3p0</artifactId>
              </exclusion>
          </exclusions>
    </dependency>
     
    <!-- 第三处:修改版本为2.5.3  -->
    <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>dubbo</artifactId>
           <version>2.5.3</version>
    </dependency>
    

    1.2 修改 tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/RecoverScheduledJob.java

    该文件中 CronTriggerBean类在4.x中已经不存在,也是修改源码主要修改的地方。
    修改其中的init方法,修改后如下:

    public void init() {
        try {
            MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
            jobDetail.setTargetObject(transactionRecovery);
            jobDetail.setTargetMethod("startRecover");
            jobDetail.setName("transactionRecoveryJob");
            jobDetail.setConcurrent(false);
            jobDetail.afterPropertiesSet();
     
            CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
            cronTrigger.setBeanName("transactionRecoveryCronTrigger");
            cronTrigger.setJobDetail(jobDetail.getObject());
     
            cronTrigger.setCronExpression(transactionConfigurator.getRecoverConfig().getCronExpression());
            cronTrigger.afterPropertiesSet();
     
            scheduler.scheduleJob(jobDetail.getObject(), cronTrigger.getObject());
     
            scheduler.start();
     
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }
    

    各位也可参考如下的修改:https://github.com/changmingxie/tcc-transaction/pull/84/files 

    1.3 打包并发布

    这里我们通过Maven进行打包发布,命令为:

    mvn -Dmaven.test.skip=true install

    2.项目依赖

    参考1.2.x使用指南,引入两个依赖(本人项目dubbo/dubbox框架,我使用并打包时版本为1.2.3.1)。调用方和提供方都需要引入依赖

    <dependency>
    	<groupId>org.mengyun</groupId>
    	<artifactId>tcc-transaction-spring</artifactId>
    	<version>1.2.4.23</version>
    </dependency>
    
    <!-- dubbo版本才需要,其他版本不需要 -->
    <dependency>
    	<groupId>org.mengyun</groupId>
    	<artifactId>tcc-transaction-dubbo</artifactId>
    	<version>1.2.4.23</version>
    </dependency>

    3.加载tcc-transaction.xml配置

    原文中是配置在web.xml中,我个人试了一下放在dubbo web项目的web.xml中,但配置并没有被加载。该文件的意义只是希望项目启动时被加载,于是直接在dubbo中的一个spring的配置文件中引入,如下:

    <import resource="classpath:tcc-transaction.xml" />
    <import resource="classpath:tcc-transaction-dubbo.xml" />

    4.设置TransactionRepository

    需要为tcc配置数据源,可以是MySQL或其他nosql,本文使用mysql,其他可参见原指南文档。
    mysql配置如下:

    <!--tcc-->
    <bean id="tccDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.tcc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="initialSize" value="${dbcp.initialSize}" />
        <property name="maxActive" value="${dbcp.maxActive}" />
        <property name="maxIdle" value="${dbcp.maxIdle}" />
        <property name="maxWait" value="${dbcp.maxWait}" />
        <property name="poolPreparedStatements" value="${dbcp.poolPreparedStatements}" />
        <property name="defaultAutoCommit" value="${dbcp.defaultAutoCommit}" />
        <property name="timeBetweenEvictionRunsMillis" value="${dbcp.timeBetweenEvictionRunsMillis}" />
        <property name="minEvictableIdleTimeMillis" value="${dbcp.minEvictableIdleTimeMillis}" />
    </bean>
     
    <bean id="transactionRepository"
          class="org.mengyun.tcctransaction.spring.repository.SpringJdbcTransactionRepository">
        <property name="dataSource" ref="tccDataSource"/>
        <property name="domain" value="SAAS"/>
        <property name="tbSuffix" value="_ASSET"/>
    </bean>
     
    <bean class="org.mengyun.tcctransaction.spring.recover.DefaultRecoverConfig">
        <property name="maxRetryCount" value="30"/>
        <property name="recoverDuration" value="120"/>
        <property name="cronExpression" value="0 */1 * * * ?"/>
        <property name="delayCancelExceptions">
            <util:set>
                <value>com.alibaba.dubbo.remoting.TimeoutException</value>
            </util:set>
        </property>
    </bean>
    

    需要注意的点:
    1.数据源必须配置新的,不能使用之前项目存在的dataSource的bean,也不能在同一库中,不然会导致tcc表数据与本地事务一起回滚,从而无法保存异常事务日志;
    2.注意domain、tbSuffix的配置,这两项文档中并没有配置,但源码demo中配置了,用于数据库的表名称等,推荐配置;
    3.最后的DefaultRecoverConfig项是可选的,用于恢复与重试,具体作用参考使用指南;
    4.defaultAutoCommit必须为true(默认为true) 


    5.mysql建表脚本

    根据以上的tbSufifix配置,脚本如下:

    CREATE TABLE `tcc_transaction_asset` (
      `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
      `DOMAIN` varchar(100) DEFAULT NULL,
      `GLOBAL_TX_ID` varbinary(32) NOT NULL,
      `BRANCH_QUALIFIER` varbinary(32) NOT NULL,
      `CONTENT` varbinary(8000) DEFAULT NULL,
      `STATUS` int(11) DEFAULT NULL,
      `TRANSACTION_TYPE` int(11) DEFAULT NULL,
      `RETRIED_COUNT` int(11) DEFAULT NULL,
      `CREATE_TIME` datetime DEFAULT NULL,
      `LAST_UPDATE_TIME` datetime DEFAULT NULL,
      `VERSION` int(11) DEFAULT NULL,
      PRIMARY KEY (`TRANSACTION_ID`),
      UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    

    注意:上面的是官方的sql,但是在本人实践中发现,sql经常会报缺少一个 IS_DELETE 字段,需要在上表中加上该字段

    6.发布服务(重点)

    6.1 dubbo接口

    public interface RedPacketService {
    
    	/**
    	 * 新增红包接口
    	 */
    	@Compensable
    	Integer insertRedPacket(Order order);
    
    }

    要注意的点:
    1.对外提供服务的接口必须有@Compensable注解;
    2.对应的confirm与cancel方法必须声明为接口,不能声明为private,即使是public也不行,必须有接口(本文没有实现接口,而是在实现类中直接写的confirm和cancel接口

    6.2 dubbo接口实现类

    @Service("redPacketServiceImpl")
    public class RedPacketServiceImpl implements RedPacketService {
    
    	@Autowired
    	private RedPacketDao redPacketDao;
    
    	@Override
    	@Compensable(confirmMethod = "confirmInsertRedPacket", cancelMethod = "cancelInsertRedPacket", transactionContextEditor = DubboTransactionContextEditor.class)
    	public Integer insertRedPacket(Order order) {
    		RedPacket redPacket = new RedPacket();
    		redPacket.setOrderId(1);
    		redPacket.setNum(1);
    		redPacket.setId(1);
    		redPacket.setStatus(-1);
    
    		System.out.println("redPacketInsert");
    
    		redPacketDao.insert(redPacket);
    
    		return redPacket.getOrderId();
    	}
    
    	@Transactional
    	public void confirmInsertRedPacket(Order order) {
    		System.out.println("confirmRedPacketInsert");
    
    		RedPacket redPacket = new RedPacket();
    		redPacket.setOrderId(1);
    		redPacket.setNum(1);
    		redPacket.setId(1);
    		redPacket.setStatus(0);
    
    		redPacketDao.update(redPacket);
    
    	}
    
    	@Transactional
    	public void cancelInsertRedPacket(Order order) {
    		System.out.println("cancelRedPacketInsert");
    
    		RedPacket redPacket = new RedPacket();
    		redPacket.setOrderId(1);
    		redPacket.setNum(1);
    		redPacket.setId(1);
    		redPacket.setStatus(1);
    
    		redPacketDao.delete(redPacket);
    	}
    
    }

    注意点:
    1.对外提供服务的接口必须有@Compensable注解,同时必须有confirmMethod、cancelMethod参数的配置,同时dubbo接口额外增加 "transactionContextEditor = DubboTransactionContextEditor.class"这个配置;
    2.提供服务接口与对应另外的两个CC方法参数必须完全一致;
    3.该tcc框架可嵌套调用,如上在testSaveAssetCard方法,即try阶段中调用了另一个tcc方法"assetCardService.processMongo()",理论上嵌套只应该在try阶段进行;
    4.confirm、cancel需要实现幂等性,可能会被重试;5.由于网络等因素,可能导致cancel方法先执行,cancel方法一定要做好相应的判断与处理
    5.confirmMethod、cancelMethod方法上的 @Transactional 不可省略(官方文档上面有说明,这里未测试省略情况下面是否可以)

    6.3 上一个service调用方

    @Service
    @Component
    public class OrderServiceImpl implements OrderService {
    
    	@Autowired
    	private OrderDao orderDao;
    
    	@Autowired
    	private RedPacketService redPacketService;
    
    	@Override
    	@Compensable(confirmMethod = "confirmInsert", cancelMethod = "cancelInsert", asyncConfirm = true)
    	@Transactional
    	public Integer insert(Order order) {
    		Order orde = new Order();
    		orde.setName("电脑");
    		orde.setOrderId(1);
    		orde.setStatus(-1);
    
    		orderDao.insert(orde);
    
    		redPacketService.insertRedPacket(orde);
    
    		//int i = 1 / 0;
    
    		return order.getOrderId();
    	}
    
    	public void confirmInsert(Order order) {
    		System.out.println("confirmOrderInsert");
    
    		Order orde = new Order();
    		orde.setName("电脑");
    		orde.setOrderId(1);
    		orde.setStatus(0);
    
    		orderDao.update(orde);
    
    	}
    
    	public void cancelInsert(Order order) {
    		System.out.println("cancelOrderInsert");
    
    		Order orde = new Order();
    		orde.setName("电脑");
    		orde.setOrderId(1);
    		orde.setStatus(1);
    
    		orderDao.delete(orde);
    
    	}
    
    }

    6.4 controller调用方

    	@RequestMapping(value = "/createOrder", produces = { "application/json;charset=UTF-8" })
    	@ResponseBody
    	//@Transactional
    	public String createOrder() {
    		Order order = new Order();
    		Integer id = orderService.insert(order);
    
    		return "订单创建成功,订单ID: " + id;
    	}

    注意点:
    1.因为需要回滚更新等操作,所以此业务中id不能用自增,而是需要项目生成;
    2.特别注意,调用方必须在事务中,也就是说必须有事务注解,或者能被事务配置切到,没有事务tcc框架调用时会抛异常。
    至此,配置已经全部完成

    7、测试

    在orderService的createOrder中的 1/0 注释放开后,可以看见 订单表和红包表都是没有数据的,同时tcc_transaction_assert中有数据。

    在 1/0 注释放开后,订单表和红包表 的status字段值都为0,是confirm执行后的状态,所以是成功的。

    8、完整代码

     完整代码实现:https://blog.csdn.net/u013278314/article/details/85112891

    9.事务查看

    源码中提供tcc-transaction-server web项目,该项目提供界面查看事务日志,打包后部署即可,我们这里就不在作详细的描述。

    展开全文
  • 数据库事务Transaction)那点事

    千次阅读 多人点赞 2018-12-19 16:54:27
    Transaction 也就是所谓的事务了,通俗理解就是一件事情。从小,父母就教育我们,做事情要有始有终,不能半途而废。 事务也是这样,不能做一般就不做了,要么做完,要么就不做。也就是说,事务必须是一个不可分割的...

    Transaction 也就是所谓的事务了,通俗理解就是一件事情。从小,父母就教育我们,做事情要有始有终,不能半途而废。 事务也是这样,不能做一般就不做了,要么做完,要么就不做。也就是说,事务必须是一个不可分割的整体,就像我们在化学课里学到的原子,原子是构成物质的最小单位。于是,人们就归纳出事务的第一个特性:原子性(Atomicity)。我靠,一点都不神秘嘛。

    特别是在数据库领域,事务是一个非常重要的概念,除了原子性以外,它还有一个极其重要的特性,那就是:一致性(Consistency)。也就是说,执行完数据库操作后,数据不会被破坏。打个比方,如果从 A 账户转账到 B 账户,不可能因为 A 账户扣了钱,而 B 账户没有加钱吧。如果出现了这类事情,您一定会非常气愤,什么 diao 银行啊!

    当我们编写了一条 update 语句,提交到数据库的一刹那间,有可能别人也提交了一条 delete 语句到数据库中。也许我们都是对同一条记录进行操作,可以想象,如果不稍加控制,就会出大麻烦来。我们必须保证数据库操作之间是“隔离”的(线程之间有时也要做到隔离),彼此之间没有任何干扰。这就是:隔离性(Isolation)。要想真正的做到操作之间完全没有任何干扰是很难的,于是乎,每天上班打酱油的数据库专家们,开始动脑筋了,“我们要制定一个规范,让各个数据库厂商都支持我们的规范!”,这个规范就是:事务隔离级别(Transaction Isolation Level)。能定义出这样牛逼的规范真的挺不容易的,其实说白了就四个级别:

    1. READ_UNCOMMITTED

    2. READ_COMMITTED

    3. REPEATABLE_READ

    4. SERIALIZABLE

    千万不要去翻译,那只是一个代号而已。从上往下,级别越来越高,并发性越来越差,安全性越来越高,反之则反。

    当我们执行一条 insert 语句后,数据库必须要保证有一条数据永久地存放在磁盘中,这个也算事务的一条特性, 它就是:持久性(Durability)。

    归纳一下,以上一共提到了事务的 4 条特性,把它们的英文单词首字母合起来就是:ACID,这个就是传说中的“事务 ACID 特性”

    真的是非常牛逼的特性啊!这 4 条特性,是事务管理的基石,一定要透彻理解。此外还要明确,这四个家伙当中,谁才是老大?

    其实想想也就清楚了:原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性。数据不一致了,就相当于“江湖乱套了,流氓戴胸罩”。所以说,这三个小弟都是跟着“一致性”这个老大混,为他全心全意服务。

    这四个家伙当中,其实最难理解的反倒不是一致性,而是隔离性。因为它是保证一致性的重要手段,是工具,使用它不能有半点差池,否则后果自负!怪不得数据库行业专家们都要来研究所谓的事务隔离级别了。其实,定义这四个级别就是为了解决数据在高并发下所产生的问题,那又有哪些问题呢?

    1. Dirty Read(脏读)

    2. Unrepeatable Read(不可重复读)

    3. Phantom Read(幻读)

    首先看看“脏读”,看到“脏”这个字,我就想到了恶心、肮脏。数据怎么可能脏呢?其实也就是我们经常说的“垃圾数据”了。比如说,有两个事务,它们在并发执行(也就是竞争)。看看以下这个表格,您一定会明白我在说什么:

     

    时间事务 A(存款)事务 B(取款)
    T1开始事务 
    T2 开始事务
    T3 查询余额(1000 元)
    T4 取出 1000 元(余额 0 元)
    T5查询余额(0 元) 
    T6 撤销事务(余额恢复为 1000 元)
    T7存入 500 元(余额 500 元) 
    T8提交事务 


    余额应该为 1500 元才对!请看 T5 时间点,事务 A 此时查询余额为 0 元,这个数据就是脏数据,它是事务 B 造成的,明显事务没有进行隔离,渗过来了,乱套了。

    所以脏读这件事情是非常要不得的,一定要解决掉!让事务之间隔离起来才是硬道理。

    那第 2 条,不可重复读又怎么解释呢?还是用类似的例子来说明:

     

    时间事务 A(存款)事务 B(取款)
    T1开始事务 
    T2 开始事务
    T3 查询余额(1000 元)
    T4查询余额(1000 元) 
    T5 取出 1000 元(余额 0 元)
    T6 提交事务
    T7查询余额(0 元) 


    事务 A 其实除了查询了两次以外,其他什么事情都没有做,结果钱就从 1000 变成 0 了,这就是重复读了。可想而知,这是别人干的,不是我干的。其实这样也是合理的,毕竟事务 B 提交了事务,数据库将结果进行了持久化,所以事务 A 再次读取自然就发生了变化。

    这种现象基本上是可以理解的,但在有些变态的场景下却是不允许的。毕竟这种现象也是事务之间没有隔离所造成的,但我们对于这种问题,似乎可以忽略。

    最后一条,幻读。我去!Phantom 这个单词不就是“幽灵、鬼魂”吗?刚看到这个单词时,真的把我的小弟弟都给惊呆了。怪不得这里要翻译成“幻读”了,总不能翻译成“幽灵读”、“鬼魂读”吧。其实意义就是鬼在读,不是人在读,或者说搞不清楚为什么,它就变了,很晕,真的很晕。还是用一个示例来说话吧:

    时间事务 A(统计总存款)事务 B(存款)
    T1开始事务 
    T2 开始事务
    T3统计总存款(10000 元) 
    T4 存入 100 元
    T5 提交事务
    T6统计总存款(10100 元) 


    银行工作人员,每次统计总存款,都看到不一样的结果。不过这也确实也挺正常的,总存款增多了,肯定是这个时候有人在存钱。但是如果银行系统真的这样设计,那算是玩完了。这同样也是事务没有隔离所造成的,但对于大多数应用系统而言,这似乎也是正常的,可以理解,也是允许的。银行里那些恶心的那些系统,要求非常严密,统计的时候,甚至会将所有的其他操作给隔离开,这种隔离级别就算非常高了(估计要到 SERIALIZABLE 级别了)。

    归纳一下,以上提到了事务并发所引起的跟读取数据有关的问题,各用一句话来描述一下:

    1. 脏读:事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作。

    2. 不可重复读:事务 A 读取了事务 B 已提交的更改数据。

    3. 幻读:事务 A 读取了事务 B 已提交的新增数据。

    第一条是坚决抵制的,后两条在大多数情况下可不作考虑。

    这就是为什么必须要有事务隔离级别这个东西了,它就像一面墙一样,隔离不同的事务。看下面这个表格,您就清楚了不同的事务隔离级别能处理怎样的事务并发问题:

     

    事务隔离级别脏读不可重复读幻读
    READ_UNCOMMITTED允许允许允许
    READ_COMMITTED禁止允许允许
    REPEATABLE_READ禁止禁止允许
    SERIALIZABLE禁止禁止禁止


    根据您的实际需求,再参考这张表,最后确定事务隔离级别,应该不再是一件难事了。

    JDBC 也提供了这四类事务隔离级别,但默认事务隔离级别对不同数据库产品而言,却是不一样的。我们熟知的 MySQL 数据库的默认事务隔离级别就是 READ_COMMITTED,Oracle、SQL Server、DB2等都有有自己的默认值。我认为 READ_COMMITTED 已经可以解决绝大多数问题了,其他的就具体情况具体分析吧。

    若对其他数据库的默认事务隔离级别不太清楚,可以使用以下代码来获取:

    DatabaseMetaData meta = DBUtil.getDataSource().getConnection().getMetaData();int defaultIsolation = meta.getDefaultTransactionIsolation();

    提示:在 java.sql.Connection 类中可查看所有的隔离级别。

    我们知道 JDBC 只是连接 Java 程序与数据库的桥梁而已,那么数据库又是怎样隔离事务的呢?其实它就是“锁”这个东西。当插入数据时,就锁定表,这叫“锁表”;当更新数据时,就锁定行,这叫“锁行”。当然这个已经超出了我们今天讨论的范围,所以还是留点空间给我们的 DBA 同学吧,免得他没啥好写的了。

    除了 JDBC 给我们提供的事务隔离级别这种解决方案以外,还有哪些解决方案可以完善事务管理功能呢?

    不妨看看 Spring 的解决方案吧,其实它是对 JDBC 的一个补充或扩展。它提供了一个非常重要的功能,就是:事务传播行为(Transaction Propagation Behavior)。

    确实够牛逼的,Spring 一下子就提供了 7 种事务传播行为,这 7 种行为一出现,真的是亮瞎了我的狗眼!

    1. PROPAGATION_REQUIRED

    2. RROPAGATION_REQUIRES_NEW

    3. PROPAGATION_NESTED

    4. PROPAGATION_SUPPORTS

    5. PROPAGATION_NOT_SUPPORTED

    6. PROPAGATION_NEVER

    7. PROPAGATION_MANDATORY

    看了 Spring 参考手册之后,更是晕了,这到底是在干嘛?

    首先要明确的是,事务是从哪里来?传播到哪里去?答案是,从方法 A 传播到方法 B。Spring 解决的只是方法之间的事务传播,那情况就多了,比如:

    1. 方法 A 有事务,方法 B 也有事务。

    2. 方法 A 有事务,方法 B 没有事务。

    3. 方法 A 没有事务,方法 B 有事务。

    4. 方法 A 没有事务,方法 B 也没有事务。 

    这样就是 4 种了,还有 3 种特殊情况。还是用我的 Style 给大家做一个分析吧:

    假设事务从方法 A 传播到方法 B,您需要面对方法 B,问自己一个问题:

    方法 A 有事务吗?

    1. 如果没有,就新建一个事务;如果有,就加入当前事务。这就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默认事务传播行为,适合绝大多数情况。

    2. 如果没有,就新建一个事务;如果有,就将当前事务挂起。这就是 RROPAGATION_REQUIRES_NEW,意思就是创建了一个新事务,它和原来的事务没有任何关系了。

    3. 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。这就是 PROPAGATION_NESTED,也就是传说中的“嵌套事务”了,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)。

    4. 如果没有,就以非事务方式执行;如果有,就使用当前事务。这就是 PROPAGATION_SUPPORTS,这种方式非常随意,没有就没有,有就有,有点无所谓的态度,反正我是支持你的。

    5. 如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是 PROPAGATION_NOT_SUPPORTED,这种方式非常强硬,没有就没有,有我也不支持你,把你挂起来,不鸟你。

    6. 如果没有,就以非事务方式执行;如果有,就抛出异常。这就是 PROPAGATION_NEVER,这种方式更猛,没有就没有,有了反而报错,确实够牛的,它说:我从不支持事务!

    7. 如果没有,就抛出异常;如果有,就使用当前事务。这就是 PROPAGATION_MANDATORY,这种方式可以说是牛逼中的牛逼了,没有事务直接就报错,确实够狠的,它说:我必须要有事务!

    看到我上面这段解释,小伙伴们是否已经感受到,被打通任督二脉的感觉?多读几遍,体会一下,就是您自己的东西了。

    需要注意的是 PROPAGATION_NESTED,不要被它的名字所欺骗,Nested(嵌套),所以凡是在类似方法 A 调用方法 B 的时候,在方法 B 上使用了这种事务传播行为,如果您真的那样做了,那您就错了。因为您错误地以为 PROPAGATION_NESTED 就是为方法嵌套调用而准备的,其实默认的 PROPAGATION_REQUIRED 就可以帮助您,做您想要做的事情了。

    Spring 给我们带来了事务传播行为,这确实是一个非常强大而又实用的功能。除此以外,也提供了一些小的附加功能,比如:

    1. 事务超时(Transaction Timeout):为了解决事务时间太长,消耗太多的资源,所以故意给事务设置一个最大时常,如果超过了,就回滚事务。

    2. 只读事务(Readonly Transaction):为了忽略那些不需要事务的方法,比如读取数据,这样可以有效地提高一些性能。

    最后,推荐大家使用 Spring 的注解式事务配置,而放弃 XML 式事务配置。因为注解实在是太优雅了,当然这一切都取决于您自身的情况了。

    在 Spring 配置文件中使用:

    ...<tx:annotation-driven />...

    在需要事务的方法上使用:

    @Transactionalpublic void xxx() {
        ...
    }

    可在 @Transactional 注解中设置:事务隔离级别、事务传播行为、事务超时时间、是否只读事务。

    简直是太完美了,太优雅了!

    最后,有必要对本文的内容做一个总结,免费赠送一张高清无码思维导图

    原文地址:https://my.oschina.net/huangyong/blog/160012

     

    展开全文
  • transaction、Conference、Workshop的区别

    千次阅读 2019-03-03 13:00:53
    Transaction中的文章对于相关背景的介绍比较少,相关理论也会少一点。 Journal就是期刊的意思,里面的文章对相关背景的介绍会多一些,而且理论深度比较深,因此看起来比较厉害。例如:IEEE/OSA Journal of Display ...

    full paper、short paper、poster、oral:

    而CV界的会议一般分三级:
    oral,需要作者准备PPT上台进行presentation;
    poster,作者贴一张海报,如果有人感兴趣就会到该作者的墙报前面讨论;
    workshop,一般都是某些大牛觉得该领域有哪些方面是研究热点,就向会议chair申请开一个独立的研讨会,值得注意的是workshop是独立审稿的。
    总的来说,这些都算该会议的publication,只是由于接受率不同,所以论文档次也有所不同,一般说来,刚提到的三种文章在同一个会议中档次是降序排列的。

    另外,在数据挖掘,信息检索领域,会议除了一般分为:
    full paper:全文收录;
    short paper:如果审稿人认为作者的文章没那么优秀,但是又没有很强的理由拒绝,就会询问作者是否愿意降格为该类文章(参考会议:CIKM)。啰嗦一句,会议一般不会专门开设一个track让作者投short paper,这与下面要说的poster有所不同。
    poster:通常只有2页,也有可能是上述情况(不同会议的叫法不同),也有可能是作者只希望把自己的idea讲出来,于是特意投了一个poster(参考会议 WWW, SIGIR)

    作者:姜子恒
    链接:http://www.zhihu.com/question/20186384/answer/14262884
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。




    transaction、Conference、Workshop:

    Transactions我们最熟悉的意思是事务,而它还有一个意思被称为“议事录”。一般情况下是某个专业或者学会的议事录,比如:IEEE Transactions on Aerospace and Electronic Systems。Transaction中的文章对于相关背景的介绍比较少,相关理论也会少一点。

    Journal就是期刊的意思,里面的文章对相关背景的介绍会多一些,而且理论深度比较深,因此看起来比较厉害。例如:IEEE/OSA Journal of Display Technology。

    Conference:大家常说的会议。

    Conference Proceeding和Conference Paper的区别:在一些会议开完后,会对会议上讨论的文章进行整理和发布。发表了的会议论文被称为Conference Paper,而没有发表的称为Conference Proceeding。因此在引用Conference Proceeding时不需要标记页码(pp. xx-xx),而引用Conference Paper时就需要标记了。

    workshop,一般都是某些大牛觉得该领域有哪些方面是研究热点,就向会议chair申请开一个独立的研讨会,值得注意的是workshop是独立审稿的。

    展开全文
  • START TRANSACTION - 开始一个事务块

    千次阅读 2019-06-28 09:07:00
    START TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ] DESCRIPTION 描述 这条命令开始一个新的事务。如果声明了隔离级别或者读写模式,那么新事务就使用这个...
  • spring注解@Transaction详解

    千次阅读 2017-08-02 00:36:11
    原因: ...此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调
  • mysql之commit,transaction事物控制

    千次阅读 2017-07-25 10:45:46
    简单来说,transaction就是用来恢复为以前的数据。 举个例子,我想把今天输入到数据库里的数据在晚上的时候全部删除,那么我们就可以在今天早上的时候开始transaction事物,令autocommit关闭并且执行commit,然后再...
  • COMMIT TRANSACTION (Transact-SQL)

    千次阅读 2016-09-24 17:22:30
    本主题适用于:SQL Server(从 ... 如果 @@TRANCOUNT 为 1,COMMIT TRANSACTION 使得自从事务开始以来所执行的所有数据修改成为数据库的永久部分,释放事务所占用的资源,并将 @@TRANCOUNT 减少到 0。 如果 @@TRA
  • Spring 事务 注解@Transaction 用法

    万次阅读 2018-08-09 00:06:12
    在实际开发中,对于一组数据库操作特别是增...Spring中可以通过注解@Transaction 常用的方法如下:   @Transactional public void testTransaction(User user) { int rowNum = userMapper.insertUser(user);...
  • 安装好几次都是这样,求教大神 ![图片说明](https://img-ask.csdn.net/upload/201911/28/1574874384_153100.png)
  • (1)autonomous_transaction-自治事务,该程序块的commit或rollback不影响外层事务; (2)exception_init--错误代码与declare的标识符关联; (3)restrict_references--程序包的纯度级别; (4)serially_...
  • 一 Transaction(事务)接口 事务简单的说,就是一组对数据库的操作集合,它们要么全部成功,要么全部失败.这个可以保证数据的一致性,事务具有原子性。 ①Transaction是底层的事务实现中抽象出来的接口。 ②可能是一...
  • 可以看到的是 , Letter 的内容通常是 Short Paper, 有即时性的 , 而 Transaction 收录的内 容则没有这个在时间上的特性 . 3 至于 Journal 的內容 , 是属于比较难的 。 Journal 所收录的內容介于 Transaction 及 ...
  • 转自《知乎》如何写好一篇高质量的IEEE/ACM Transaction级别的计算机科学论文? 问题: 作为一个博士生,一直为写论文头疼,读过很多高质量论文,觉得写的真好,但是轮到自己写总是力不从心。 最讨厌的是活生生的把...
  • BEGIN TRANSACTION (Transact-SQL)

    千次阅读 2016-09-24 17:20:39
    BEGIN TRANSACTION 使 @@TRANCOUNT 按 1 递增。   适用范围:SQL Server(SQL Server 2008 至当前版本),Azure SQL Database。  Transact-SQL 语法约定 语法
  • 数据表_事物码(Transaction Code)信息

    千次阅读 2017-06-06 15:40:36
    SAP的事物码(Transaction Code,简写T-CODE)相关信息存放在三张表(Table)中: 数据表TSTC存放T-CODE的关联程序、屏幕信息; 数据表TSTCP存放相关参数,如变式名称及赋值等; 数据表TSTCT存放语言文本,为...
  • 一、主要分类Journal期刊:刊登关于某特殊主题的文章的期刊 magazine杂志:综合性内容的期刊 ...IEEE的paper大体分为3类,letter,magazine,journal/transaction.IEEE letter:属于快报形式,一般...
  • 一般出现这种情况都是服务里面的"Distributed Transaction Coordinator" 意外停止。我们试着打开电脑的服务,发现DTC服务没 有启动。手动启动它,启动不了,电脑重启,还是启动不了。没办法了,上网看看资料。网络就是...
  • TransactionSystemException

    千次阅读 2018-09-19 14:41:31
    无法解决的问题:最终解决方案将Log...org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while...
  • 主要介绍了MySQL数据库事务隔离级别(Transaction Isolation Level) ,需要的朋友可以参考下
  • 数据库处理中的begin transaction 命令

    万次阅读 2015-12-04 10:56:23
    begin transaction 命令 启动一个事务处理。仅对数据库中的表支持事务处理。有关如何在数据库中创建和增加表的详细信息,请参阅 CREATE DATABASE 和 ADD TABLE 。 具体的作用和用法说明: 为了保存所做的修改并...
  • Android 运行不正常关闭,在一堆报错里面找到了FAILED Binder Transaction。 百度了一下基本一致的说法就是: 在Intent 中传递bitmap时,要限制图片小于40K. 看了一些解决方案,分为以下几种: 1.从根本出发直接...
  • 主要介绍了Android app开发中Fragment的Transaction操作,包括Transaction和Fragment的生命周期的联系等内容,需要的朋友可以参考下
  • javax.transaction.jar

    2016-04-26 10:17:34
    javax.transaction.jar javax.transaction.jar
  • Principles of transaction processing Copyright © 2009 by Elsevier Inc. All rights reserved
  • Spring 之 @Transaction 详解

    千次阅读 多人点赞 2020-05-12 22:23:53
    @Transaction 是 Spring 提供用来控制事务回滚/提交的一个注解,让我们从编程式注解转换到声明式注解。在这里就不做过多的撰述,今天主要来看下 @Transaction 里面的属性使用。 作用域 @Transaction 可以写在类、...
  • Runtime-Settings-Miscellaneous--Automatic Transactions 在脚本和场景设置中同时勾上这两项,保存后,再去掉勾选这两项,再保存,即可解决问题
  • private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations"); private static final ...
  • C# 执行Transaction事务的一般例子,创建SqlTransaction 对象并用SqlConnection对象的BeginTransaction()方法开始事务,将Transaction属性设置为上面所生成的SqlTransaction对象。 运行环境:Visual Studio2010
  • pending transaction

    千次阅读 2008-06-17 13:18:00
    Launch the Move Transaction Manager even if the TP:WIP Move Transaction Profile Option = on-line processing. (Navigation -> Inventory/Setup/Transactions/Interface Managers). Use the "Launch Manager" ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 590,303
精华内容 236,121
关键字:

transaction是什么