隔离性与脏读、幻读、不可重复读的理解

读取的问题

  1. 脏读:读取到了未提交的数据
  2. 不可重复读:一个事务,两次读取到的数据不同。注意,这里不同是指两次读取到的记录主键一样,但是其中的内容不一样
  3. 幻读:一个事务,两次读取到的数据记录不同。注意,这里的要点是,读取到了之前没读取到的记录,或者之前读取的记录,本次读取没有获取到。

这些问题都是在并发访问下出现的,如何更好理解这几个问题呢?

在一个事务A进行数据库操作时,另外的事务B可能进行一些操作:

  1. B修改、新增了数据,但未提交,此时A去查询数据库
    • 此时如果没有任何隔离操作,那么A有可能读到未提交的数据,出现脏读
  2. A查询数据库 --> B修改数据并且提交 --> A再次查询数据库
    • 假如数据库做了限制,仅提交后的数据才会被读到。但是A仍有可能在B被提交前后两次读取中,获取到了被B修改后的不同的数据,出现不可重复读
  3. A查询数据库 --> B新增数据并且提交 --> A再次查询数据库
    • 假定数据库在2的基础上进一步做限制,对第一次查询的数据记录加了锁或创建快照。但A前后两次查询语句条件,仍有可能包含B新增的记录,于是出现了幻读

事务的隔离性

对应上面的问题,于是对应的有几种隔离。

READ UNCOMMITTED:未作任何隔离,此时之前的1、2、3都可能发生
READ COMMITTED(RC):顾名思义,只读提交后的数据,那么可以解决问题(1)脏读
REPEATABLE READ(RR):解决(2)不可重复读的问题的隔离机制
SERIALIZABLE: 解决幻读的隔离级别

与MySQL的关系

MySQL默认采用RR级别,但是MySQL的RR级别,也可解决幻读问题。

这种控制多事务并发隔离的做法,有个名字叫MVCC(多版本并发管理)。

MySQL的实现方式:通过在每条记录后面增加两个事务版本号,版本号是每个事务开始时唯一生成的。两个版本号一个存储创建版本,一个存储删除版本。

查询时,事务只查询

  • 规则1:创建版本在本事务之前 - 从而去除被其他事务新加入的记录
  • 规则2:且删除版本号大于本事务(或不存在)的记录 - 从而保证被其他事务删除的记录仍然能读到

那么修改呢?修改时,MySQL会生成一条新记录,并更新原记录删除版本号。这样

  • 对于本事务来说,因为有规则2,所以查询不到原记录
  • 对于其他事务(在次事务开始前的事务),因为有规则1,新插入的记录版本会高于其他事务版本,其他事务也就读不到了。
posted @ 2020-06-29 17:30  mosakashaka  阅读(216)  评论(0编辑  收藏  举报