数据库笔记1——mvcc(多版本并发控制)

一、数据库4大隔离级别

为了解决并发事务存在的脏读(读到了其他事务已修改还未提交的数据)、不可重复读(一个事务里两次读同一个数据,但数据不一样,因为这个数据在两次读的间隔里,有其他事务修改了这个数据并提交了)、幻读(a事务读取表的记录数为x,然后有其他事务对这个表进行了新增或删除行,a事务再读取该表时,发现记录数不再是x)等问题,数据库大叔设计了四种隔离级别。分别是读未提交,读已提交,可重复读,串行化(Serializable)。

  • 读未提交隔离级别:只限制了两个数据不能同时修改,但是修改数据的时候,即使事务未提交,都是可以被别的事务读取到的,这级别的事务隔离有脏读、不可重复读、幻读的问题;
  • 读已提交隔离级别:当前事务只能读取到其他事务提交的数据,所以这种事务的隔离级别解决了脏读问题,但还是会存在不可重复读、幻读问题;
  • 可重复读:sqlserver通过限制了读取数据的时候,不可以进行修改,所以解决了不可重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题(而mysql是通过mvcc:多版本并发控制,解决了不可重复读和幻读)
  • 串行化:事务最高的隔离级别,在该级别下,所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

二、数据库默认隔离级别: 

mysql ---可重复读(在这个级别,因为普通查询都是快照读(其他事务的新增记录不会被看到,另一种是当前读),所以不会造成幻读),

oracle,sql server ---读已提交,sqlserver可以设置SNAPSHOT (快照隔离)来解决幻读。

三、 Mysql的Mvcc:多版本并发控制,解决了幻读

每一行数据都有两列隐藏列:创建版本号和删除(更新)版本号,这两列的版本号就是当时执行插入、修改、删除时的全局事务id。

SELECT

InnoDB会根据以下两个条件检查每行记录:

A、 InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。(解决了其他事务新增了行的幻读)

B、 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除,因为如果事务开始前就已经被删除,那么行的删除版本号会小于当前事务版本号。如果行在事务开始后被其他事务删除了,该行的删除版本号一定大于当前事务版本号,此时再读一次还是可以读出和前一次相同的记录。(解决了其他事务删除了行的幻读)

只有符合上述两个条件的记录,才能返回作为查询结果

 

INSERT

InnoDB为新插入的每一行保存当前系统版本号作为行版本号。

 

DELETE

InnoDB为删除的每一行保存当前系统版本号作为行删除标识。

 

UPDATE

InnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。

posted @ 2022-03-15 21:06  暗,伏!  阅读(168)  评论(0编辑  收藏  举报