本地事务
单服务进程,单数据库资源,同一个连接conn多个事务操作
在JDBC编程中,我们通过java.sql.Connection
对象来开启、关闭或者提交事务。代码如下所示:
Connection conn = ... //获取数据库连接
conn.setAutoCommit(false); //开启事务
try{
//1:张三-100
//2:李四+100
//3.其他操作10/0
conn.commit(); //提交事务
}catch (Exception e) {
conn.rollback();//事务回滚
}finally{
conn.close();//关闭链接
}
Spring声明式事务(基于aop实现)
/**
* @param fromUserName 转账人
* @param toUserName 被转账人
* @param changeSal 转账额度
*/
@Transactional(rollbackFor = Exception.class)
public void changeSal(String fromUserName,String toUserName,int changeSal) {
bankMapper.updateSal(fromUserName, -1 * changeSal);
bankMapper.updateSal(toUserName, changeSal);
int i = 10/0
}
分布式事务的一些问题
分布式事务解决方案
1. 2PC两段提交
两段提交分为两个阶段:
第一个阶段是准备阶段,参与者需要开启事务,执行SQL,保证数据库中已经存在相应的数据。参与者会向TransactionManager准备OK。
第二个阶段当TransactionManager收到了所有的参与者的通知之后,向所有的参与者发送Commit请求。
问题1:执行的性能是很低的。一般是传统事务的10倍以上。
问题2:TransactionManager是没有超时时间的。
问题3:TransactionManager存在单点故障的问题
2. 3PC三段提交
三段提交在二段提交的基础上,引入了超时时间机制,并且在二段提交的基础上,又多了一个步骤,在提交事务之前,再询问一下,数据库的日志信息,是否已经完善。
缺点是过程太过繁琐,耗时,比二段提交还耗时
TCC机制
TCC(Try,Confirm,Cancel),和你的业务代码切合在一起。
Try:尝试去预执行具体业务代码。 下单订ing。。。
try成功了:Confirm:再次执行Confirm的代码。
try失败了:Cancel:再次执行Cancel的代码。
会造成锁单
MQ分布式事务
RabbitMQ在发送消息时,confirm机制,可以保证消息发送到MQ服务中,消费者有手动ack机制,保证消费到MQ中的消息。