SQL - 事务隔离性问题 与 事务隔离级别 简述
-
概述
- 数据库 隔离性 相关问题
-
背景
- 这个算是每个 it 工作人员, 都应该有点理解吧
- 别人写过, 也不妨碍我理解认识啊...
- 说来惭愧
- 我之前对这些的认识, 其实很凌乱
- 本身就是为了应付面试, 硬背
- 理解上也没有层次
- 甚至把 事务特性, 和 隔离性问题 理解为 同一个层次 的东西
- 但实际上, 隔离性 相关的问题, 是 特性下面 的问题, 更加具体
- 估计没有人比我还笨了吧...
- 我之前对这些的认识, 其实很凌乱
- 这个算是每个 it 工作人员, 都应该有点理解吧
1. 隔离性 的问题
-
概述
- 隔离性的问题
-
背景
- 事务隔离性如果出了问题, 会让事务之间相互影响
- 可能还会导致很多 莫名其貌 的结果
- 最简单的问题
- 并发取钱
- 当然现实中这是不太可能的
- 并发取钱
- 事务隔离性如果出了问题, 会让事务之间相互影响
-
问题们
- 脏读
- 不可重复读
- 幻读
-
解释
- ref 里提到了 可重复读, 我觉得这个不是问题, 所以我没有把它 单独列出来
1. 脏读
-
概述
- 脏读
-
脏读
- 事务中, 读取到 其他事务未提交 的改动
-
场景
-
事务
- 事务A
- 事务B
-
操作
- 针对 数据 D
-
行为
- 事务A 开启, 查询 D 值为 d1
- 事务B 开启, 修改 D 值为 d2
- 事务A 再次 查询 D, 值为 d2
- 事务B 再次 修改 D, 改为 d1
- 事务B 提交
- 事务A 再次 查询D, 值为 d1
-
问题
- 事务A 中间一次查询, 查的 D 的值为 d2
- 这个 d2, 是 事务B 修改所致
- 但是 事务B 实际上, 并没有最终提交
- 事务A 中间一次查询, 查的 D 的值为 d2
-
结果
- 事务A 可以读取到 其他事务 没有提交 的结果
- 这种结果本身很不稳定, 容易出现问题
- 而且这种问题, 甚至不太好复现...
- 事务A 可以读取到 其他事务 没有提交 的结果
-
2. 不可重复读
-
概述
- 不可重复读
-
不可重复读
- 事务中, 读取到 其他事务未提交 的改动
-
场景
-
事务
- 事务A
- 事务B
- 事务C
-
操作
- 针对 数据 D
-
行为
- 事务A 开启, 查询 D 值为 d1
- 事务B 开启, 修改 D 值为 d2, 并提交
- 事务A 再次 查询 D, 值为 d2
- 事务C 开启, 修改 D 改为 d3, 并提交
- 事务A 再次 查询D, 值为 d3
-
问题
- 事务A 的两次查询, 结果都不一样
- 一次是 事务B 的提交
- 一次是 事务C 的提交
- 我个人的理解
- 事务操作的数据, 应该是在这个事务开始运行时候的快照
- 如果其他事务要对相关数据修改, 就应该等着
- 等它改完了, 再按时间顺序排队继续
- 感觉这个比较理想化, 几乎就是 序列化 了...
- 事务A 的两次查询, 结果都不一样
-
结果
- 事务A 可以读取到 其他事务 提交 的修改
- 感觉 好像也没有比 脏读 好到哪里去
- 事务A 可以读取到 其他事务 提交 的修改
-
-
可重复读
- 事务中, 在自己没有修改的前提下, 对同一个值的读取, 每次结果都应该是一样的
3. 幻读
-
概述
- 幻读
-
幻读
- 事务中, 多次读取的结果, 会有一些偏差
- 读到 上次 不存在 的值
- 丢失 上次 存在的值
- 事务中, 多次读取的结果, 会有一些偏差
-
场景
-
事务
- 事务A
- 事务B
-
操作
- 按条件搜索
-
行为
- 事务A 开启, 查询值为 d1
- 事务B 开启, 插入值为 d2, 并提交
- 事务A 再次 查询, 值为 d1, d2
-
问题
- 事务A 的两次查询, 结果都不一样
- 第二次多了个 d2
- 这个 d2, 第一次不存在
- 事务A 的两次查询, 结果都不一样
-
结果
- 事务A 可以读取到 其他事务 提交的 插入/删除
- 感觉 好像也没有比 不可重复度 好到哪里去
- 事务A 可以读取到 其他事务 提交的 插入/删除
-
2. 事务隔离级别
-
概述
- 事务隔离级别
-
背景
- 为了处理以上的问题, 有了事务隔离级别
- 技术上可能也不是一步到位
- 生产中可能会有不同的需求
- 性能方面, 也会有或多或少的牺牲
- 为了处理以上的问题, 有了事务隔离级别
-
隔离级别
- 读未提交 - READ UNCOMMITTED
- 读已提交 - READ COMMITTED
- 可重复读 - REPEATABLE READ
- 序列化 - SERIALIZABLE
-
表格
隔离级别 | 脏读 | 不可重复读 | 幻读
- | - | - | - |
读未提交 | O | O | O |
读已提交 | X | O | O |
可重复读 | X | X | O |
序列化 | X | X | X |
- | - | - | - |
-
其他
- mysql 的默认隔离级别, 是 可重复读
- 实际上 mysql 的 可重复读, 是解决了 幻读 问题的
- 但是这个表这么我先这么画, 主要是为了方便自己记忆
- 具体的机制, ref 的文章里, 讲得很清楚
ps
-
ref
-
一文讲清楚MySQL事务隔离级别和实现原理,开发人员必备知识点
- 讲得很详细
- 表面的现象
- 实验来仔细探究, 而且思路简单科学
- 后面还提到了 b+树 机制, 当然这块我数据结构不太好, 就没看懂...
- 老实说, 挺丢人的...
- 讲得很详细
-
- 另一篇专门讲 幻读 的文章
- 感觉条理清晰
- 但是我目前功力有限, 好些东西, 还理解不了
- 另一篇专门讲 幻读 的文章
-
-
后续
- mvcc
- b+树
- 这个是 单点事务 的问题, 后续还有 分布式事务, 当然这个我只有等以后再查了
尽量尝试解释清楚; 自己校对能力有限, 如果有错误欢迎指出