1、 事务简介
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
在关系数据 库中,一个事务由一组SQL语句组成。事务应该具有4个属性:【原子性、一致性、隔离性、持久性】。 这四个属性通常称为ACID特性。
2、在JDBC编程中,我们通过java.sql.Connection对象来开启、关闭或者提交事务。代码如下所 示
Connection conn = ... //获取数据库连接
2 conn.setAutoCommit(false); //开启事务
3 try{
4 //...执行增删改查sql
5 conn.commit(); //提交事务
6 }catch (Exception e) {
7 conn.rollback();//事务回滚
8 }finally{
9 conn.close();//关闭链接
10 }
3 、Transational 声明式事务
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务 (Local Transaction)。本地事务的ACID特性是数据库直接提供支持。
4、如果遇见以下情况。【跨库事务、分库分表、服务化】 需要用到分布式事务
Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B 又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要 不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。
分布式事务
什么是分布式事务:
指一次大的操作由不同的小操作组成的,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
常见的解决方案(seata、消息队列、XA、saga)
分布式事务Seata
seata 是一款分布式事务的解决方案、是阿里开源的一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。
seata将为用户提供了 【AT 、TCC、SAGA、和AX 】事务模式
AT----在数据库层面 需要加入行级锁 一种无侵入的分布式事务解决方案。
在第一阶段,seata会拦截业务SQL,首先解析SQL 语义,找到业务SQL 要更新的业务数据,在业务数据被更新前,将其保存成 before image 然后执行sql 更新业务语句,在业务数据更新之后,将其在保存到 after image 最后生成行锁,以上操作全部在一个数据库事务内完成,这样保证了一阶段的原子性。
在第二阶段,如果是提交的话,因为业务sql 在第一级段已经执行,只要删除 before image 和 after image 和行锁
在第二阶段回滚、before image 保存最初的数据 逆向sql 数据还原。 删除before image 删除 after image 删除行锁
TCC---在业务层面 侵入性比较强 编写代码较多 没有锁的概念 性能强
TCC 模式需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作;事务发起方在一阶 段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。
try (){
sendMQ
}
confirm(){
} 数据入库 cancel 回滚
SAGA:
AX:
2、2pc(两个阶段)
Prepare :
1. 询问--- 协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应。
2. 执行-- 各个参与者接收到协调者事务请求后,执行事务操作(例如更新一个关系型数据库表中的记录),并将 Undo 和 Redo 信息记录事务日志中。
3. 响应 如果参与者成功执行了事务并写入 Undo 和 Redo 信息,则向协调者返回 YES 响应,否则返回 NO 响应。当然,参与者也可能宕机,从而不会返回响应
commit:
1、commit 请求 协调者向所有参与者发送 Commit 请求。
2. 事务提交 参与者收到 Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
3. 反馈结果 参与者执行事务提交后向协调者发送 Ack 响应。
4. 完成事务 接收到所有参与者的 Ack 响应后,完成事务提交。
TC 事务协调者
维护全局和分支事务的状态,驱动全局事务提交和回滚
TM 事务管理器
开启全局事务,配合事务协调者提交或回滚
RM 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚
分布式事务Seata在微服务中的应用
快速搭建Seata服务 环境
技术栈: springboot + mysql5.7以上 + nacos
1、新建mysql 数据库 seata_server
-- -------------------------------- The script used when storeMode is 'db' -------------------------------- -- the table to store GlobalSession data CREATE TABLE IF NOT EXISTS `global_table` ( `xid` VARCHAR(128) NOT NULL, `transaction_id` BIGINT, `status` TINYINT NOT NULL, `application_id` VARCHAR(32), `transaction_service_group` VARCHAR(32), `transaction_name` VARCHAR(128), `timeout` INT, `begin_time` BIGINT, `application_data` VARCHAR(2000), `gmt_create` DATETIME, `gmt_modified` DATETIME, PRIMARY KEY (`xid`), KEY `idx_gmt_modified_status` (`gmt_modified`, `status`), KEY `idx_transaction_id` (`transaction_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; -- the table to store BranchSession data CREATE TABLE IF NOT EXISTS `branch_table` ( `branch_id` BIGINT NOT NULL, `xid` VARCHAR(128) NOT NULL, `transaction_id` BIGINT, `resource_group_id` VARCHAR(32), `resource_id` VARCHAR(256), `branch_type` VARCHAR(8), `status` TINYINT, `client_id` VARCHAR(64), `application_data` VARCHAR(2000), `gmt_create` DATETIME(6), `gmt_modified` DATETIME(6), PRIMARY KEY (`branch_id`), KEY `idx_xid` (`xid`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; -- the table to store lock data CREATE TABLE IF NOT EXISTS `lock_table` ( `row_key` VARCHAR(128) NOT NULL, `xid` VARCHAR(96), `transaction_id` BIGINT, `branch_id` BIGINT NOT NULL, `resource_id` VARCHAR(256), `table_name` VARCHAR(32), `pk` VARCHAR(36), `gmt_create` DATETIME, `gmt_modified` DATETIME, PRIMARY KEY (`row_key`), KEY `idx_branch_id` (`branch_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
下载客户端的资源目录 : https://seata/script at 1.3.0 · seata/seata · GitHub
client 存放client端sql脚本,参数配置
config-center 各个配置中心参数导入脚本,config.txt(包含server和client,原名nacos-config.txt)为通用参数文件
server server端数据库脚本及各个容器配置
db存储模式+Nacos(注册&配置中心)部署
配置
1、数据库配置
2、注册中心配置
3、naocs 配置中心 文件配置
讲config.txt 文件导入到nacos 中 nacos 有脚本文件可以执行导入
4、启动
sh ${SEATAPATH}/script/config‐center/nacos/nacos‐config.sh ‐h localhost ‐p 8848 ‐g SEATA_GROUP ‐t 5a3c7d6c‐f497‐ 4d68‐a71a‐2e5e3340b3ca
-h: host,默认值 localhost
-p: port,默认值 8848
-g: 配置分组,默认值为 'SEATA_GROUP'
-t: 租户信息,对应 Nacos 的命名空间ID字段, 默认值为空
快速搭建Seata 客户端环境
1、导入Seata 依赖
<dependency>
3 <groupId>com.alibaba.cloud</groupId>
4 <artifactId>spring‐cloud‐starter‐alibaba‐seata</artifactId>
5 </dependency>
2、每个服务都需要交建立以下表
CREATE TABLE `undo_log` (
2 `id` bigint(20) NOT NULL AUTO_INCREMENT,
3 `branch_id` bigint(20) NOT NULL,
4 `xid` varchar(100) NOT NULL,
5 `context` varchar(128) NOT NULL,
6 `rollback_info` longblob NOT NULL,
7 `log_status` int(11) NOT NULL,
8 `log_created` datetime NOT NULL,
9 `log_modified` datetime NOT NULL,
10 PRIMARY KEY (`id`),
11 UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3、修改application.yml配置
4、在需要的地方需要添加@GlobalTransactional注解