MVCC:全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是为MySQL并发场景下无锁生成读视图进行读操作来进行多版本控制。
或者叫
MVCC:一致性非锁定读
mvcc是基于MySQL的回滚机制,在并发场景下为读操作做的的读取的一个优化。
实现基于undo log 版本链 + ReadView机制
https://www.51cto.com/article/641019.html
undo log存在的意义是确保数据库事务的原子性。
redo log用于保证事务的持久性,即ACID中的D。
redo log的主要功能是用于数据库崩溃时的数据恢复。
redo log保证事务的持久性,undo log用来帮助事务回滚及MVCC的功能。
数据持久化性能,批量插入,commit刷盘
Mysql 里会接触到三个核心日志分别是 binlog 、redo log、undo log, 这里面binlog是server层的日志,而redo log 和undo log都是引擎层(innodb)的日志,要换其他数据引擎那么就未必有redo log和undo log了。
https://zhuanlan.zhihu.com/p/213770128
四种:
不同的隔离级别下,mvcc表现不同
此时事务不是隔离的(ACID的I)A,B事务影响C事务
可重复读repeatable-read:默认
串行serializable
读未提交 read-uncommitted
读已提交 read-committed
串行serializable,出现的问题就是慢
可重复读级别,下next-key-lock机制
InnoDB存储引擎实现了如下两种标准的行级锁:
共享锁(S Lock),允许事务读一行数据。
排他锁(X Lock),允许事务删除或更新一行数据。
如果一个事务T1已经获得了行r的共享锁,那么另外的事务T2可以立即获得行r的共享锁,因为读取并没有改变行r的数据,称这种情况为锁兼容(Lock Compatible)。但若有其他的事务T3想获得行r的排他锁,则其必须等待事务T1、T2释放行r上的共享锁——这种情况称为锁不兼容
MySQL锁分3种
InnoDB存储引擎有3种行锁的算法
Record Lock:单个行记录上的锁
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身
Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身
Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。
Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。
在InnoDB 默认的事务隔离级别下,即REPEATABLE READ下,InnoDB存储引擎采用Next-Key Locking这种锁定算法。例如一个索引有10,11,13和20这四个值,那么该索引可能被Next-Key Locking的区间为:
(-∞,10]
(10,11]
(11,13]
(13,20]
(20,+∞)
当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。
什么是唯一属性,其实就是我们所说的能够标识该行数据唯一的标识。
unique 字段。比如:主键就是唯一的,不重复的。我们也可以自己设计多个字段组合不重复,唯一的。
表t共有1、2、5三个值。在上面的例子中,在会话A中首先对a=5进行X锁定。而由于a是主键且唯一,因此锁定的仅是5这个值,而不是(2,5)这个范围,这样在会话B中插入值4而不会阻塞,可以立即插入并返回。即锁定由Next-Key Lock算法降级为了Record Lock,从而提高应用的并发性。
表z的列b是辅助索引,若在会话A中执行下面的SQL语句:
SELECT*FROM z WHERE b=3 FOR UPDATE
很明显,这时SQL语句通过索引列b进行查询,该列不是唯一属性,因此其使用传统的Next-Key Locking技术加锁,并且由于有两个索引,其需要分别进行锁定。对于聚集索引(primay-key a),其仅对列a等于5的索引加上Record Lock。而对于辅助索引b,其加上的是Next-Key Lock,锁定的范围是(1,3)。特别需要注意的是,InnoDB存储引擎还会对辅助索引下一个键值加上gap lock,即还有一个辅助索引范围为(3,6)的锁。
因此,若在新会话B中运行下面的SQL语句,都会被阻塞:
第一个SQL语句不能执行,因为在会话A中执行的SQL语句已经对聚集索引中列a=5的值加上X锁,因此执行会被阻塞。第二个SQL语句,主键插入4,没有问题,但是插入的辅助索引值2在锁定的范围(1,3)中,因此执行同样会被阻塞。第三个SQL语句,插入的主键6没有被锁定,5也不在范围(1,3)之间。但插入的值5在另一个锁定的范围(3,6)中,故同样需要等待。