duckflew
duckflew
Published on 2022-03-22 / 121 Visits
0
0

数据库的事务隔离级别

事务是数据库中的一个核心概念,指的是对数据库的一组操作作为一个整体,要么都执行要么都不执行

事务有四大特性:

  1. 原子性:每个事务都是一个整体,不可再拆分,事务中的sql语句要么都执行成功,要么都执行失败。

  2. 一致性:事务执行前后数据库的状态保持一致。比如不管如何转账,转账前后的总钱数是不变的。

  3. 隔离性:事务和事务之间不应该相互影响,保持隔离。

  4. 持久性:事务一旦提交对数据库的修改就是永久的,即使电脑发生故障也不会影响该修改,因为他的结果是记录在存储设备上的。

事务中有一个重要的特性“事务的隔离性”指的是事务和事务之间不应该相互影响,保持隔离,然而在现实中多个事务可能会操作同一个数据,造成并发问题:

  • 脏读:一个事务读取到了另一个事务尚未提交的数据。
  • 不可重复读:事务一读取到了age的值20,事务二将该值修改成了28,事务一再次读取age的值28,事务一两次读取的age值不一致。
  • 幻读:事务一读取到A表中有一条记录,事务二往A表中插入一条记录,事务一再次读取的时候记录变成了两条,就像发生幻觉一样。

脏读比较好理解,就是读取到了别的事务尚未提交的数据.然而幻读和不可重复读些许类似,他们都是读取到了别的事务已经提交了的数据。

区分方法, 不可重复读主要是读取到了别的事务本事务读取的数据的修改。幻读则是读取到了另外一个事务删除或者新增的记录。

对应到并发的锁的方面来体现的话,也就是:

  • 解决不可重复读只需要加行级锁就可以解决
  • 解决幻读需要加表级锁

正是因为有这些问题存在,数据库设置了隔离级别来处理:

  1. 读未提交(read uncommitted): 事务中的修改,即使没有提交,其他事务也可以看得到

    在这种隔离级别下有可能发生胀读,不可重复读和幻读。

  2. 读已提交(read committed): 事务中的修改只有提交以后才能被其它事务看到。在这种隔离级别下有可能发生不可重复读和幻读。

  3. 可重复读 (repeatable read):该级别保证了在事务中看到的每行的记录的结果是一致的,但是这种级别下有可能发生幻读。

  4. 串行化(serializable):该级别下所有的事务都是串行执行的,一个事务执行完了才能执行其它的事务,可以解决所有的并发问题,它是靠大量加锁实现的,所以效率很低下。只有在需要绝对保证数据一致性,并且并发量不大的情况下,可以考虑。

这些事务隔离的级别从上到下越来越高,当然了并发的性能也是越来越低的。

MVCC

是什么

MVCC是一种用来解决数据库读写并发冲突的无锁控制方式,全程为多版本并发控制(Multiversion concurrency control (MCC or MVCC))

原理

通过为事务分配单独的时间戳,每个修改保存一个版本,版本与事务时间相关联,读操作只读取改事务开始前的快照,所以MVCC可以为数据库解决如下问题:

  1. 并发读写数据库时可以做到读操作时不用获取锁来阻塞写的操作,写的操作同样也不用来阻塞读的操作,提高了数据库的并发性能
  2. 解决脏读、幻读、不可重复读等事务隔离的问题,但是不能解决更新的丢失问题

**tips:**关于更新的丢失问题,其实就是指的多个线程同时操作数据库并且执行了写入操作,可能会导致某个线程的修改记录丢失。例如记录1中数据为1, 此时有两个线程想分别将其修改为2,3 我们得到的记录应该是1->2->3 但实际上留下的记录可能是1->3 称之为更新的丢失

如何工作的?

InnoDB 的 MVCC 是通过在每行记录后面保存两个隐藏的列来实现。这两个列一个保存了行的创建时间,一个保存行的过期时间(删除时间)。当然存储的并不是真实的时间而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动新增。事务开始时刻的系统版本号会作为事务的版本号,用来查询到每行记录的版本号进行比较。

作者:树懒学堂
链接:https://www.zhihu.com/question/464248235/answer/1934605425
来源:知乎


Comment