MySQL(十四)】事务 MVCC机制

事务的四大特性:Atomicity(原子性),Isolation(隔离性),Consistency(一致性)和Durability(持久性)。

重点说下隔离性,指的是多个事务并行执行时,效果上就像一个一个执行的。没有因为是并行而导致问题。因为系统不可能完全让事务顺序执行,这样性能太差,所以说需要在并发的同时满足隔离性。

接下来,再看下事务并发执行时会遇到怎样的问题?

脏写,或者说写覆盖。就是是A更新一行数据,还未提交,事务B又更新了同一行数据。一句话概括即使,允许事务更新未提交的事务已经更新的行。这个会导致严重的问题,比如事务B之后又回滚了,那么A的修改也会被覆盖。

脏读;

不可重复读;

幻读;

再重点看下幻读,幻读有两个特点:一是必须是别的事务插入导致的;而是必须是第二次读读到的行变多了;

隔离级别

sql标准有四种隔离级别:

MySQL(十四)】事务 MVCC机制_第1张图片

当然这个也仅是标准,不同的实现会略有不同,比如mysql就可以在rr级别下避免幻读问题。另外再强调下事务与锁的关系。为了保证事务并发读,在非序列化隔离级别下,事务的普通读取都不需要加锁,非锁定读。

下面看下mysql里如何解决脏读和不可重复读问题的。

使用的是MVCC机制。

在非锁定读机制下,如何解决脏读和不可重复读问题?答案是使用快照思路,在事务读取时,先得到一份当前数据库数据的快照,只从这个快照里读数据,后面的修改都不会影响这个快照。那么真的会备份全部数据生成这个快照吗?

不会的。之前讲过数据的行格式,知道每一条数据都有rollback_pointer属性。这个是干嘛的?其实每一个事务对同一行数据的修改均会被记录到该行数据上,按照先后关系形成一个链表,而rollback_pointer指向的就是链表的头结点。这个其实是undo log,记录了修改的内容,方便后续回滚。

所以,所谓的快照,其实就是读数据的事务需要在读取前,得到读取行的一个一致性视图,这个视图就是通过undo log来得到的。也就是只读自己可以看到的修改,屏蔽不能看到的修改。

对于rc级别,每一次普通的读取语句都会计算出一个视图;而对于rr级别,因为保证需要在整个事务期间读取到相同的值,所以会在第一次普通读取语句计算出一个视图,整个事务期间就用这个视图;

那么如何得到事务的可见性视图?

在事务发起读语句时,需要记录这么几个值。

1.当前事务id为A;

2.记录当前所有活跃的事务id列表list;

3.下一个可分配的事务idC;

然后从后往前遍历回滚段链表。拿到当前undo log里的事务id,假设为D:

如果D > C,说明事务D是本事务之后开启的,不可见;

如果D < A,说明事务D在本事务开启前就已提交,可见;

否则呢,看D是否在活跃事务列表list里,如果在,事务D还未提交,不可见,否则说明已经提交,可见; 

 

你可能感兴趣的:(mysql,MVCC,事务,隔离级别)