Skip to content

Latest commit

 

History

History
38 lines (29 loc) · 4.56 KB

ddia_7.md

File metadata and controls

38 lines (29 loc) · 4.56 KB

事务

ACID

事务所提供的安全保证,即ACID, 分别为原子性(atomicity), 一致性(Consistency), 隔离性(Isolation)与持久性(Durability).

  • 原子性, 在出错时终止事务,并将部分完成的写入全部丢弃

  • 一致性, 数据库中的一致性与CAP理论中的一致性以及用于动态分区的一致性哈希完全不同,他指对数据状态有特定的预期状态,任何数据修改必须满足这些状态约束。 这实际上要求应用层来维护这个状态一致,如转账过程中,A转账给B,那么A的账户余额与B的账户粤之和应该保持一致。

  • 隔离性, 并发执行的多个事务之间相互隔离,当事务提交时,其结果与串行执行完全相同

  • 持久性,一旦事务提交成功,即使存在硬件故障或数据库崩溃,事务所写入的任何数据也不会消失

隔离级别

  • 违反事务隔离的几种类型

    • 脏读, 读到了其他事务尚未提交的数据
    • 脏写,覆盖了其他事务尚未提交的数据
    • 不可重复读,用户观察数据库处于不一致的状态,即违反了一致性

    假设有A、B两个事务,B事务为用户从账号a转账(余额为500元)给账号b(余额为500元) 100元,A事务为用户在B事务发起的时间点之前查询两个账户的余额。两个事务分别在时间点1,2,3,4执行了以下4条语句:1、A事务查询账号b的余额,发现余额为500元;2、B事务修改账号b的余额为600元;3、B事务修改账号a的余额为400元;4、A事务查询账号a的余额,发现余额为400元。 也就是说在转账事物B执行的过程中,查询事物A发现用户的两个账号的总财产少了100元, 然而对事物A的4操作而言,事务B确实已经提交了2、3操作,因此读已提交场景下, 会读到a修改后的余额

    • 更新丢失, 多个事务同时更改同一条数据, 即并发写事务冲突。
    • 幻读, 一个事务的写入改变了另一个事务的查询结果,和不可重复读的区别在于: 两个事务修改、读取的不是同一个对象,而仅仅是具有相关联性。
    • 写倾斜, 事务根据查询的结果决定写入的数据

    假设a、b两个医生值班,医院规定至少有一名医生在值班的情况下允许请假。现在a、b同时提出了请假申请,发起了事务A、B。 执行顺序为: 1、事务A查询值班医生人数为2;2、事务B查询到值班医生人数为2;3、事务A判断值班人数大于1, 修改值班医生a的状态为离开;4、事务B判断值班人数大于1,修改值班医生b的状态为离开。 因此两个医生的请假都会被批准。类似的例子还有抢票场景,剩余票数大于0时,才允许购票。

  • 事务的几种隔离级别

    • 读已提交,读请求只能看到已经提交的数据,写请求只能覆盖已经提交的数据。 防止脏读、脏写
    • 快照隔离,防止脏读脏写与不可重复读,不可防止幻读。实现机制: MVCC(多版本并发控制),为每份数据保留多个事务的版本, 每次事务开始时,列出所有当前正在进行中的其他事务,然后查询数据的时候,忽略掉正在进行的事务版本。写操作相互阻塞。。
    • 可串行化,防止幻读。 可串行化的实现:
      • 严格按照串行顺序执行, 即单线程执行。
      • 两阶段加锁。 如果事务A已经读取了某个对象,那么事物B想要写入该对象的话,必须等到A提交或者终止之后,确保B不会在A的提交过程中去修改对象; 如果事务B已经修改了某个对象,那么事务A必须等到B提交或终止后才能继续。
      • 为了防止幻读, 还需要引入范围更大的锁来防止所有的可能影响当前事务查询的修改,也就是谓词锁(对符合某种条件的数据加锁,插入数据时必须检查所有的谓词锁是否存在冲突)与区间锁(对某个key区间的所有数据加锁)。
    • 可串行化的快照隔离:

      串行执行是悲观的并发控制,如果某些操作可能会出错,那么直接放弃,采用等待的方式直到绝对安全。而可串行化的快照隔离,则是一种乐观的并发控制,当事务可能会发生冲突时他会继续执行,直到事务提交的时候,才检查是否确实发生了冲突, 如果是的话,终止事务并停下来。 检测事务冲突:1、检查读取是否作用于一个即将过期的MVCC对象;2、检查写入是否覆盖了一个即将完成的读取

  • 分布式事务

Percolator