软件系统设计-事务处理

数据库事务处理

本篇采用5W2H对本知识点进行分析、总结、归纳

What

什么是数据库事务?

事务处理是一种数据处理技术,主要用于记录和跟踪软件系统的特定业务活动,确保数据的完整性和一致性。它涉及将多个相关的数据库操作组合成一个单一的逻辑单元,这个单元要么完全执行,要么完全不执行,以确保数据的准确性和系统的稳定性。这种处理方式通常具有ACID属性,即

	· 原子性(Atomicity):即本次操作的执行过程要么成功,要么失败,不存在中间态,这就是原子性;
	· 隔离性(Isolation):即本次操作的数据在事务未提交前,不可能被其他操作可见,也不可能访问到其他事务操作的数据;
	· 一致性(Consistency):即本次操作的结果和数据库中实际的数据结果是相符合的,不会出现事务成功而数据库中没有相应数据的情况;
	· 持久性(Durability):即事务成功完成后,数据被持久化的保存到磁盘中,从而设备的关机不会导致数据丢失;

这些属性共同保证了事务的正确执行、数据持久化、数据一致性等重要功能特征,在实际应用中,事务处理系统涉及多个阶段,如开始事务、提交事务、执行
事务和结束事务,特殊情况下还包括事务回滚过程。

以一个例子来说明事务处理的过程
TaoBao是一个在线商城。当一个商品的交易过程成功完成时,需要确保以下三件事情被正确地处理:
(此处为便于理解,省去资金在平台进行托管的流程)
· 买家的账号扣减相应的商品款项;
· 商品仓库中扣减库存,将商品配送给买家;
· 商家的账号增加买家所支付的商品款项。
从上面的例子可以看出,一个商品成功交易后,必须保证上面三个步骤全部执行成功,若其中任意一个步骤出错,整笔交易就会失败,被修改的数据需要恢复到交易前的状态,比如买家扣的款项要退回,仓库口的库存需恢复,商家收到的款项需扣减等等。

有哪几种数据库事务类型?

  • 本地事务
    本地事务(Local Transaction)本质上是"局部事务",“单数据源事务”,只是本地事务的叫法更为耳熟能详。本地事务是指只操作单一数据源事务,无需第三方事务协调器(分布式事务中的概念)来管理事务过程的事务。
    本地事务是只适用于单个服务使用单个数据源的场景。从应用角度看,事务的能力完全由数据库提供,对于编程人员而言,只能调用数据库提供的接口来通知数据库开启事务、封装数据、提交事务,本质上事务的开启、终止、提交、回滚、嵌套、设置隔离级别等功能,全部都要依赖底层数据源的支持才能工作。所以本地事务和后续提到的分布式事务相比,无论是功能流程、还是要解决的问题都差异很大

  • 分布式事务
    分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单来说就是软件系统有了多个不同的数据源,这些数据源不仅地理位置不同,保存的数据内容也会不同,并且每个业务操作都涉及对多个数据源的修改,此时分布式事务就保证这些对数据源的修改要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证分布式系统中的单个业务操作对多个数据源的修改都能符合最终的预期。

举例来说: 在分布式系统中,往往有多个服务集群,每个服务集群有各自的数据源集群,比如订单服务集群+订单数据库集群,库存服务集群+库存数据库集群等等,一次下订单的业务操作涉及对订单服务集群、库存服务集群的操作,分布式事务是为了保证做了下订单操作后,订单服务集群的订单信息、库存服务的库存信息都能正确更新(或者失败后能回滚恢复)。

Why

为什么设计据库事务功能?

数据库事务的设计就是为了保证操作的结果符合预期(即使操作失败也应该恢复操作前的状态)。
以最经典的分布式事务场景-转账为例,假设用户1使用银行 app 发起一笔转账给用户2,银行系统需要扣掉用户1的钱,然后增加用户2 账户中的余额。在分布式系统中会出现 2 种异常情况(因为扣钱和加钱的操作不能用串行模式,否则会很影响业务性能):
1. 用户1的账户扣款成功,用户2账户余额增加失败
2. 用户1账户扣款失败,用户2账户余额增加成功
无论是对于银行系统还是客户来说,以上 2 种情况都是不能接受的,而分布式事务可以保证转账操作的成功。

