事务已提交另外会话查询不到的问题解析

导 读

今天遇到一个很有趣的问题:跑python代码程序,使用python程序开启两个session连接数据库,先在第一个session里面对t表查询,然后到第二个session往t表插入一行记录,并commit了;在第一个session去查t表,发现t表中查不到刚插入的这条记录。而我们拿相同的python代码程序,在另一套环境上,也开启2个session,重复上面的操作,结果居然可以查到记录。开发人员认为,我在session 2上数据都插入进去了,并且提交了,为什么sessioin 1查询不到?并且相同的代码,连的同一个mysql环境,怎么两次结果都不一样?

环 境

A环境:MySQL5.7.13 +相同的python代码+ Fedora22操作系统

B环境:MySQL5.7.13 +相同的python代码+ RedHat7操作系统

现象描述

环境A的情况下,下面的实验是模拟python代码程序跑的过程,如需使用python代码测试,详见附录3。

结论:在环境A的情况下模拟,在session 1中无法搜到session2提交的变更。

在环境B的情况下,也去跑这个python脚本,但是跑出来的结果如下:

结论:在环境B的情况下模拟,在session 1中可以搜到session2提交的变更。

问题分析

隔离级别问题

看到这样的情况,我们理所当然的猜测,应该是隔离级别不同导致的,环境A的隔离级别应该是REPEATABLE-READ,可重复读,什么是REPEATABLE-READ?就是当你开启一个事务,读一个数据,而后再次读,再读,再读……只要这个事务没结束,那么读取的数据就是一致的。 所以,环境A下面,session1事务开启,反复查,结果是一致的,这很正常。

而环境B的隔离级别应该是READ-COMMITTED,提交读,什么是提交读?就是只要事务提交了,那你就能读到修改的数据。所以,在环境B的情况下,session1第二次读取的时候,就能读到提交的数据。

好了,现在去数据库看一下,是不是我们猜测的情况。

环境A:

环境B:

事实摆在眼前,结果出乎我们的意料。环境A和环境B都是REPEATABLE-READ,啊啊啊,那到底是为什么呢?

auto commit问题

明明是一模一样的python代码,一样的实验环境,一样mysql版本,一样的执行过程,查询到的结果就是不一致的?

唯一的不同,这2套环境的操作系统不一样,环境A是Fedora22,环境B是redhat7,验证中偶然发现,redhat7的autocommit变量居然还是on的。

默认情况下,python连接MySQL默认是自动开启新事务,也就是说autocommit=OFF的。

好,现在要引入一个MySQL参数,autocommit。

什么是autocommit?

autocommit这个变量表示是否开启自动提交事务模式。如果将这个值设置为1,那么所有变更无需手工提交,每次提交SQL语句,事务就会自动提交,马上生效。如果设置为0,那么你必须使用commit来提交事务或者使用rollback来回滚事务,事务不会自动提交。

问题的原因最终确定:环境B是因为自动提交了事务,session1才在第二次搜索的时候,查到了修改的数据。

详细解释一下环境A和环境B的现象:

环境A:

环境A是Fedora22,autocommit设置为0,表示已经关闭,隔离级别是REPEATABLE-READ。所以在session1中第二次搜索t表的时候无法搜索到新插入的数据,因为两次搜索都在一个事务里面,实现了可重复读。如果要搜到新提交的事务必须键入commit才能搜索到。

环境B:

我们现在来分析情况环境B,环境B是RedHat7,autocommit设置为1,表示事务自动提交开启,隔离级别是REPEATABLE-READ。所以对session1来说第二次去搜索已经相当于已经是第二个事务了,当然就能搜索得到session2提交的数据。

总 结

提 问

通过上述的总结,各位看官可以尝试回答几个关于隔离级别的问题,来验证下对隔离级别和自动事务提交参数的理解。

还是针对这2个session

Q1.在auto_commit=on,隔离级别是REPEATABLE-READ,T3时刻,session1能否看到session2在T2时刻提交的数据?

Q2.在auto_commit=off,隔离级别是REPEATABLE-READ,T3时刻,session1能否看到session2在T2时刻提交的数据?

