1. XA模式
1.1 原理
1.1.1 XA模式原理
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
1.1.2 seata的XA模式
seata的XA模式做了一些调整,但大体相似:
1.1.3 小结
- XA模式的优点是什么?
- 事务的强一致性,满足ACID原则。
- 常用数据库都支持,实现简单,并且没有代码侵入
- XA模式的缺点是什么?
- 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
- 依赖关系型数据库实现事务
1.2 实现XA模式
第一步修改代码
第二步重启服务
第三步测试
正常情况:
异常情况:
ok钱没被扣
2. AT模式(seata默认)
2.1 AT模式原理
2.2 AT模式的脏写问题
出现丢失更新问题,原因就是事务没有做好隔离,解决如下2.3
2.3 AT模式的写隔离
产生死锁:事务1在等待当前属于事务2的DB锁,事务2在等待当前属于事务1的全局锁
此处注意避免与XT模式的混淆:XT模式是数据库锁,锁的力度大,一旦锁定,谁都无法访问被锁数据;此处AT的全局锁是事务协调者TC搞得,力度小,他只是记录事务1(有seata管理),若事务2不是由seata管理的,则可以访问数据,例如修改此表中id=1记录的其他字段
此时,如果事务1直接进行数据恢复将80变为100,则又出现了丢失更新问题
实际上,事务1在保存快照是会保存两份,一份是执行SQL前,一份是之后
2.4 实现AT模式
注意AT和XA模式一样,也需要在全局事务入口加上
@GlobalTransactional
注解
lock_table表导入到seata库,用于记录全局锁
undo_log表导入到seata_demo库,用于记录快照信息
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
`xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
`context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` longblob NOT NULL COMMENT 'rollback info',
`log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` datetime(6) NOT NULL COMMENT 'create datetime',
`log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
`row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`transaction_id` bigint(20) NULL DEFAULT NULL,
`branch_id` bigint(20) NOT NULL,
`resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`gmt_create` datetime NULL DEFAULT NULL,
`gmt_modified` datetime NULL DEFAULT NULL,
PRIMARY KEY (`row_key`) USING BTREE,
INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
重启三个微服务
重启完成,做一下测试
先看一下当前数据
发送请求
发现报错500
再来看一下数据库数据有没有恢复
ok,数据与原先的一致,说明分布式事务生效,有问题的业务都回滚了
上述undo_log表中没有数据,原因是回滚结束后自动删除了记录,实际上会先插入一条记录再删除
2.5 小结
- 简述AT模式与XA模式最大的区别是什么?
- XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
- XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
- XA模式强一致;AT模式最终一致
- AT模式的优点:
- 一阶段完成直接提交事务,释放数据库资源,性能比较好
- 利用全局锁实现读写隔离
- 没有代码侵入,框架自动完成回滚和提交
- AT模式的缺点:
- 两阶段之间属于软状态,属于最终一致
- 框架的快照功能会影响性能,但比XA模式要好很多