聊聊mysql的事务
今天来聊聊事务的四大特性以及其实现原理,需结合之前写的mysql是如何实现mvcc的来理解,因为大多数的实现都是基于mvcc的,理论介绍完后会通过实例来演示mvcc又是如何实现这些隔离级别的
事务的四大特性
- 原子性
事务的执行要么全部成功要么全部失败,成功的时候直接提交就好,某些环节失败的时候是需要回滚的,这就要用到回滚日志(undolog)根据当前记录的回滚指针去undolog定位历史记录了; - 一致性
事务的其他特性就是为了保证一致性的 - 隔离性
两个事务之间的执行应该是隔离开的,各自造成的数据改变不会相互影响,有四个隔离级别下面会一一解释 - 持久性
事务提交后持久化到硬盘,通过redo log实现
隔离级别
说明:下面的概念解释假设有两个事务A、B处于活跃状态
- 读未提交(READ-UNCOMMITTED)
事务B读到了事务A新增但未提交的数据;这种事务未提交就被其他事务读取到的现象叫做脏读;而在实际生产中这是毫无意义的,所以几乎不会被用到 - 读已提交(READ-UNCOMMITTED)
是oracle的默认隔离级别;事务B读到了事务A修改了并且已经提交了的数据;分两种情况,一是事务A修改了数据导致B在第二次读的时候与第一次读到的结果不一样,这种现象叫做不可重复读;二是事务A新增了数据导致B在第二次查询时候与第一次查询时读到的记录数不一致,这种现状叫做幻读;即RC级别下可能会出现幻读和不可重复读的现象 - 可重复读(REPEATABLE-READ)
是mysql的默认隔离级别;事务A对数据的操作不影响事务B,即事务B在事务A修改数据前后查的数据是一致的;这种级别看似不会出现问题,但是当当前读和快照读混用的时候也是会出现幻读或者不可重复读的问题的,下面我会演示这一现象;而mysql是通过mvcc+间隙锁来解决这一问题的 - 串行(SERIALIZABLE)
事务串行执行,效率低但不会出现脏读、幻读、不可重复读的现象
小总结:综上所述,幻读可以理解成相同条件下事务前后读取到的记录数不一样,而不可重复读可理解成事务前后读取都的内容不一样,记录数可以一样;
不同隔离级别下的实操
数据准备
- 创建一个测试表test
CREATE TABLE test (
id int NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
age int DEFAULT NULL,
PRIMARY KEY (id)
)
- 插入原始测试数据
insert into test values(10,'zhangsan',19);
insert into test values(20,'lisi',21);
insert into test values(30,'wangwu',21);
可重复读(RR)隔离级别下测试
1.打开两个命令行窗口并关闭事务的自动提交;然后分别在两个窗口手动开启事务;如图:
2.在A事务窗口执行查询操作:select * from test where age = 21;结果和预期一致符合条件的是两条数据,如图:
3.在B事务窗口执行插入操作insert into test values(40,'zhaoliu',21);后提交事务并进行查询select * from test where age = 21;此时查询到的是三条记录,如图:
4.在事务A窗口重新执行select * from test where age = 21;发现得到的结果与第一次一致还是两条
分析:
综上可以发现,事务A在事务周期内在事务B对表做了新增数据的情况下两次查询结果仍然一致,没有出现幻读、不可重复读的情况,是因为mysql的默认隔离级别是RR(可重复读),而正常情况下RR是可以避免幻读和不可重复读的情况的,除非在事务周期内混用了当前读和快照读,下面来演示RR级别下出现幻读的情况;
- 5.在上面的基础上我们在事务A的查询语句基础上新增一个for update语句:select * from test where age = 21 for update;此时我们就会发现记录数变成了3条(如图),即出现了幻读的情况,因为类似for update、delete等语句是会使用当前读的,而之前的查询语句用的是快照读,这就出现了快照读和当前读混用的现象从而出现了幻读
读已提交(RC)隔离界别下的测试
步骤与上面几乎一致,只是需要在开启事务之前将隔离级别设置成读已提交(RC),如图:
接下来重复上面的步骤:
- 1.关闭事务的自动提交;手动开启两个事务,这里就不上图了
- 2.事务A执行select * from test where age = 21;得到的结果是三条(上面的测试新增了一条数据),如图:
- 3.事务B执行insert into test values(50,'qianqi',21);后提交事务并进行查询select * from test where age = 21;此时查询到的是四条记录,如图:
- 4.在事务A窗口重新执行select * from test where age = 21;此时我们发现得到结果却是4条记录与第一次查询的结果不一致,这就出现了幻读的现象,如图:
思考:为什么在测试步骤和数据不变的情况下不同的隔离级别下查询的结果不一致呢?
这是因为两种隔离级别下生成readView的时机不一样,mysql默认的可重复读级别下是在事务中的第一次查询时生成的readview,后续在没有当前读的情况下事务内所有的查询都是基于第一次查询生成的readview的快照读;而读已提交的隔离级别下在事务内的每次查询都会生成一个readview,所以造成了两种不同的现象;
聊聊mysql的事务的更多相关文章
- 数据库事务系列-MySQL跨行事务模型
说来和MySQL倒是有缘,毕业的第一份工作就被分配到了RDS团队,主要负责把MySQL弄到云上做成数据库服务.虽说整天和MySQL打交道,但说实话那段时间并没有很深入的理解MySQL内核,做的事情基本 ...
- 聊聊MySQL的加锁规则《死磕MySQL系列 十五》
大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...
- MySQL 数据库事务与复制
好久没有写技术文章了,因为一直在思考 「后端分布式」这个系列到底怎么写才合适. 最近基本想清楚了,「后端分布式」包括「分布式存储」和 「分布式计算」两大类. 结合实际工作中碰到的问题,以寻找答案的方式 ...
- Mysql分布式事务
关于Mysql分布式事务介绍,可参考:http://blog.csdn.net/luckyjiuyi/article/details/46955337 分为两个阶段:准备和执行阶段.有两个角色:事务的 ...
- mysql的事务和select...for update
一.mysql的事务mysql的事务有两种方式:1.SET AUTOCOMMIT=0;也就是关闭了自动提交,那么任何commit或rollback语句都可以触发事务提交;如果SET AUTOCOMMI ...
- MySQL的事务
MySQL的事务 1.事务:事务是由一步或者几步数据库操作序列组成的逻辑执行单元,这一系列操作要么全部执行,要么全部放弃执行. 2.事务具备的四个特性(简称为ACID性): (1)原子性(Atomic ...
- mysql 分布式事务
php + mysql 分布式事务 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元: 事务应该具有4个属性:原子性.一致性.隔离性.持续性 原子性(atomicit ...
- MySQL之事务隔离级别--转载
转自:http://793404905.blog.51cto.com/6179428/1615550 本文通过实例展示MySQL事务的四种隔离级别. 1 概念阐述 1)Read Uncommitted ...
- MySQL数据库事务剖析
MySQL数据库事务剖析 事务就是一组原子性的SQL查询,是一个独立的执行单元.事务内的语句,要么全部执行成功,要么全部执行失败. 1.事务的标准特征 一个运行良好的事务处理系统,必须具备原子性.一致 ...
随机推荐
- LGV 引理——二维DAG上 n 点对不相交路径方案数
文章目录 引入 简介 定义 引理 证明 例题 释疑 扩展 引入 有这样一个问题: 甲和乙在一张网格图上,初始位置 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_ ...
- C#基础_XML文件读写
使用C#对XML文件进行操作,包括生成一个XML文档,以及读取XML文档中的内容,修改某个元素中的内容 using System; using System.Collections.Generic; ...
- Springboot重定向,没有位置没有加“/user”,但是url在请求位置的前面“/user”就出现了
是因为":"后面没有加"/" 原先的 return "redirect:main.html"; 正确的 return "redir ...
- Linux常用基础命令一
一.目录操作 进入路径 cd [目录地址] 切换回主目录 cd 返回上一个路径 cd - 打印当前路径 pwd 列出目录下文件 ls ---查看只包含非隐藏文件 ls -a -----查看目录下所有文 ...
- C/C++ Capstone 引擎源码编译
Capstone 是一个轻量级的多平台.多架构的反汇编框架.Capstone 旨在成为安全社区中二进制分析和反汇编的终极反汇编引擎.Capstone的编译非常简单只需要一步即可轻松得到对应的Lib库文 ...
- 快速排序C语言版图文详解
算法原理:选一个数位基准,将序列分成两个部分,一边全是比它小序列,另一边全是比它大序列.然后再分别对比他小的序列和比再次进行基准分割.依次分割下去,得到一个有序的队列. 原理图示: 编辑 编辑 ...
- MySQL到底有没有解决幻读问题?这篇文章彻底给你解答
MySQL InnoDB引擎在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题? 网上众说纷纭,有的说解决了,有的说没解决,甚至有些大v的意见都无法达成统一. 今天就深入 ...
- KubePi主界面添加镜像仓库并授权给集群,供创建Deployment时选择镜像使用
1.添加kubeoperator自带的nexus仓库 2.添加harbor 3.把添加的镜像仓库授权给集群 4.关于镜像仓库secrets的有关说明 5.实际效果 6.从添加授权的镜像仓库创建工作负载 ...
- linux中通过date命令获取昨天或明天时间的方法
date命令可以获取当前的时间,通过man,可以看到date有很多参数可以用,很容易做到格式化 # 获取当前日期 date +"%F" 或者 date +"%Y-%m-% ...
- 使用SpringCloud实现的微服务软件开发部署到Linux上占用内存过大问题解决办法
问题描述 最近上线的一个使用JAVA的Spring Cloud开发的ERP软件,部署上线时发现很严重的内存资源占用过高问题,而实际上开发测试并没有很大的访问量,甚至却出现了服务器无法正常访问的现象. ...