学学MySql中的隔离性

学学MySql中的隔离性

之前写了一篇事务的笔记没保存,吐了。

为什么需要隔离性?

数据库上有多个事务同时执行的时候,就可能出现脏读不可重复读幻读的问题。

  1. 脏读:当前事务A可以读到其他事务B未提交的数据,也就是脏读
  2. 不可重复读:在事务A中先后两次读取同一个数据,两次结果不相同,这种就是不可重复读。注意:不可重复读读到的是其他事务已提交的数据。
  3. 幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这是幻读。注意:幻读不一样的是条数。

隔离级别

隔离级别越高,效率就会越慢。所以我们在不同的场景中需要选择不一样的隔离级别。
在不同的隔离级别可以解决不同的问题,如下表所示:

隔离级别 脏读 不可重复读 幻读
读未提交 Read Uncommitted 可能 可能 可能
读提交 Read Committed 不可能 可能 可能
可重复读 Repeatable Read 不可能 不可能 可能
可串行化 Serializable 不可能 不可能 不可能

来认真看看每一种隔离级别代表了什么

  • 读未提交:一个事务没被提交,他做的操作就可以被其他事务看到
  • 读提交:一个事务提交之后,他做的操作才可以被其他事务看到
  • 可重复读:一个事务在执行过程中看到的数据,在事务启动到结束都是一样的
  • 串行化:对于同一行记录,“读”“写”会加读写锁。

隔离的实现

来想一想最简单的读写,读操作对其他是没有影响的,所以我们需要考虑写操作对其他操作的影响

(一个事务)写操作对(另一个事务)写操作

锁机制保证了这件事。
事务再修改数据之前,需要先获得对应的锁。得到锁之后,事务就可以修改数据。事务操作期间,数据是锁定的,其他事务需要修改书需要等到该事务提交或者回滚后释放锁。
根据锁的粒度,锁可以分为表锁、行锁以及两者之间的锁。

  • 表锁在操作时会锁定整张表,并发性能差。
  • 行锁只锁定需要操作的数据,并发性能好。

如果我们需要锁定大量的数据使用表锁会节省更多的资源。MyIsam只支持表锁,InnoDB同时支持表锁和行锁。

(一个事务)写操作对(另一个事务)读操作

MVCC机制保证这件事。MVCC 只在 read-committed 和 repeatable-read两个隔离级别下工作。
MVCC,即多版本并发控制。核心思想是通过保存数据在某个时间点的快照来进行控制。使用MVCC就是让一个数据拥有多个版本。在查询的时候添加对应的约束条件,就可以获取对应版本的数据。
它的优点是读不加锁,因此读写不冲突,性能好。
它基于以下技术和数据结构:

  • 隐藏列:InnoDB每一行都有隐藏列,这一列包含了本行的事务ID、指向undo log的指针等。
  • 版本链:每行数据的隐藏列有指向undo log的指针,而每条undo log也会指向更早的undo log,这就是版本链。
  • ReadView:MySql在隐藏列和版本链的帮助下可以恢复到之前的任意版本。但版本的具体信息,需要依靠ReadView来确定。在读操作的时候读取到的数据与事务系统的快照比较,从而决定对ReadView是否可见。

注意MVCC旨在RR和RC两个隔离级别下工作,RU隔离级别下总是读到最新的数据,也就是直接读数据就行可以了,串行化则需要对每一行数据加锁。

posted @ 2022-08-04 16:35  Paranoid5  阅读(66)  评论(0编辑  收藏  举报