李雷和韩梅梅的一次转帐事务–事务系统概述

上次咱们在最后一部分,给出了一个事务操做的模型和内部简单实现的方式,以期让你们能针对事务有一个比较简单的印象。今天,我就尝试针对事务的基本特性作一个简单的概述。固然,由于仍然是概述,因此不会特别深刻的去介绍和分析内部的机制,只但愿可以将一些难以理解的概念,用举例子的方式协助你们可以更容易的理解事务的基本概念。

谈到事务,咱们要作的第一件事,就是理解,什么叫作事务,以及为何要有事务。html

事务这个概念的产生,仍然是为了解决咱们在以前提到的打字机问题:
(面试

http://blog.sina.com.cn/s/blog_693f08470101l1n1.html)数据库

像咱们在上文中提到的,计算机只是一个图灵机,因此,若是计算机要实现咱们现实的世界的一些操做模式,只能靠模拟的方式进行。上次咱们是使用锁来处理一次写请求过程里面对应的屡次计算机操做的时候怎么看起来像是一次总体的操做。而在这里咱们要解决的问题是,一组用户的屡次写入和读取操做,怎么可以被看起来像是一次总体的操做呢?首先,让我用个例子来看看为何须要这样作。

为了后面叙述方便,让咱们先设定一个实际的环境场景:
梅梅给李雷打了一个电话,说最近想买一本英语书,须要一百元,李雷得知梅梅的请求,二话不说就开始操做他的网银给梅梅作了转帐付款:

假定李雷帐户是pk=1,韩梅梅的帐户是pk=2
begintransaction;
{查看李雷是否有一百元}
selectcashfromTwherepk=1;A操做
{肯定有足够的钱,减小李雷的钱}
updateTsetcash=cach-100wherepk=1;B操做
{给韩梅梅增长一百元}
updateTsetcach=cash+100wherepk=2;C操做
commit;好,我想我针对事务场景的场景应该描述清楚了。

首先咱们来介绍原子性服务器

从业务需求来讲,咱们必须保证,只要李雷的帐户减小了100块,那么这一百块必须可以加到韩梅梅的帐户里。若是中间有任何一个操做失败,系统不可以凭空多出一百元(李雷没有减钱,韩梅梅却加了钱),也不能凭空少了一百元(李雷减小了一百元,韩梅梅帐户却没增长)。
为了作到这个特性,就必须保证李雷帐户减钱与韩梅梅帐户加钱这两件事,要么同时成功,要么同时不成功。
这就是事务中的第一个重要的概念:原子性的含义分布式

下面咱们来介绍一致性
当看到本身的帐户减小了一百块之后,李雷问电话那头的梅梅:“梅梅,我看我这里操做成功了,你那里收到钱了没?”。若是这时候梅梅跟李雷说:”雷~我没看见我帐户的钱有变化啊“。
想想,这时候李雷会是什么感受?他的内心必定会”咯噔“一下,钱不会是丢了吧?赶忙给支付宝打电话确认怎么回事!ide

这里的这种状况,就是一致性没有保证而可能出现的一种状况,简单来讲,就是其余用户看到了事务三步操做过程当中的中间状态信息,这种信息是明显反用户常识的,因此应该尽量被避免。
所以我作个简单小结,这里咱们须要可以保证,当李雷看到本身帐户减小了100元的时候,韩梅梅的帐户里也必须可以看到增长了一百元。
这种要么同时出现,要么同时消失的保证,就是事务一致性。在看到这里的时候,相信必定会有人来问,这个一致性和原子性,看起来都是要么成功,要么不成功的感受,那么这两个概念有什么差别呢?

恩,下面我就来尝试解决这个疑惑吧~
区分这俩概念的关键,其实在一个”看”字,一致性约束的是一个用户写入并提交数据以后,其余用户去去读这条记录的时候,要么看到的是李雷尚未给韩梅梅转帐的那个状态,要么就是李雷已经成功转帐给了韩梅梅的状态,而在这两个状态之间的事务状态,好比李雷减小了100元,但韩梅梅还没加上这一百块的这个中间状态则不可以被其余人看到。而原子性只须要保证操做要么”最终“所有成功,要么”最终“所有失败而已。原子性不约束可见性,只保证操做的逻辑性。
这,就是一致性和原子性保证的差异。性能

最后,咱们来介绍持久性
我想,任何用户都必定不但愿下述的这种状况发生:李雷和韩梅梅都已经确认此次转帐成功了。然而过了5分钟,韩梅梅想用这充满了感情的100元去买他想要的英语书的时候,却发现钱不知去向了!?因而赶忙给支付宝打电话询问,支付宝却回答说:对不起您那帐户的数据库服务器重启了,丢失了一部分的数据,您帐户里的那个钱正好在丢失范围内,请节哀。
我想这时候应该有(bi….)的动机了吧:)htm