Who

推动数据库事务技术发展的几个大佬?

When

数据库事务技术发展有几个阶段?

Where

什么情况、场景下要使用数据库本地事务?

单体软件架构+单体数据源的设计下会使用本地事务来保证数据操作的可靠性。

什么情况、场景下要使用数据库分布式事务?

在Why章节中有所提及,后续再丰富

How-实战使用

此处基于SpringBoot来进行简单的事务实战

本地事务技术使用

  • 代码示例(源码参考开源项目Spring-Cloud-Alibaba)
public class AccountServiceImpl implements AccountService {

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

	@Autowired
	private AccountMapper accountMapper;

	//此处基于SpringBoot的@Transactional实现本地的事务管理
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void reduceBalance(String userId, Integer price) throws BusinessException {
		logger.info("[reduceBalance] currenet XID: {}", RootContext.getXID());

		checkBalance(userId, price);

		Timestamp updateTime = new Timestamp(System.currentTimeMillis());
		int updateCount = accountMapper.reduceBalance(userId, price, updateTime);
		if (updateCount == 0) {
			throw new BusinessException("reduce balance failed");
		}
	}
}
  • @Transactional 核心原理分析

  • 说明:从这个注解就可以看出其底层是基于AOP实现的,本质上是对该注解标记的方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。通过声明式事物,无需在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),即可实现普通数据操作的事务化。

  • 事务AOP切面分析

    • 主要类
      • @Transactional
      • TransactionAttribute
      • SpringTransactionAnnotationParser
      • AnnotationTransactionAttributeSource
      • TransactionInterceptor
      • BeanFactoryTransactionAttributeSourceAdvisor
      • ProxyTransactionManagementConfiguration
      • PlatformTransactionManager
      • TransactionStatus
      • TransactionDefinition
    • 流程分析
      • 创建代理对象:当目标对象被 Spring 管理时,Spring 会为目标对象创建一个代理对象。代理对象负责拦截目标方法的调用,并在必要时应用事务管理。

      • 事务拦截器:代理对象内部包含一个事务拦截器(TransactionInterceptor),负责处理事务相关的逻辑。事务拦截器实现了 MethodInterceptor 接口,可以拦截目标方法的调用。

      • 事务切点:事务拦截器使用事务切点(TransactionAttributeSourcePointcut)来确定哪些方法需要应用事务。事务切点根据方法上的 @Transactional 注解和其他配置信息来决定是否应用事务。

      • 事务管理器:事务拦截器通过事务管理器(PlatformTransactionManager)来启动和管理事务。事务管理器负责协调数据库连接、事务的开始、提交或回滚等操
        作。

      • 事务通知:事务拦截器在目标方法执行前后应用事务通知。在方法执行前,事务拦截器启动事务;在方法执行后,根据方法的执行结果决定事务的提交或回滚。

      • 事务的传播行为:事务拦截器还负责处理事务的传播行为。事务的传播行为定义了事务方法如何与其他事务方法进行交互和协调。

  • @Transactional事务失效的常见场景

    • 事务注解的方法使用非public的标志
    • 事务方法被final、static修饰
    • 方法内对Exception做了Try-Catch-影响事务回滚
    • 同一个类中,未被注解的方法调用了注解过的代码
    • 多线程内调用事务导致事务失效
    • 当前类未交予Spring管理(即未被@Component,@Service等注解标志的事务注解不会生效)
    • 注解未配置对Exception.class的回滚(默认只支持RuntimeException和Error的回滚)
    • 数据库本身不支持事务

分布式事务技术使用

以Alibaba的Seata框架来进行分布式事务实战

How Much

事务使用要考虑什么代价-有什么成本?

个人总结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值