数据库事务一致性与锁

对大多数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?

乐观锁 vs 悲观锁

你可能感兴趣的:(数据库事务一致性与锁)