Myql 系列--MVCC

什么是MVCC

MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。

MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

举个例子,程序员A正在读数据库中某些内容,而程序员B正在给这些内容做修改(假设是在一个事务内修改,大概持续10s左右),A在这10s内 则可能看到一个不一致的数据,在B没有提交前,如何让A能够一直读到的数据都是一致的呢

有几种处理方法:

  • 第一种:基于锁的并发控制,程序员B开始修改数据时,给这些数据加上锁,程序员A这时再读,就发现读取不了,处于等待情况,只能等B操作完才能读数据,这保证A不会读到一个不一致的数据,但是这个会影响程序的运行效率。

  • 还有一种就是:MVCC,每个用户连接数据库时,看到的都是某一特定时刻的数据库快照,在B的事务没有提交之前,A始终读到的是某一特定时刻的数据库快照,不会读到B事务中的数据修改情况,直到B事务提交,才会读取B的修改内容。

当前读

当前读一定是读取的是记录的最新版本,select lock in share mode(共享锁),select for update,update,insert,delete这些操作都是一种当前读。读取时要保证其他并发事务不能修改当前记录,会对读取的记录加锁

快照读

不加锁的select操作就是快照读,即不加锁的非阻塞读,快照读的出现是基于提高并发性能的考虑,快照读的实现是基于MVCC,MVCC可以认为是行锁的一个变种,避免了加锁操作,降低开销,既然MVCC是多版本并发控制,字面上意思都知道了,可能读取到的并不一定是数据的最新版本。这里想一个问题,如果进行数据值的插入的时候,除了保留最新结果外,还会有很多历史版本,历史版本都存在undolog里,磁盘上,回滚的时候只需要找到当前行的上一个版本的数据就行了。当前行的历史版本数据存在undolog里,从undolog里取到当前行的结果返回就ok了

实现原理

MVCC(多版本并发控制)指的是维持一个数据的多个版本,使得读写操作没有冲突,快照读是MySQL为实现MVCC的一个非阻塞的读功能,MVCC模块在MySQL中的具体实现是由三个隐式字段、undolog、read view 这三个组件来实现的。 说白了MVCC就是为了实现读(select)-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现。

数据库并发场景有三种,分别为:

  • 1、读读:不存在任何问题,也不需要并发控制

  • 2、读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读、幻读、不可重复读

  • 3、写写:有线程安全问题,可能存在更新丢失问题

MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每一个修改保存一个版本,版本与事务时间错关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决以下问题:

  • 1、并发读写DB时候,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。

  • 2、解决了脏读,幻读,不可重复读等事务隔离问题,但是不能解决更新丢失问题。

每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID等字段

  • DB_TRX_ID: 6byte,最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID

  • DB_ROLL_PTR: 7byte,回滚指针,指向这条记录的上一个版本(存储于rollback segment里)

  • DB_ROW_ID: 6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚集索引

你可能感兴趣的:(数据库,mysql,数据库)