spring 事务管理与数据库隔离级别
1遇到问题: spring 事务中保存了对象后 启动一个线程获取对象无效
public void postDispatchDoc(DispatchDoc entity) {
try {
dispatchMapper.save(entity);// 保存对象
new Thread(new SendMsgThread(userIds)).start(); //如果流程已经完成则发送短信
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
DispatchDoc disPatch = dispatchMapper.queryById(entityId); //查询对象
sendMsg(dispatch); //发送短信
} catch (Exception e) {
e.printStackTrace();
}
}
写web项目的时候,我们一般在service层中启用事务。在一个事务当中,只有方法执行完毕才会提交结果到数据库。而在service中方法中调用另个一个线程,另外一个线程不在当前事务中,有肯能在事务还没有提交前就已经执行。
mysql默认的事务隔离级别是 repeatable-read 对照下面可以查看出,mysql不可能dirty read & nonRepeatable Read 有可能 phantom Read
那么具体是什么意思呢?
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
看了解释时候还是不懂通俗的说mysql默认就是:事务A操作了数据库的同时,B也操作,若B未提交。A读取不到。B提交后,A才能获取。除非A统计数据时B在此期间插入一条数据。如果考虑这种情况需要将数据库设置成串行化设置方式如下:
set session transaction isolation level serializable;
查看当前数据库的隔离级别:
现在总数弄明白了,mysql的事务原理。当启动一个线程后另一个线程读取不到未提交的数据。
2解决:那么怎么才能在service层中当mapper对象保存完数据后立即发送短信或则邮件功能呢?
*一般边缘的操作,通常会设置成为异步的,以提升性能,比如发送MQ,业务系统负责事务成功后消息发送成功,然后接收系统负责保证通知成功完成。以上的业务即使能获取到业务,也要保证提交成功否则回退后发短信无效。
如何在spring事务提交之后进行异步操作,这些异步操作必须得在该事务成功提交后才执行,回滚则不执行
使用TransactionSynchronizationManager在事务提交之后操作
//该方法就可以实现在事务提交之后进行操作
public void insert(TechBook techBook){
bookMapper.insert(techBook);
// send after tx commit but is async
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
System.out.println("send email after transaction commit...");
}
}
);
ThreadLocalRandom random = ThreadLocalRandom.current();
if(random.nextInt() % 2 ==0){
throw new RuntimeException("test email transaction");
}
System.out.println("service end");
}
上一篇: Spring数据库事务管理
下一篇: Spring跨数据库事务管理
推荐阅读
-
Spring Boot 与 Kotlin 使用JdbcTemplate连接MySQL数据库的方法
-
Spring Boot 与 Kotlin 使用Redis数据库的配置方法
-
ORACLE数据库事务隔离级别介绍
-
Spring Boot 与 Kotlin 使用JdbcTemplate连接MySQL数据库的方法
-
Spring Boot 与 Kotlin 使用Redis数据库的配置方法
-
MySQL数据库事务隔离级别详解
-
RR与RC隔离级别下索引和锁的测试脚本示例代码
-
深入分析MSSQL数据库中事务隔离级别和锁机制
-
Spring事务隔离级别简介及实例解析
-
高性能MySQL--innodb中事务的隔离级别与锁的关系