1.自从JDBC部长与东海之滨的阿拉伯联合酋长国数据库达成合作协议后,IO部长退居二线。本来他是想把JDBC归自己管理的,但是国王实在是太急躁了,任命了一个新的JDBC大臣来负责这件事情。JDBC大臣经常在清晨给国王做简报??:“陛下,我们的JDBC设计的非常好,别看Hibernate,Mybatis是现在的事实标准,底层都是用我们的JDBC接口。”“国王赞许地点点头,似乎忘记了这是躲在角落里的IO大臣的功劳。IO部长咬牙切齿,无奈。这一天,JDBC正在给国王带来关系数据库的好处:“陛下,这种关系数据库比起简单的文件系统有一个巨大的优势,那就是支持事务。”听到JDBC部长又在贬低自己分管的部门,IO部长勃然大怒。国王问:“什么是交易,为什么需要交易?”账户需要增加100元,涉及到两次操作。这两个操作要么完成,要么都不执行。只有这样才能保证数据的一致性。这是一个交易。数据库中有一个事务概要阿联酋四个特性:原子性、一致性、隔离性、持久性,简称ACID,要不我给详细解释一下?”国王连忙摆手:“不不不不,不要不要用这些细节打扰我,只需告诉我们的受试者如何使用它。”JDBC部长说:“这很简单。默认情况下,我们的JDBC会把对数据库的操作看成一个事务。当然,subjects也可以设置为手动方式,手动提交和回滚事务。不管怎样,都很简单。”国王说:“那就好,爱卿辛苦了,还有什么事吗?该离开朝廷了。”2.阴谋IO大臣回到家中,仍旧满腔怒火,请来手下商议。InputStream说道:“大人,虽然这位JDBC大臣横行,但我们暂时拿他没办法,现在是Web时代,哪个应用程序不用数据库呢?”我只需要等待合适的时间。”“什么时间?”“你看今天提到事务的JDBC家伙,但是这个事务只在一个数据库中有用。如果我需要跨数据库怎么办?比如我的账号在A库,你的账号在B库,那么转账的时候怎么办?如何实现什么样的ACID?”InputStream不以为然:“谁会傻到把我们的账户信息放到两个数据库里?,现在大部分应用数据量都不大,放在一个数据库里绰绰有余。当数据量达到一定程度,就需要对数据库进行拆分,就会出现跨库事务。那个时候,我们的机会就来了,我们已经准备好了解决办法,请参考那家伙,不信你推不倒他!”IO部长做出决定:“好!干吧,这件事离不开阿联酋(DatabaseUnitedArabEmirates)的支持,我和他们还有友谊,所以派人去,承诺很多钱,让他们继续合作就在IO部长密谋的时候,JDBC部长的家里灯红酒绿,Connection等有识之士曾提醒JDBC部长要和阿联酋搞好关系,这样才会有什么以后有意想不到的需求。但是在领导下的JDBC部长怎么听得进去?3.InputReader的两阶段提交确实很有远见,随着时间的推移,Web越来越发达,而帝国中出现了很多庞大的网站,他们的各种数据确实是不可能放到一个数据库里的,把一个大的业务系统分成多个数据库是势在必行的,当一个业务同时操作多个数据库的时候,就很不方便了。没有分布式事务就无法完成。这时,一份秘密奏折被送到了国王的办公桌上,控诉JDBC大臣保守,在好的形式面前不与时俱进,对分布式事务漠不关心,无所事事。国王召集法庭会议讨论分布式交易的问题。他带头攻击JDBC部长:“亲爱的,你有没有听说对象要求支持分布式事务?”JDBC部长惊慌失措:“这……这似乎是一群无良之徒提出的要求。陛下应该忽略它。”IO部长冷笑:“不讲道理的人?没有什么。”IO大臣觉得自己有把握,撕破了脸。国王有些明白了,直接对IO大臣道:“艾情,告诉我该怎么做?”“陛下,什么时候部长正在与阿拉伯联合酋长国进行谈判,并与他们建立了良好的友谊。我前几天招待他们的时候,特地提到了这件事。甲骨文告诉陈,这好办。其他王国正在讨论实施两阶段提交协议,我们也可以参与。“虽然IO部长跟阿联酋讨价还价很久了,也不知道花了多少钱,但还是随口说了。JDBC部长看到IO部长进了他的一亩三分地-点地,急忙问道:什么叫二阶段提交?IO大臣不屑地看了他一眼,从袖子里掏出早就准备好的提案,双手呈给国王,国王哪里来的看懂了,一看就给急于看透的JDBC大臣一看,写得赫然在列:由于两阶段提交协议涉及到多个分布式数据库,我们设置一个全局事务管理器,就是负责协调各个数据库的事务提交。为了实现分布式事务,特设两个阶段:Phase1:全局事务管理器向各个数据库发送准备消息。每个数据库都需要在本地准备好一切,perform操作,锁定资源,记录redo/undo日志,但不Commit,简而言之,进入准备提交或回滚状态,然后向全局事务管理器报告是否准备就绪。Phase2:如果所有的数据库都报告它们已经准备好了,那么全局事务管理器就会下命令:提交。这时候,每个数据库才真正提交。既然之前万事俱备,只欠东风,只需要快速完成本地提交即可;如果有数据库报告没有准备好,事务管理器会下达命令:Abort,此时每个数据库都需要执行回滚操作,释放阶段1锁定的各种资源。JDBC部长也是专家,所以他一眼就能明白是怎么回事。阶段1是让每个人都准备好,阶段2是快速提交。这是一个看起来很美好的理想计划,但他意识到其中存在漏洞。他的手下曾警告说:一旦涉及到分销,事情就不会那么简单了,哪里都有失败的可能。比如在第二阶段,事务管理器出现问题怎么办?各种数据库还在等着你下命令吗??还是不提交,资源我还在这边锁着,半天放不出来,耽误!现在还是第二阶段。由于网络问题,数据库1收到了事务管理器下发的提交命令,而数据库2没有收到。两个数据库状态不一致,怎么办?JDBC部长铁了心给IO部长挖坑:让你炫耀!让你给我穿小鞋!他说:“陛下,IO大臣不愧是设计JDBC协议的人,我深得大臣钦佩,才学无几,恳请陛下准许IO大臣又出来和阿联酋设计一个新的协议来支持分布式交易。”国王答应演奏。4.JTAIO大臣满心狐疑,不知道JDBC老爷子给自己下的是什么药,于是回府与众人商议。眼看着自己多年前的策略就要成功了,InputReader兴奋不已:“不管怎样,只要我们制定了这个分布式事务协议,JDBC老头就得下台了。”“是,到时候由我们负责。”文件、网络、数据库和Java帝国都由我们的IO主宰。”InputStream开始畅想了美好的未来,当时我估计它至少会从5级升到4级。IO部长看在之前交情不错的份上,马上安排了与阿联酋的谈判。这次很容易就达成了协议,IO部长还给了他一个非常响亮的名字:JavaTransactionAPI(简称JTA)。这个JTA规范使用起来也比较简单,只要拿到一个UserTransaction就可以操作了,帝国的臣民不需要关心底层协议的细节:经过国王的认可,JTA正式上线晋升。然而,让IO大臣万万没想到的是,在JTA发布前夕,国王亲切召见了自己和另一名不知名的官员。国王关切地说:“亲爱的,我知道你很忙,负责网络和文件操作,为了减轻你的负担,我决定任命一个新的JTA部长来协助你!”IO部长犹如晴天霹雳,他的辛勤付出完全被忽略了。为什么是这样?他迷迷糊糊的回到府里,好吧,我几天不思饮食不思茶。出来安慰他的是InputReader:“这是陛下的帝王之术,我怕我们家族变大,所以才在朝堂上权衡。”你可以放心了,你看,JDBC部长也被打压了,荣光不复存在了。5.因祸得福,但JTA并没有像JDBC那样得到广泛应用。JDBC大臣挖的坑终于露出了狰狞的面目。只是这个坑没有让IO部长掉进去。新的JTA部长背上了替罪羊。主体的抗议越来越多:分布式事务伴随着大量节点的通信交换,协调者必须判断其他节点是否完成。另外,网络带来的超时导致JTA性能低下。在高并发和高性能场景下是有难度的。感谢IO部长的工作,现在阿联酋所有部落都支持两阶段提交,很多应用服务器Websphere、Weblogic等都支持JTA,但是用户都是***,而且都快了一种装饰。JTA大臣每次上庭都瑟瑟发抖。他是一个平庸的人。虽然处处救火,却解决不了根本问题。现在那些高并发的系统尽量避免两阶段提交。他们绕过JTA部长,直接找到IO部长抱怨道:“大人,JTA的制定是你主导的,但这个标准太理想化了,与现实完全不符!”IO部长说:“不行,这不是你要的吗,用户A和B的账户在两个数据库里,A给B转100块钱的时候,要保证A扣100块钱,然后B加100元。”“这是官方的想法,他们总想保证两个数据库的实时一致性(强一致性),为了达到这个目的,JTA付出的代价太高了,我们不现在就想做。不一致的我们可以忍受一段时间,只要它们最终是一致的。比如A转100元给B,A里面的钱已经扣掉了,但是B里面的钱会不会实时增加,过段时间保证增加就够了。”“最终一致性?有意思!”,想到Java帝国的官方标准总是被臣民制定的事实标准打败,敏锐的IO大臣立刻看到了背后的机会,他决定这次联合民间力量,反击再次,一举摆脱JDBC部长和JTA部长。想到这里,IO部长得意一笑……【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信获得授权公众号编码】点此查看作者更多好文
