事务、分布式事务

事务:逻辑上的一组操作,要么都成功要么都失败

事务的四个特性:ACID 原子性,一致性,隔离性,持久性

事务的隔离级别

读未提交:产生脏读
读已提交:不可重复读
可重复读:幻读(mysql默认)
序列化读:性能最低

传播行为(7个)

七种传播行为:

REQUIRED 支持当前事务,如果不存在,就新建一个

SUPPORTS 支持当前事务,如果不存在,就不使用事务

MANDATORY 支持当前事务,如果不存在,抛出异常

REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务

NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务

NEVER 以非事务方式运行,如果有事务存在,抛出异常

NESTED 如果当前事务存在,则嵌套事务执行(嵌套式事务)

这七种事务传播机制最常用的就两种:

REQUIRED:一个事务,要么成功,要么失败

REQUIRES_NEW:两个不同事务,彼此之间没有关系。一个事务失败了不影响另一个事务

回滚策略

默认情况下的回滚策略:

  • 运行时异常:不受检异常,没有强制要求try-catch,都会回滚。例如:ArrayOutOfIndex,OutofMemory,NullPointException
  • 编译时异常:受检异常,必须处理,要么try-catch要么throws,都不回滚。例如:FileNotFoundException

只读事务

如果一个方法标记为readOnly=true事务,则代表该方法只能查询,不能增删改。readOnly默认为false
给商品新增的事务标记为只读事务:

分布式事务

seata

前提:

  • 启动seata-service服务
  • 数据库表中有undo_log表

1.引入依赖

	<dependency>
	    <groupId>com.alibaba.cloud</groupId>
	    <artifactId>spring-cloud-alibaba-seata</artifactId>
	    <version>2.0.0.RELEASE</version>
	</dependency>
	<dependency>
	    <groupId>io.seata</groupId>
	    <artifactId>seata-all</artifactId>
	    <version>0.8.0</version>
	</dependency>

2.配置文件

registry.conf:配置注册中心和配置中心,默认是file。
该文件包含两部分配置:

  1. 注册中心
  2. 配置中心
registry { # 注册中心配置
  # 可选项:file 、nacos 、eureka、redis、zk
  type = "file" 

  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = "public"
    cluster = "default"
  }
  eureka {
    serviceUrl = "http://localhost:1001/eureka"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6381"
    db = "0"
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 2000
  }
  file {
    name = "file.conf"
  }
}
config { # 配置中心
  # 可选项:file、nacos 、apollo、zk
  type = "file" # 指向file配置中心,也可以指向nacos等其他注册中心

  nacos {
    serverAddr = "localhost"
    namespace = "public"
    cluster = "default"
  }
  apollo {
    app.id = "fescar-server"
    apollo.meta = "http://192.168.1.204:8801"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 2000
  }
  file {
    name = "file.conf"   # 通过file.conf配置seata参数,指向第二个配置文件
  }
}

file.conf:seata工作规则信息

该文件的命名取决于registry.conf配置中心的配置

transport {
  # tcp udt unix-domain-socket
  type = "TCP"
  #NIO NATIVE
  server = "NIO"
  #enable heartbeat
  heartbeat = true
  #thread factory for netty
  thread-factory {
    boss-thread-prefix = "NettyBoss"
    worker-thread-prefix = "NettyServerNIOWorker"
    server-executor-thread-prefix = "NettyServerBizHandler"
    share-boss-worker = false
    client-selector-thread-prefix = "NettyClientSelector"
    client-selector-thread-size = 1
    client-worker-thread-prefix = "NettyClientWorkerThread"
    # netty boss thread size,will not be used for UDT
    boss-thread-size = 1
    #auto default pin or 8
    worker-thread-size = 8
  }
}
## transaction log store
store {
  ## store mode: file、db
  mode = "db"  ## 改成db模式

  ## database store  db相关参数根据个人环境设置
  db {
    driver_class = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://172.16.116.100:3306/guli-pms"
    user = "root"
    password = "root"
  }
}
service {
  #vgroup->rgroup
  # 根据工程的服务名修改
  vgroup_mapping.pms-service-fescar-service-group = "default"
  #only support single node
  default.grouplist = "127.0.0.1:8091"
  #degrade current not support
  enableDegrade = false
  #disable
  disable = false
}
client {
  async.commit.buffer.limit = 10000
  lock {
    retry.internal = 10
    retry.times = 30
  }
}

DataSourceConfig:配置代理数据源实现分支事务,如果没有注入,事务无法成功回滚

每一个微服务原来自己的数据源都必须使用DataSourceProxy代理,这样seata才能掌控所有事务。

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    /**
     * 需要将 DataSourceProxy 设置为主数据源,否则事务无法回滚
     *
     * @param druidDataSource The DruidDataSource
     * @return The default datasource
     */
    @Primary
    @Bean("dataSource")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
}

3.注解 @GlobalTransactional @Transactional

主业务方法添加全局事务:@GlobalTransactional

分支业务方法添加本地事务注解:@Transactional

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值