因而,这里就须要作一个很基础的保证:若是一个事务结束后,已经被其余人看到了,那么就不可以回退到事务以前的状态了。
这就是事务的第三个重要的概念:持久性的含义blog

好了,咱们介绍了三个关键的概念,原子性A,一致性C,持久性D。下课~进程

可能有看过其余数据库书籍的人会问了:”等等,你这不对吧?事务不是四个特性么?别忽悠咱们啊,咱们明天面试还得背这些概念呢,要不找不到工做啊~”

好好好,我立刻来介绍隔离性。。。

其实,我将隔离性从上面几个属性中剥离出来,是有我本身的考虑的,主要缘由是我我的认为,隔离性从逻辑概念上不与上面介绍的ACD平级。为何这么说呢?个人理由是,若是要模拟现实中发生的各类操做,只须要保证ACD三个属性,就可以完美的完成一次事务操做了,隔离性则明显是多余的。。

”那么,既然多余,去掉不就行了。。还留着他干啥?不知道这个隔离性是最(biiiii…)复杂的概念么,上次面试就由于没说明白这货因此面试被鄙视了呢!”

唉,这还真去不掉,由于去掉了,数据库的事务就慢的受不了了。。因此数据库开山的那批大牛也就不顾逻辑的清晰不清晰了,把这个概念加入了事务的四大要素。

从这件事,咱们也就能感觉到这个概念对性能的重要性了吧。。甚至能够说,数据库事务性能是否可以提高,关键就看你能接受哪一个隔离级别了呢!

咋样?是否是对这个概念肃然起敬了?好,那么咱们就来看看隔离性是个什么东西。

首先,明确隔离性要解决的问题域,与上面为了保证一次事务提交逻辑上的正确性不一样的,隔离性主要解决的问题是性能,或者更直接点,就是尽量的下降受到锁影响的事务进程的个数的。

而后,看他解决问题的方法:
在以前咱们提到,一致性要保证数据被其余人看到的时候必须是一个完整的数据状态,数据更新过程当中的中间状态则不能被看到。
好了,大牛们刚刚说了限定条件,下面立马给本身来了个响亮的自抽。。

隔离性的最低级别,就是读未提交
什么叫读未提交呢?咱们来抄维基。。
读未提交,可能出现脏读,当一个事务试图读取另外一个还未提交的事务正在修改的某一行数据时,肮脏读取(dirtyreads)就会发生。

简单来讲,就是一个事务,须要同时更新两张表的数据,而另外一我的去读这两张表的数据的时候,可能可以读到一张表的新值和另一张表的老值!
这明显就违反了一致性不是:)

其实,从我上面举出的例子,你就能感觉到,一致性和隔离性应该被一块儿考虑,一致性描述的是理想的事务过程应该怎样,而理想的事务由于锁的范围太大以致于性能难以接受,因此就使用隔离性的多个隔离级别来破坏一致性应该给出的保证,以换取更小的锁范围,从而获取更高的性能。

在这一篇,我不会扩展隔离性这个概念,由于若是不联系实际的数据库实现而死记硬背各类隔离级别的概念,我以为太难理解这个概念了。

所以,我将在后面展开讨论事务和分布式事务的章节再来关注隔离性的四个级别的问题。在这里,若是你回顾本篇的时候,若是能回想起原子,一致,持久这三个特性产生的缘由,而后又能理解到隔离性主要解决的问题域,以及从最低级别:读未提交,到最高级别:可序列化,隔离性的本质就是一个锁的范围逐渐扩大,性能逐渐下降,但能提供更强级别的一致性保证的这么一个特征。那么个人目标也就达到了。

随着隔离性概要介绍的完结,数据库系统概述这一章也就随着这篇概述的结束而结束了,在本章,我写做的主要目标就是,用尽量具象化的例子来对一个数据库系统作了一个概要性的描述。
下面,我会在后面的章节开始深刻到分布式存储的一些重要的领域进行更深刻的探讨。

enjoy~

相关文章
相关标签/搜索