spring事务相关问题记录

遇到情况:

在本地单体应用调试代码时,发现在一个加了@transaction注解的方法里进行先更新后查询的操作,查询的结果是可以看到更新的内容的。而在微服务环境中同样的代码却在后查询时查不到前面更新的内容。

伪代码如下:

@Transactional

public void call() {

bidPlanMapper.updateByPrimaryKey(plan);

List all = systemService.findBidPlan();

System.out.println(all);//单体应用时可观察到更改的结果

}

猜测本地可以而微服务上不可以,估计是因为微服务在执行call()方法时,update操作是由biz服务调用的,而findBidPlan()操作是实际是调用system服务进行的(该方法也有@Transactional),故产生的是两个事务。

处理办法:

update操作后立刻提交事务,则另外一个事务可以查询到处理的结果。

@Autowired

private DataSourceTransactionManager transactionManager;

public void call() {

//开启新事务

DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();

transDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);

TransactionStatus transStatus = transactionManager.getTransaction(transDefinition);

try {

bidPlanMapper.updateByPrimaryKey(plan);//先提交更新的操作

transactionManager.commit(transStatus);

} catch (Exception e) {

transactionManager.rollback(transStatus);

}

}

扩展阅读:

隔离级别:

隔离级别定义一个事务可能受其他并发事务活动活动影响的程度。另一种考虑一个事务的隔离级别的方式,是把它想象为那个事务对于事物处理数据的自私程度。

在一个典型的应用程序中,多个事务同时运行,经常会为了完成他们的工作而操作同一个数据。并发虽然是必需的,但是会导致以下问题:

脏读(Dirty read)-- 脏读发生在一个事务读取了被另一个事务改写但尚未提交的数据时。如果这些改变在稍后被回滚了,那么第一个事务读取的数据就会是无效的。

不可重复读(Nonrepeatable read)-- 不可重复读发生在一个事务执行相同的查询两次或两次以上,但每次查询结果都不相同时。这通常是由于另一个并发事务在两次查询之间更新了数据。(即不可重复读到同值)

幻影读(Phantom reads)-- 幻影读和不可重复读相似。当一个事务(T1)读取几行记录后,另一个并发事务(T2)插入了一些记录时,幻影读就发生了。在后来的查询中,第一个事务(T1)就会发现一些原来没有的额外记录。

隔离级别

含义

ISOLATION_DEFAULT

使用后端数据库默认的隔离级别。

ISOLATION_READ_UNCOMMITTED

允许读取尚未提交的更改。可能导致脏读、幻影读或不可重复读。

ISOLATION_READ_COMMITTED

允许从已经提交的并发事务读取。可防止脏读,但幻影读和不可重复读仍可能会发生。

ISOLATION_REPEATABLE_READ(MySQL默认隔离级别)

对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻影读仍可能发生。

ISOLATION_SERIALIZABLE

完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。

1.查看当前会话隔离级别

select @@tx_isolation;

2.查看系统当前隔离级别

select @@gobal.tx_isolation;

模拟read committed隔离级别下出现不可重复读的状况:

开启一个事务A进行三次查询。事务B在事务A第一和第二次查询中进行数据更新,事务B在事务A第二次和第三次查询中进行事务提交。

事务A

mysql> SET SESSION TRANSACTION ISOLATION LEVEL read committed; #设置当前会话事务的隔离级别为read committed

mysql> select @@tx_isolation; #查询当前会话事务的隔离级别

+----------------+

| @@tx_isolation |

+----------------+

| READ-COMMITTED |

+----------------+

mysql> start transaction; #开启事务A

Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user; #事务A第一次查询 (1)

+----+------+----------+-------+

| id | name | password | phone |

+----+------+----------+-------+

| 1 | 张三 | 123 | 000 |

+----+------+----------+-------+

###################### 事务B进行更新操作 ##############################

mysql> select * from t_user; #事务A第二次查询,没有看到事务B没有提交的更新操作。说明已经防止了脏读问题。(3)

+----+------+----------+-------+

| id | name | password | phone |

+----+------+----------+-------+

| 1 | 张三 | 123 | 000 |

+----+------+----------+-------+

###################### 事务B进行事务提交 ##############################

mysql> select * from t_user; #观察到事务B提交的结果,说明无法在同个事务中多次查询值都是一样的,即无法避免不可重复读问题。(5)

+----+------+----------+-------+

| id | name | password | phone |

+----+------+----------+-------+

| 1 | 张三 | 123 | 123 |

+----+------+----------+-------+

事务B

mysql> start transaction; #开启事务B

mysql> update t_user set `phone` = '123' where id = 1; #进行更新操作(2)

mysql> commit; #提交事务B (4)

理解REPEATABLE READ 隔离级别下什么是可重复读:

开启两个事务。

事务A

mysql> begin;

mysql> select * from t_user; #(1)

+----+------+----------+-------+

| id | name | password | phone |

+----+------+----------+-------+

| 1 | 张三 | 123 | 188 |

+----+------+----------+-------+

###################### 事务B进行事务提交 ##############################

mysql> select * from t_user; #可观察到两次查询结果都一样,不会因为事务B的更新提交而有影响(3)

+----+------+----------+-------+

