数据库事务一致性与锁
2019-10-18 本文已影响0人
光谷电锯狂魔
对大多数SQL DB
事务:
由一系列数据库操作组成的一个不可拆分的逻辑过程
事务的特性(ACID):
- 原子性(Atomicity):事务中所有操作必须全部完成。否则回滚为初始状态
例如:删除某个商品(需要删除商品,评价,订单等多个表) - 隔离性(Isolation):事务之间不会互相影响导致数据错误,分为四个级别(见下)
- 持久性(Durability):事务完成后数据不会因为系统故障而丢失
↓ - 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。由上面三者共同保证。
不一致的情况:
- 脏读(Dirty Read):
一个事务读取到另一个事务还未提交(可能回滚)的数据
时间 | 事务A | 事务B |
---|---|---|
T1 | 开启事务 | 开启事务 |
T2 | 查询金额为100 | |
T3 | 金额加10 | |
T4 | 查询金额为110(脏读) | |
T5 | 金额加10 | 回滚,金额还原为100 |
T6 | commit | |
T6 | 金额变为120 |
- 不可重复读(Non-repeatable read):
同一个事务内,两个相同的查询返回了不同的结果
时间 | 事务A | 事务B |
---|---|---|
T1 | 开启事务 | 开启事务 |
T2 | 查询金额为100 | 查询金额为100 |
T3 | 金额加10 | |
T4 | commit | |
T5 | 查询金额为110(不可重复读) |
- 幻读(Phantom read):
特殊的不可重复读,在事务2进行插入或删除时发生
时间 | 事务A | 事务B |
---|---|---|
T1 | 开启事务 | 开启事务 |
T2 | 查询学生分数 | |
T3 | 新增一个学生的分数 | |
T4 | commit | |
T5 | 将所有学生百分制分数改为ABCDE等级 | |
T6 | commit | |
T6 | 发现还存在一个百分制的分数(幻读) |
-
修改丢失:
一个事务的提交被另一个事务提交覆盖
时间 | 事务A | 事务B |
---|---|---|
T1 | 开启事务 | 开启事务 |
T2 | 查询金额为100 | 查询金额为100 |
T3 | 金额加10 | |
T4 | commit,金额变为110 | |
T5 | 金额加20 | |
T6 | commit,金额变为120 | (修改丢失) |
隔离级别:
- 读未提交(Read uncommttied)
- 读数据无锁,写数据瞬间时加行锁 -> 避免同时写入
- 读已提交(Read committed)
- 读数据时瞬间加行级共享锁,操作完成即释放
- 写数据时加行级排它锁,直到事务结束
- 解决的问题?
- 可重复读(Repeatable read)
- 读数据的时候加行锁,直到事务结束
- 解决的问题?
- 可串行化(Serializable)
- 读数据的时候加表锁,直到事务结束
- 解决的问题?
锁类型
- 行锁
- 表锁
- 共享锁(读锁):本事务可读,不可写;其它事务可读,不可写
- 排它锁(写锁):本事务可读写;其它事务不可读写
对MongoDB
MongoDB的ACID特性
- 只能保证单文档ACID,不支持跨文档事务(4.0已支持)
- 在更新单文档时会对其加锁:Intent Lock
锁类型
-
意图锁(Intent Lock)
&非意图锁(Non intent lock)
操作方对要操作的文档加Non Intent Lock,并对所有外层加intent lock。
image.png
- Multiple granularity locking
混合了多种锁,包括- 共享锁-S(Shared lock)
- 排它锁-X(Exclusive lock)
- 意图共享锁-IS(Intent Share lock)
-
意图排它锁-IX(Intent Exclusive lock)
image.png
MongoDB的事务、ACID和一致性
五个解决方案让MongoDB拥有RDBMS的鲁棒性事务
问题:怎么使用Reactive Mongo Transaction?