innodb有四种事务隔离机制,read uncommitted、read committed、repeatted read、 serializable,隔离界别依次提高,而且基本靠锁实现这些隔离级别,但众所周知,锁的消耗是很大的。当然,我们也都知道,mysql实现了一种乐观锁的机制,在select 时候加上 for update就可以了,而且我们知道乐观锁其实是不用锁的,是靠数据的版本控制实现的,那么到底是咋回事呢。
mvcc,多版本并发控制,就是innodb为了减少对锁的依赖而实现的一种并发环境下、非锁依赖的可以正常访问数据的机制,mvcc就是通过版本控制实现的,而乐观锁就是基于mvcc实现的。
首先,innodb会在每行数据中隐藏两列,表示数据的创建时间和删除时间,但实际存放的不是时间,是修改的版本号,版本号来源于每一个事务id。
例如,刚插入第一条数据的时候,我们默认事务id为1,实际是这样存储的
可以看到,我们在content列插入了kobe这条数据,在create_version这列存储了1,1是这次插入操作的事务id。
然后我们将kobe修改为kobebryant,实际存储是这样的
可以看到,update的时候,会先将之前的数据delete_version标记为当前新的事务id,也就是2,然后将新数据写入,将新数据的create_version标记为新的事务id
当我们删除数据的时候,实际存储是这样的
可以看到,当前数据行的delete_version列被置为了3,也就是当前事务id。
由此当我们查询一条记录的时候,只有满足以下两个条件的记录才会被显示出来:
1.当前事务id要大于或者等于当前行的create_version值,这表示在事务开始前这行数据已经存在了。
2.当前事务id要小于delete_version值,这表示在事务开始之后这行记录才被删除。
以上两条规则,要是有一条不满足,这说明在事务执行过程中有其他的事务对数据进行了操作,则不满足条件的数据就不会被查询出来。庆幸的是,innodb默认隔离机制为repeatted read,是可以用到mvcc的,所以我们不必为此过多担忧!