高性能mysql 事务笔记
事务的四大特性原子性、一致性、隔离性、持久性,
事务隔离的四大隔离级别:
READ UNCOMMITTED(未提交读),
在 read uncommitted级别,事务中的修改,及时没有提交,对其他事务也都是可见的。事物可以读取未提交的数据,这也被称为脏读,你想如果所有的未提交的数据事物它读取了,性能上是不是会差,所以在实际应用场景中很少应用
READ COMMITTED(提交读),
提交读是大部分数据库的默认隔离级别,mysql却不是,因为它所执行的是 一个数据至未提交事务之前 事务是看不到它的,所有事务都是不相干的没有关联,所有的修改对其他事务是不可见的,这个级别也被称为不可重复读,因为两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读),
可重读读是mysql的默认事务隔离级别,可重读读不会产生脏读的情况,它保证了,在一个事务中多次读取同样记录的结果是一致的,可重复读在innodb和xtradb 储存引擎中通过多版本并发控制解决看了幻读的问题
SERIALIZABLE(可串行化)
可串行化是最高的隔离级别,它通过强制事务串执行,避免了幻读的问题,简单来说,可串行化会在读取的每一行数据上都加上锁,所以可能导致大量的超时和锁争用的问题,实际应用场景中很少用到,只有在非常需要确保数据一致性而且可以接受没有并发的情况下,才考虑该级别隔离
mysql可重复读和幻读实例
mysql的默认事务级别是:可重复读
其中可重复读是通过mvcc来实现的又叫快照读,在事务中的读操作通过对当前的数据库中记录一个版本,以后的读操作只会读取记录的版本,因此相当于对数据库的数据建立了一个快照数据,因此叫做快照读,其不用对数据库中的数据进行加锁又叫做乐观锁。
同时RR事务级别的mysql通当前读和gap锁来解决幻读,其本质是通过对数据库周边记录进行加悲观锁(读锁(共享锁)和互斥锁(写锁))【gap锁】来解决幻读。
RR事务隔离级别号称可以解决幻读的问题(通过当前读加锁来实现)
第一步建表并插入5条记录:
接下来我们看下大部分mysql所说的幻读现象:
事务1(开启事务查询发现没有记录6准备插入):
事务2(开启事务,发现没有记录6插入,并提交事务):
事务1:查询发现没有记录6,现在开始进行插入6:
没有的记录我要插入却告诉已经存在,这就是通常说的幻读。
2.gap锁(当前读)解决幻读问题
mysql说对数据加锁不管共享锁还是互斥锁就能解决幻读的问题
开启一个事务1(加上共享锁解决幻读的情况):
开启事务2(查询发现没有记录8,准备插入)
可以发现事务2被阻塞,不准插入,除非事务1提交。因此在事务1中插入记录8是能够成功的。
事务1插入记录8,最后可以查询出自己插入的数据,但是更新一条不存在的数据是不会查询出来的,最后提交事务:
事务2阻塞的操作会爆重复异常:
因此对一个事务加上悲观锁(共享锁或者互斥锁)是能够保证幻读不会出现的,并且谁先加锁,谁就能够保证check and
insert是成功的。如果你需要每个事务的check and
insert都能成功,那么你不要加共享锁,直接加互斥锁。那么事务会直接阻塞在加锁阶段,就不会出现check and insert 失败的情况。
事务1加上互斥锁
事务2也想加互斥锁,BOOM你只能失败:
3.RR没有解决的幻读
场景:我们知道grap锁能够将右边的记录进行加锁,因此我要统计表记录的数量,我只需要对最大记录加锁就行了
事务1:对最大记录互斥加锁,准备计算表中记录数量。发现数量为8,并且不存在3和4的记录。
事务2:插入缺失记录3和4成功,但是插入id为100的记录被锁住,OK事务2可以提交了。
事务1:在事务1在事务2插入数据后进行查询总量,发现数量还是6,OK很完美
事务1:接下来我发现事务1中没有3和4这条记录,我进行一次无用的更新会发生什么?
OK,最终问题终于出现了,为什么我更新两条不存在的记录,我能够更新成功,并且我再次统计的时候,数量添加了两条?并且我重新读取,发现结果不一样了,不是说可以重复读吗?加锁可以解决幻读吗?
PS:如果一个事务里面插入或者删除会改变记录的数据,这个是合理的不是幻读。更新应该只会修改数据记录,这个也是合理,同样不是幻读,都是可重复读的。但是更新出现新的记录就是一种异常的情况。
- [WCF-Discovery] 实例演示:如何利用服务发现机制实现服务的“动态”调用?
- [WCF-Discovery]服务如何能被”发现”
- 我的数据访问函数库的源代码(一)—— 共用部分
- 《WCF服务编程》关于“队列服务”一个值得商榷的地方
- 我的数据访问函数库的源代码(二)—— SQL语句部分
- 来源于WCF的设计模式:可扩展对象模式[上篇]
- 我的数据访问函数库的源代码(三)——返回结构数组
- 我的数据访问函数库的源代码(四)—— 存储过程部分,包括存储过程的参数的封装
- [WCF 4.0新特性] 路由服务[实例篇]
- [WCF 4.0新特性] 默认终结点
- 三层架构之我见 —— 不同于您见过的三层架构。
- 来源于WCF的设计模式:可扩展对象模式[下篇]
- [WCF 4.0新特性] 标准终结点与无(.SVC)文件服务激活
- 我的数据访问类(第二版)—— for .net2.0 (二)
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- RPC 和 REST还有RESTFul到底是个什么玩意?
- 线程和线程池的几个状态值
- 阿里代码规约为什么不让使用Executors包装好线程池呢?
- Groovy、热部署和热加载(自定义类加载器)及spring loaded 部分源码分析
- Centos在线迁移到腾讯云cvm
- ClickHouse源码导读:网络IO
- 手把手教你:将ClickHouse集群迁至云上
- 直播中台iLiveSDK终端框架演变之路
- ClickHouse 数据导入实战:Kafka 篇
- pipeAsyncFunctions
- 【python-leetcode287-循环排序】寻找重复的数
- 聊聊claudb的list command
- 【python-leetcode448-循环排序】找到所有数组中消失的数字
- input/change/composition/keydown事件详解
- isSameDate