在上文《分布式事务?咱先弄明白本地事务再说 - ACID》中,咱们讲解了数据库的事务及事务的特性ACID,了解到一个数据库要支持事务,就须要实现完备的事务的规范,咱们才能说这是一个支持事务的数据库,例如Mysql、Oracle等。
本文就来讨论一下数据库实现事务的几个关键阶段,背后都经历了哪些曲折的技术变迁。html
数据库的事务,本质上是解决数据库并发的问题,处理多个数据操做时相互不干扰,都能获得正确的执行结果,这个问题在应用层是没法解决的,由于你彻底不知道同时可能有另外一个程序(进程)也在操做相同的数据项,因此,这个问题必须由数据库来解决。sql
最简单的思路,就是彻底顺序执行全部的数据库操做,不须要加锁,简单的说就是全局排队,序列化进行全部的事务单元,数据库同时只处理一个事务,特色是强一致性,处理性能低。
这种模式适应于早期的C/S开发模式,单机系统,一个系统,一个数据库(例如Access数据库),彻底本地用户+本地系统+本地事务。数据库
开始支持并行处理事务,若是事务之间涉及到相同的数据项时,会使用排他锁,或叫互斥锁,先进入的事务独占数据项之后,其余事务被阻塞,等待前面的事务释放锁。并发
注意,在整个事务1结束以前,锁是不会被释放的,因此,事务2必须等到事务1结束以后开始。分布式
采用了 并行+排他锁
之后,大幅提高了数据库事务处理效率,若是几个事务之间没有共享数据项,彻底能够并行被处理,但,一些数据库大牛们显然对这个性能还不知足,进一步研究细化发现,全部的事务当中,对数据的操做无非是读和写排列组合的几种结果, 读读、写写、读写、写读
这4种状况的不断重复。性能
哪些操做之间能够相互兼容,或者共享呢?例如,读的时候为何要阻止读呢?优化
因此,读写锁就应用而生了,进一步细化锁的颗粒度,区分读和写,让读和读之间不加锁,这样下面的俩个事务就能够同时被执行了。版本控制
读写锁,可让读和读并行,而读和写、写和读、写和写这几种之间仍是要加排他锁。code
有人可能要说,优化到这个份上,已经差很少了吧,还有空间?
大牛们用行动告诉世人,答案是确定的。
每每,肯定一个模型不是最难的,难的是对这个模型实现的境界,大牛们会把本身的实现往死里优化,并行+读写锁
解决了读和读的并行,大牛们接下来要解决的是写和读、读和写,甚至写和写是否均可以并行!htm
这个技术就是如今大部分数据库在使用的事务处理技术,MVCC(Multi Version Concurrency Control),也就是Copy on Write的思想,对数据项进行多版本控制,一个精妙的想法,用空间换时间,进一步优化锁,减小锁。
给每条记录增长版本号和删除俩个字段,在事务开始的时候copy一个新的版本,此时事务操做的其实是一个副本,所以不会影响其余事务对此数据项的读操做,选择版本号最大的记录读取。
另外,MVCC支持读已提交 和 重复读
俩种隔离级别,串行和读未提交都没有意义,一个必需要求排队执行,另外一个要求必须读取最新数据。
人类对速度的激情是没有最快,只有更快。
因此,以上方案的演变,本质是速度上的逐步提高的过程,到目前MVCC为止,在数据库层面能作的事情已经很少了。
进一步,如何解决写和写冲突的问题,这里提供俩个思路