MVCC全称是【Multi-Version ConCurrency Control】即多版本控制协议。
MVCC的主要是靠在每行记录上增加隐藏列和使用undo log来实现的,隐藏列主要包括,改行数据创建的版本号(递增的),删除时间,指向undo log的指针等。MVCC是读不加锁的,只有在写的时候才会加锁,从而提高的并发的效率。
那么MVCC是如何保证读写隔离的呢?主要是通过快照读和当前读两个操作。
- 快照读:
MVCC为了保证并发的效率,在进行读取数据的时候是不加锁的,在执行select的时候(不带锁的普通select),会先读取当前数据的版本号,如果在select还没返回结果时,有事务将此行数据进行了修改,那么版本号就会比执行select的时候的大,所以为了保证select读取数据的一致性,就只会读取小于或等于当前版本的数据,这个历史版本的数据就是从undo log中获取到的。 - 当前读:
当执行insert、update、delete的时候,是读取的当前最新的版本数据,并且会给当前记录加上锁,用来保证在操作的时候不会被别的事务将版本号进行修改。
像普通的select就是快照读即读取的有可能就是数据的历史版本。
insert、update、delete、select ... lock in share mode 和select ... for update 读取的就是当前读,即读取的都是数据的最新版本。
通过MVCC机制保证了多个事务间的读写隔离,从而实现了事务的隔离性。
总结
MySQL事务的ACID,一致性是最终目的。
保证一致性的措施有:
A原子性:靠undo log来保证(异常或执行失败后进行回滚)。
D持久性:靠redo log来保证(保证当MySQL宕机或停电后,可以通过redo log最终将数据保存至磁盘中)。
I隔离性:事务间的读写靠MySQL的锁机制来保证隔离,事务间的写操作靠MVCC机制(快照读、当前读)来保证隔离性。
C一致性:事务的最终目的,即需要数据库层面保证,又需要应用层面进行保证,并且MySQL底层通过两阶段提交事务保证了事务持久化时的一致性。