Q3.在auto_commit=on,隔离级别是READ-COMMITTED,T3时刻,session1能否看到session2在T2时刻提交的数据?

Q4.在auto_commit=off,隔离级别是READ-COMMITTED,T3时刻,session1能否看到session2在T2时刻提交的数据?

回 答

Q1.能。

在auto_commit=on,隔离级别是REPEATABLE-READ,session1能看到session2在T2时刻提交的数据。因为auto_commit=on的时候,每一个语句都是一个全新的事物,所以在T3的时候,session3作为一个新的事务是能查询到,session2在T2时刻提交的数据。

Q2.不能。

在auto_commit=off,隔离级别是REPEATABLE-READ,session1不能看到session2在T2时刻提交的数据。因为auto_commit=off的时候,对session1来说,在T3时刻,因为没有提交,所以事务还是t1时候的那个事务,所以无法查到session2在T2时刻提交的数据。

Q3.能

在auto_commit=on,隔离级别是READ-COMMITTED,session1能看到session2在T2时刻提交的数据。因为auto_commit=1的时候,每一个语句都是一个全新的事物,所以在T3的时候,session1作为一个新的事物是能查询到,session2在T2时刻提交的数据。

Q4.能

在auto_commit=off,隔离级别是READ-COMMITTED,session1能看到session2在T2时刻提交的数据。因为auto_commit=off的时候,虽然在T3的时候,session1还是T1时刻的那个事务,但是,READ-COMMITTED的特性就是可以看到已提交的事务。

附录1:测试环境描述

附录2:表结构

附录3:python代码

原文发布于微信公众号 - 沃趣科技(woqutech)

原文发表时间:2016-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏即时通讯技术

Comet技术详解:基于HTTP长连接的Web端实时通信技术前言 学习交流概述“服务器推”(Comet技术)的应用范围来看看更传统的基于客户端套接口的“服务器推”技术 基于 HTTP 长连接的“服务器

一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、We...

9610
来自专栏鸿的学习笔记

闲话聊聊事务处理(上)

如前面的一些文章写的,数据系统不可能保证是完全的可靠的,我们会遇上各种各样的问题,比如数据库或者应用突然崩溃,网络连接断了,并发读和并发写,诸如此类...

9320
来自专栏友弟技术工作室

Nginx简介--nginx系列之一什么是HTTP服务器?什么是NginxNginx 特点

什么是HTTP服务器? HTTP服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL。与客户端的网络浏览器配合。因为We...

43780
来自专栏上善若水

s001android逆向安全初级篇之apk逆向常用工具及简单使用一览

关于apk 逆向中的一些工具的使用,看了不少文章,也使用过有很长一段时间了,今天对此做一总结:

35630
来自专栏Android开发指南

Android 6.0权限

36170
来自专栏PingCAP的专栏

三篇文章了解 TiDB 技术内幕:谈调度

前两篇文章介绍了 TiKV、TiDB 的基本概念以及一些核心功能的实现原理,这两个组件一个负责 KV 存储,一个负责 SQL 引擎。本篇文章将介绍一下 PD(P...

36100
来自专栏小巫技术博客

Android混淆代码错误堆栈还原

14050
来自专栏腾讯大讲堂的专栏

全民K歌后台编译优化:从40分钟到30秒

编者注 全民K歌上线1年半的从0发展到1.5亿,用户越来越多,后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,如何实现秒编至关重要。...

41550
来自专栏腾讯Bugly的专栏

Android Patch 方案与持续交付

Android 不仅系统版本众多,机型众多,而且各个市场都各有各的政策和审核速度,每次发布一个版本对于开发同学来讲都是一种漫长的煎熬。相比于 iOS 两三天就能...

38150
来自专栏QQ音乐技术团队的专栏

全民K歌后台编译优化:从40分钟到30秒

编者注 :全民K歌上线1年半的从0发展到1.5亿,用户越来越多,后台代码库越来越大,编译速度也与日俱慢,编译一下整个工程需要30-40分钟,如何实现秒编至关重要...

42570

扫码关注云+社区

领取腾讯云代金券