READ COMMITTED定义

在提交读(READ COMMITTED)级别中,基于锁机制并发控制的DBMS需要对选定对象的写锁(write locks)一直保持到事务结束,但是读锁(read locks)在SELECT操作完成后马上释放(因此“不可重复读”现象可能会发生,见下面描述)。和前一种隔离级别一样,也不要求“范围锁(range-locks)”。
简而言之,提交读这种隔离级别保证了读到的任何数据都是提交的数据,避免读到中间的未提交的数据,脏读(dirty reads)。但是不保证事务重新读的时候能读到相同的数据,因为在每次数据读完之后其他事务可以修改刚才读到的数据。
提交读保证我们读到的数据都是事务提交后的数据,这样子就保证了程序中数据的正确性。
在Read Committed隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。

场景

我们首先设置我们的数据库事务级别为提交读,开启事务1,对student表做更新,但是不对其提交,再开启事务2对数据进行读取。如下:

事务T1事务T2
start TRANSACTION;start TRANSACTION;
select * from student; 
update student set name = 'a1' where id = 1; 
select * from student; 
 select * from student;

在事务2中查询到的student还是旧数据,对事务1进行提交,再在事务2中查询,数据则获取到的为我们最新的数据。
再次期间事务2和事务1中读取数据,事务1未提交时两个读取的数据不一致,可能发生不可重复读。

事务隔离级别实现原理

MVCC简介

多版本并发控制(Multiversion concurrency control, MCC 或 MVCC),是数据库管理系统常用的一种并发控制,也用于程序设计语言实现事务内存。

MVCC意图解决读写锁造成的多个、长时间的读操作饿死写操作问题。每个事务读到的数据项都是一个历史快照(snapshot)并依赖于实现的隔离级别。写操作不覆盖已有数据项,而是创建一个新的版本,直至所在操作提交时才变为可见。快照隔离使得事物看到它启动时的数据状态。

简单来说:MVCC 就是 同一份数据临时保留多版本的一种方式,进而实现并发控制。

在MySQL中建表时,每个表都会有三列隐藏记录,其中和MVCC有关系的有两列:数据行版本和删除版本号。

在RC级别下,我们每次读取最大的版本号即可读到最新的数据,而在RR(可重复读)级别下,我们读取当前事务的版本即可

而MVCC则通过undo log来实现。

 

MVCC实现算法

MVCC使用时间戳 (TS), 或“自动增量的事务ID”实现“事务一致性”。MVCC可以确保每个事务(T)通常不必“读等待”数据库对象(P)。这通过对象有多个版本,每个版本有创建时间戳废止时间戳 (WTS)做到的。

事务Ti读取对象(P)时,只有比事务Ti的时间戳早,但是时间上最接近事务Ti的对象版本可见,且该版本应该没有被废止。

事务Ti写入对象P时,如果还有事务Tk要写入同一对象,则(Ti)必须早于(Tk),即 (Ti) < (Tk),才能成功。

MVCC可以无锁实现。

InnoDB Multi-Versioning

InnoDB是一个多版本的存储引擎。它保留有关已更改行的旧版本的信息,以支持事务功能,例如并发和回滚。此信息以称为回滚段的数据结构存储在系统表空间或undo表空间中。InnoDB 使用回滚段中的信息来执行事务回滚中所需的撤消操作。它还使用该信息来构建行的早期版本,以实现一致的读取。

在内部,InnoDB在数据库存储的每行数据中增加三个字段:

  • 6字节的DB_TRX_ID字段,指示插入或更新该行的最后一笔事务的事务标识,此外,删除在内部被视为更新,在该更新中,该行中的特殊位被设置为将其标记为已删除。
  • 7字节的DB_ROLL_PTR字段,被称作回滚指针,回滚指针指向写入回滚段中的回滚日志。
  • 一个6字节的DB_ROW_ID字段包含一个行ID,该行ID随着插入新行而单调增加。如果 InnoDB自动生成聚簇索引,则该索引包含行ID值。否则,该 DB_ROW_ID列不会出现在任何索引中。

回滚段中的回滚日志分为插入和更新回滚日志。Insert undo logs只有在事务回滚的时候才需要,在事务提交的时候会被丢弃。Update Undo log主要用于一致性读,当时只有在InnoDB不存在为其分配的快照的事务后,才可以将其删除。由此,我们也可以看出来,不同的隔离级别,读取的数据不同,都是通过undo log来实现的

所以建议我们需要定期提交事务,尤其一些循环中的事务,包括仅发出一致读取的事务。否则,会导致InnoDB的undo log很大,而填满表空间。

在InnoDB MVCC中,当我们删除一行数据的时候,并不是立即从物理行删除实际记录。InnoDB只有在丢弃删除日志相关的undo log 的时候,才物理删除对应的行和索引记录。

 

Logo

更多推荐