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

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

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. HTTP是什么连接

    ① 在HTTP/1.0中,默认使用的是短连接. 但从 HTTP/1.1起,默认使用长连接,用以保持连接特性. ②http长连接并不是一直保持连接 http的长连接也不会是永久保持连接,它有一个保持时间 ...

  2. prometheus的agent 二次开发代码参考

    import com.codahale.metrics.MetricRegistry;import io.prometheus.client.CollectorRegistry;import io.p ...

  3. Android Studio waiting for debugger 卡死

    当你使用AS进行调试时,发现卡在进入调试模式的 waiting for debugger 不动了,出现这种问题是adb端口被抢占了.解决方法就是: 在命令行: netstat -ano|findstr ...

  4. git的安装以及生成ssh key

    安装git 在ubuntu系统下输入以下命令安装git软件: sudo apt-get install git 输入以下命令查看git是否安装成功: git --version 如下图所示则表示安装成 ...

  5. Python 闭包(Closure)

    Python  闭包 (Closure) 这里介绍一下python 的闭包 基本概念 闭包(closure)是函数式编程的重要的语法结构. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函 ...

  6. Webpack 常见静态资源处理 - 模块加载器(Loaders)+ExtractTextPlugin插件

    Webpack 常见静态资源处理 - 模块加载器(Loaders)+ExtractTextPlugin插件 webpack系列目录 webpack 系列 一:模块系统的演进 webpack 系列 二: ...

  7. Axure XMind整理交互思路

    本部分主要是为了研究Xmind思维导图总结设计原型的思路

  8. 分享:selenium(一) xpath

    xpath无所不能定位.   https://www.w3.org/TR/xpath/all/#axes 两个神器:firebug.xpath-checker 举例:混合定位 //td[a//fron ...

  9. learn the python the hard way习题11~17总结

    关于 input() 格式: input("prompt")功能:从 CLI 获取 User 的一个输入,显示 promt 的内容,并且返回一个 string 类型的数值其他:如果 ...

  10. 用C#实现多种方式播放Wav声音

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...