1. 原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。
2. 一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种 正确状态
3. 隔离性:在事务正确提交之前,不允许把该事务对数据的任何改变提供 给任何其他事务
4. 持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务 提交后有了其它故障,事务的处理结果也会得到保存。
脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改, 而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据, 然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个 事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务 也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失 修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修 改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。 在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务 中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数 据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情 况,因此称为不可重复读。
幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务 (T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在 随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就 好像发生了幻觉一样,所以称为幻读。
不可重复读和幻读区别: 不可重复读的重点是修改,比如多次读取一 条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如 多次读取一条记录发现记录 增多或减少了
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交 的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可 以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致 的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻 读仍有可能发生。
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级 别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就 是说,该级别可以防止脏读、不可重复读以及幻读。
一、微服务之间通过远程调用完成事务操作

二、单体系统访问多个数据库实例
比如:用户信息和订单信息分别在两个Mysql实例存储,用户管理系统删除用户信息,需要分别删除信息以用户的订单信息。由于数据分布在不同的数据库实例,需要通过不同的数据库连接去操作数据

三、多服务访问同一个数据库实例
比如:订单微服务和存库微服务即使访问同一个数据库也会产生分布式事务,原因就是跨JVM进程,两个微服务持有了不同的数据库连接进行数据库操作。

使用消息中间件手写代码解决分布式事务使用第三方组件 --->Seata 阿里巴巴的产品
seata的官网如下:
Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata的执行流程如下:
1. A 服务【订单微服务】的 TM[ 事务发起者 ] 向 TC[seata 服务端 ] 申请开启一个全局事务, TC 就会创建一个全局事务并返回一个唯一的 XID2. A 服务开始远程调用 B 服务【账户微服务】,此时 XID 会在微服务的调用链上传播3. B 服务的 RM 向 TC 注册分支事务,并将其纳入 XID 对应的全局事务的管辖4. B 服务执行分支事务,向数据库做操作5. 全局事务调用链处理完毕, TM 根据有无异常向 TC 发起全局事务的提交或者回滚6. TC 协调其管辖之下的所有分支事务, 决定是否回滚
这里需要注意的是springcloud的版本要和seata的版本相对应,下面是版本对照表

我们可以从这个网址下载所需要的seata的版本




seata默认引入的jar包没有包含MySQL的jar包,需要我们从lib/jdbc目录下复制下相对应的MySQL的jar包到lib目录下

这里的数据库表结构可以在源码中找到




nacos中需要存储哪些配置文件呢?



先开启seata服务



执行完之后上面这个页面会自动关闭,这时我们去nacos配置中心会发现生成的这些配置文件

如果想人为指定nacos配置中心的地址
在 Windows Terminal 下打开 Git 安装目录 bin 文件夹,执行 .\sh.exe 进入 sh 命令窗口,在 sh 窗口下导航至 \seata-1.3.0\script\config-center\nacos 文件夹,执行以下命令将配置导入 Nacos;
- # 导入,t:命名空间,g:分组,p:端口号,h:IP地址
- sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 5e22d16b-da6c-4f3f-8f3a-41cb501f18e5


- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-seataartifactId>
- dependency>

然后添加seata注册中心和配置中心的相关配置
- # 指定seata服务器所在nacos的注册中心的地址
- seata:
- registry:
- type: nacos
- nacos:
- # 指定seata服务器所在的注册中心地址
- server-addr: localhost:8848
- username: nacos
- password: nacos
- # 指定seata服务器所在的注册中心地址 默认SEATA_GROUP
- group: SEATA_GROUP
- # 指定seata服务器在注册中心的服务名称 默认seata-server
- application: seata-server
- config:
- type: nacos
- nacos:
- server-addr: localhost:8848
- username: nacos
- password: nacos
- group: SEATA_GROUP
@Transactional //只是本地事务 它只能回滚本地自己连接的数据库 无法回滚其他微服务连接数据库。@GlobalTransactional //全局事务

然后启动项目进行测试,访问
localhost:8001/order/addOrder?userId=1&productId=1&money=100&count=10
先验证下单成功

验证下单失败


