深夜浅谈MYSQL 的MVCC
Posted java充电站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深夜浅谈MYSQL 的MVCC相关的知识,希望对你有一定的参考价值。
最近在开发中因为经常涉及到数据库并发和数据一致性的操作,因此今晚特意简单总结了一份关于MVCC的文章跟大家分享。
1.什么是MVCC
MVCC (Multiversion Concurrency Control),即多版本并发控制技术,它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是把数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能
读锁:也叫共享锁、S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
写锁:又称排他锁、X锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
表锁:操作对象是数据表。mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行。
行级锁:操作对象是数据表中的一行。是MVCC技术用的比较多的,但在MYISAM用不了,行级锁用mysql的储存引擎实现而不是mysql服务器。但行级锁对系统开销较大,处理高并发较好。
2.MVCC是为了解决什么问题?
大多数的MYSQL事务型存储引擎,如,InnoDB,Falcon以及PBXT都不使用一种简单的行锁机制.事实上,他们都和MVCC–多版本并发控制来一起使用.大家都应该知道,锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC,能降低其系统开销.
说了这么多,可能还是会觉得有点懵逼,那么我们来举个通俗易懂的栗子来描绘一下吧:
books表中有5条数据,此时mysql给它设定的版本号为1。
这个时候有两个事务性的操作,事务A,B
事务A 系统版本号2:select * from books;因为1<=2所以此时会读取5条数据。
事务B 系统版本号3:insert into books ...,插入一条数据,新插入的数据版本号为3,而其他的数据的版本号仍然是2,插入完成之后commit,事务结束。
事务A 系统版本号2:再次select * from books;只能读取<=2的数据,事务B新插入的那条数据版本号为3,因此读不出来,解决了幻读的问题。
事务并发中有还有一个和幻读有点类似的概念,那就是不可重复读:
3.不可重复读:事务A重复读取同一条数据,在读取的同时事务B修改并提交了这个条数据,那么A再读取的时候就会发生不一致。
关于数据的不一致,我们经常会用事务回滚来处理这一方面,谈及事务回滚的原理我们就不得不得去了解一下mysql的回滚日志了
4.回滚日志(undo log)
作用: 保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。
内容: 逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。
什么时候产生:
事务开始之前,将当前是的版本生成undo log,undo 也会产生 redo 来保证undo log的可靠性
什么时候释放:
当事务提交之后,undo log并不能立马被删除,
而是放入待清理的链表,由purge线程判断是否由其他事务在使用undo段中表的上一个事务之前的版本信息,决定是否可以清理undo log的日志空间。
历史文章精选:
长按二维码
以上是关于深夜浅谈MYSQL 的MVCC的主要内容,如果未能解决你的问题,请参考以下文章