事务引发的"血案"见的多了也麻木了,这回遇到个事务隔离级别的"案子",坑了我小半天的时间...也怪自己细节不牢..

敲着代码遇到这么一个怪事情:

class XXXService{
@Transactional
public void demo(){
//一堆业务逻辑
rpc.insertOne(); //dubbo调用远程服务插入一条数据
getOne(); //获取刚才插入的数据 } }

其中getOne()的事务的传播属性是required, 因为dubbo是远程调用,所以实际上返回后插入的数据就已经commit了, 一个事务中commit的数据另一个事务中应该可以读取到...本来是这样的,但是呢getOne()方法中却读取不到新插入的数据..

倘使如果不是用dubbo远程调用插入数据的话, 我可能还不会误入歧途, 因为数据库是本地自己搭建的, 平时也没人改默认配置, 按照以往经验Mysql默认配置的情况上面的例子应该是可以读取到的. 所以我把关注点放到这个rpc调用上去了..浪费了很多时间..反正是折腾了很久, 各种推导测试事务传播,想来想去也应该没问题.后来干脆把事务去掉了,发现正常了,传播属性各种测试基本确定没有任何问题了,那么问题可以确定是在事务隔离性上..饶了一大圈这才刚刚走上正道....

SELECT @@session.tx_isolation;

通过命令查询了一下mysql数据库的隔离配置,发现是 Repeatable Read, 咦, 这个和记忆中的默认配置貌似对不上(这里实际上是我记混了,mysql默认配置的确是这个,Oracle才是Read committed)..赶紧查询一下线上的数据库配置果然不对应该是Read Committed

这下问题明了,由于代码中没有写明隔离级别,所以使用的是mysql配置的隔离级别,而mysql的隔离级别是可重复读,故产生了此次问题.

此次问题做一个小结:

产生原因:

查询数据库的时候会建立一个到数据库的连接, 熟称数据库session, 有事务的情况下, 这一次连接就处于一个事务中, rpc调用远程服务,由于不是本地方法,故无法加入本地事务中,所以可以算作是另一个事务,那么rpc所处的事务插入数据后事务就结束并提交了. 而getOne()方法所处的事务实际上并没有完成,还受到事务配置的约束,又由于没有配置事务的隔离属性,故采用的mysql的隔离配置Repeatable Read, 而这个可重复读的意思就是一个数据可以反复读取, 并且读取到的值不会发生变化, 这实际上就是说当建立此次事务的时候就不会再读取到新的值了.那么在事务中途rpc插入的数据也不在getOne()所处事务可以读取的范围内, 故读取不到. 但是如果隔离的属性是Read Committed的话,则可以读取到已经提交的数据, rpc服务虽然是中途插入的数据,但是由于新插入的数据已经提交了事务,故依然可以被getOne()方法读取到.

 解决方法:

set global transaction isolation level read committed;

最简单的方法是直接变更mysql的隔离配置为read committed,这样就一切归位了.如果无法变更数据库隔离级别也依然有办法,由于隔离配置的生效级别是首先按照程序中配置的级别,其次再看数据库配置的,那么在程序中变更隔离级别也可以.

class XXXService{
@Transactional(isolation = Isolation.READ_COMMITTED)
public void demo(){
//一堆业务逻辑
rpc.insertOne(); //dubbo调用远程服务插入一条数据
getOne(); //获取刚才插入的数据 } }

问题到此就结束了,但是这里有一个问题比较好奇,Reaptable Read是如何实现的呢,感觉像是开启事务后就对数据库进行了一个快照一样,但是想想又不可能真这样做,然后百度到了一个介绍mysql mvcc机制的文章.

简单来说就是实际上在每行数据最后有2列隐藏列,一列代表数据的创建版本,一列代表数据的删除版本,列中的值存放的是版本号,而这个版本号就是递增的且和某个事务唯一对应,这样只要查询创建版本小于当前版本,删除版本大于当前版本就可以了,换成白话就是查询在当前版本之前创建,当前版本之后删除的数据,这样就可以保证对于当前版本能查询到的数据的稳定不可变,而对于修改数据的操作,则是拆分为标记原来的数据为删除,并插入一条修改后的数据,这样就完美巧妙的保证修改数据读取的稳定性.

事务隔离级别引发的"血案"的更多相关文章

  1. 30分钟全面解析-SQL事务+隔离级别+阻塞+死锁

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  2. 事务隔离级别与传播机制,spring+mybatis+atomikos实现分布式事务管理

    1.事务的定义:事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功.其必须遵循四个原则(ACID). 原子性(Atomicity):即事务是不可分割的最小工作单 ...

  3. Spring事务隔离级别与传播机制详解,spring+mybatis+atomikos实现分布式事务管理

    原创说明:本文为本人原创作品,绝非他处转载,转账请注明出处 1.事务的定义:事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功.其必须遵循四个原则(ACID). ...

  4. Sqlserver事务隔离级别详解

    sqlserver存储方式   页    sqlserver是以页的形式存储数据,每个数据页的大小为8KB,sqlserver会把空间分为多个页,sqlserver与数据交互单位最小的io操作就是页级 ...

  5. 事务,Oracle,MySQL及Spring事务隔离级别

    一.什么是事务: 事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. 二.事务特性(4种): 原子性 (atomicity):强调事务的不可分割:一致性 (consiste ...

  6. SQL Server 事务隔离级别

    一.事务隔离级别控制着事务的如下表现: 读取数据时是否占用锁以及所请求的锁类型. 占用读取锁的时间. 引用其他事务修改的行的读操作是否: 在该行上的排他锁被释放之前阻塞其他事务. 检索在启动语句或事务 ...

  7. SQL Server中锁与事务隔离级别

    SQL Server中的锁分为两类: 共享锁 排它锁 锁的兼容性:事务间锁的相互影响称为锁的兼容性. 锁模式 是否可以持有排它锁 是否可以持有共享锁 已持有排它锁 否 否 已持有共享锁 否 是 SQL ...

  8. 从事务隔离级别谈到Hibernate乐观锁,悲观锁

    数据库的事务,是指作为单个逻辑工作单元执行的一系列操作. 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源.通过将一组相关操作组合为一个要么全部成功要么全部失败的单 ...

  9. 事务以及MySQL事务隔离级别+MySQL引擎的区别

    1.事务的基本要素:ACID 1.原子性(Atomicity): 事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

随机推荐

  1. 远程连接MongoDB报“Network is unreachable”错误的解决方法

    解决办法:/etc/mongod.conf 里把127.0.0.1 改成 0.0.0.0

  2. C#6.0 语法

    属性表达式 属性值初始化 public string name {get;set;} = "张三"; 函数表达式 NULL检查运算符 var aa = Created?.Date; ...

  3. 用友软件系统管理员账号admin密码忘记了,如何解决?

    1.打开数据库. 2.点开  数据库-UFSystem. 3.找到dbo.UA_user表,鼠标右键,点打开表. 4.打开后,找到admin,cPassword列即可找到系统管理员密码.

  4. pythonl输出的预警消息中的json串的中文展示乱码(中文的unicode码)

    来源:ctrip接口名称:ReviewStandartAPI错误信息:[{'ReviewTime': u'\u63a5\u53e3\u8fd4\u56de\u7684\u70b9\u8bc4\u65f ...

  5. [Solution] The superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path

    HttpServlet需要tomcat等. 右键project点开properties>project facets> 在右侧栏的Runtime tab中勾选tomcat或者新建tomca ...

  6. 管家基因 | Human housekeeping genes

    管家基因就是在细胞里稳定表达的基因,及时在胁迫状态下,表达的差异也不大. 以前做实验的时候就经常听说管家基因,因为在做RT-PCR的时候需要同时检测管家基因,这样可以用于矫正我们不同批次的结果. Li ...

  7. Introduction to dnorm, pnorm, qnorm, and rnorm for new biostatisticians

    原文:Introduction todnorm,pnorm,qnorm, andrnormfor new biostatisticians Today I was in Dan’s office ho ...

  8. English trip V1 - 23. Big and Bigger Teacher:Corrine Key: adjective comparisons 形容词 比较级

    In this lesson you will learn to make comparisons. 课上内容(Lesson) compare   n. 比较  vt. 比拟,喻为:[语]构成  vi ...

  9. You Don't Know JS: Scope & Closures (第3章: 函数 vs 块作用域)

    第二章,作用域由一系列的bubbles组成.每一个都代表了一个container或bucket,装着被声明的identifiers(variables, functions).这些bubbles相互嵌 ...

  10. 以CapsNet为例谈深度学习源码阅读

    本文的参考的github工程链接:https://github.com/laubonghaudoi/CapsNet_guide_PyTorch 之前是看过一些深度学习的代码,但是没有养成良好的阅读规范 ...