| id | name | password | phone |

+----+------+----------+-------+

| 1 | 张三 | 123 | 188 |

+----+------+----------+-------+

事务B

mysql> begin;

mysql> update `t_user` set `phone` = '8888'; #(2)

mysql> commit; #(2)

虽然该隔离级别下是,无论事务B进行更新、新增、删除,在事务A中仍然可以重复读到相同值的。

但是如果事务A进行更新操作,则可以对事务B新增的数据进行直接更新。

可参考如下例子:

在REPEATABLE READ 隔离级别下,MySQL在session1执行UPDATE语句的时候对于session2的INSERT语句是可以看到的,也就是说发生了幻读。

相关阅读:MySQL在REPEATABLE READ 隔离级别下的工作方式

mysql交给spring管理_Mysql事务结合spring管理相关推荐

  1. atitit.spring hibernate的事务机制 spring不能保存对象的解决

    atitit.spring hibernate的事务机制 spring不能保存对象的解决 sessionFactory.openSession() 不能..log黑头马sql语言.. sessionF ...

  2. MySQL学习笔记07【事务、用户管理和权限管理】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  3. mysql spring隔离级别_MySQL事务与Spring隔离级别实现

    1.事务具有ACID特性 原子性(atomicity):一个事务被事务不可分割的最小工作单元,要么全部提交,要么全部失败回滚. 一致性(consistency):数据库总是从一致性状态到另一个一致性状 ...

  4. mysql用户及权限管理_MySQL 用户及权限管理

    1.mysql用户的定义 在mysql中,用户由用户名和主机域组成的. 1.1 用户名的写法 mysql> create user test1@'localhost'; 注意:用户名不要以数字. ...

  5. 使用mysql事务管理_MySQL事务管理的介绍(附示例)

    原标题:MySQL事务管理的介绍(附示例) 事务处理用来维护数据库等完整性,保证mysql操作要么成功,要么失败(myisam不支持事务) 1.关键词 事务(transaction)指一组SQL语句; ...

  6. Mysql drop table 原理_mysql事务的实现原理

    此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中 有一个整体的认识,如下图 如上图所示,M ...

  7. mysql怎么测试事物_mysql事务简单测试

    Auth: jin Date: 20140507 一.事务控制 默认情况下,MySQL是自动提交(autocommit)的,如果需要通过明确的commit和rollblack来提交和回滚事务,那么需要 ...

  8. mysql隔离级别验证_MySQL事务隔离级别以及验证

    查询初始数据 开启A事务 并做更新操作 再另一端 B开始另一个事务查询 事务级别设置为读未提 查询到事务未提交的数据  a的count修改为3 但是没有提交 2 第二个级别 读已提交 避免脏读问题 但 ...

  9. mysql与缓存脏读_MySQL 事务的隔离级别问题 之 脏读

    1. 脏读 所谓的脏读就是指一个事务读取了另一个事务未提取的数据. 试想一下:a账户要给b账户100元购买商品,如果a账户开启一个事务,执行下面的update语句做了如下转账的工作: update a ...

最新文章

  1. ubuntu没有interfaces文件_ubuntu里终端中eth0为何没有显示IP地址
  2. 【ElasticSearch系列】简单谈谈kibana-由安装marvel插件而来
  3. python2.7配置tensorflow1.5.0和keras2.1.6
  4. 嵌入式笔录(6)单管收音机电路分析
  5. 5个杰出的商业机器学习用例
  6. 【干货集锦】如何轻松玩转文档管理工具?我们为你精心准备了一份学习大礼包...
  7. [蓝桥杯][算法提高VIP]分分钟的碎碎念-dfs
  8. 【java】java Integer 缓存 一定是 -128~127 吗
  9. R语言自动化报告格式——knitr
  10. 软件测试设计测试用例案例
  11. js去除空格12种方法
  12. 非参数检验——Wilcoxon 检验 Friedman 检验与 Nemenyi 后续检验
  13. 【我的OpenGL学习进阶之旅】学习OpenGL ES 3.0 的实战 Awsome Demo (上)
  14. 路由器局域网设置_教你如何修改路由器LAN口IP地址的方法
  15. 图片太大加载不出来的解决方法
  16. 用dango框架搭建博客网站
  17. 【亲测有效】win10修改电脑系统字体大小
  18. YJJ's Salesman HDU - 6447(线段树 单点更新+DP思想)
  19. visual assist 工具条不见了
  20. 鸿蒙kal内核,鸿蒙OS发布!官方打脸安卓换壳:华为自研Open鸿蒙内核不兼容安卓...

热门文章

  1. Python中的操作符重载
  2. JAVA追加写文件方法
  3. volatile关键字的用法
  4. mamp 配置php,Mac OSX下使用MAMP安装配置PHP开发环境
  5. mysql5.1修改登陆密码_mysql 5.1版本 修改密码,及远程登录mysql数据库
  6. seleniumphantomJs相关
  7. nodeJs 控制台打印中文显示为Unicode解决方案
  8. IT届常用单词读法纠正
  9. Linux 虚拟机配置-network is unreachable
  10. LOB字段存放在指定表空间 清理CLOB字段及压缩CLOB空间