您的位置:首页 > 其它

事务的原子性

2016-04-11 13:26 169 查看
http://blog.sina.com.cn/s/blog_5e6fd4290100wwba.html

事务的原子性指的是,事务中包含的程序作为系统的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。这种特性称为原子性。原子性的意义是数据库系统的基础。

也许有的人想大多数程序员都没有需求去写要求超长时间高稳定性、高健壮性运行的程序。我想这是不负责任的想法。不管你写的是动态网站、嵌入式控制、移动程序、桌面软件还是别的什么,稳定性、健壮性、容错性和排错性都应是程序员努力做好的本职工作。对我这种写游戏软件的更是如此。会出莫名其妙问题的单机、网游都能赶走大批玩家。

事务原子性这一点我也是最近改一些bug感悟出了点头绪,才成本文。程序员手头都有很多现成的理论做编码依据,数据结构、算法、设计模式……有经验的程序员带领一个团队写出的程序也许不会有大的问题,不过毕竟程序员也是会犯错误的人,百密难免一疏。隐蔽bug经常让人防不盛防。

先说明一下什么是我所想的事务原子性问题。和数据库系统对事务原子性的定义差不多一样,一些逻辑操作是一个整体,要么完全成功,要么完全失败。但可惜我们不能拿几段代码所表达的抽象逻辑去要求计算机作为运算单元,CPU一步步的执行指令,我们始终无法完全保证这几段代码的原子性,你写出在逻辑上再多么滴水不漏的程序也抵挡不住猛然断电对逻辑做出的不可回滚和恢复的中断。所以对于事务原子性我们只能尽量考虑逻辑上的,物理上的无法保证只能尽力而为。关于原子性问题有如下五个要点。

一、简单事务。逻辑上不易或不能进一步细分的事务。

二、伴随事务。两个或两个以上弱相似度简单原子事务,我们可以说某个原子事务是伴随另外的原子事务的。例:玩家吃了补血药后,药品数量减少、玩家血量回升这两个就是伴随事务,不能少了药不回血。

三、集合事务。两个或两个以上强相似度简单原子事务所组成的集合。例:玩家放了群体补血技能后所有在队伍里的人物都要回血。

四、流程事务。两个或两个以上有先后逻辑顺序依赖的简单原子事务。例:玩家放了眩晕攻击,对方除了被攻击时要伤血,还要持续一段时间眩晕状态。

五、综合事务。有限次以上四种事务的组合。

看到这也许你大失所望,想也不过如此嘛。的确顺着想很容易,除非写代码时走神了否则减了药没回血的问题是不会出现的,即使出现了,这种bug也是好重现好排查修改的。但正常情况下表现不出bug不代表代码严谨,逻辑中途遇到非期望数据的情况也要考虑。此时最重要的还要考虑事务可回滚,比如加载一个数据文件创建一些逻辑对象,但处理到数据中间突然发现数据出了问题,这时千万不要把异常情况吞掉,要么对有问题的数据做记录和报告并略过,要么让整个逻辑失败并回滚前面已经正常执行的操作。异常情况处理不当往往造成一些非常隐蔽的bug,像幽灵一样若隐若现却如影随形。能简单归纳的问题都容易简单避免。要想保证事务原子性,在写代码时让自己头脑里有强烈的上面五点意识,在敲击键盘时能条件反射一样注意并规避即可。要保证程序健康,我想有下面几点。

一、保证事务原子性、可回滚性。参考上面五种原子事务。特别注意多线程这种流程不可控的逻辑间不要安插过多原子事务,不然会发现原子事务中断和回滚都会特别麻烦。

二、容错性。非常无关紧要的异常情况可以忽略掉,保证程序主要逻辑没有问题。

三、不吃异常。如果原子性和可回滚性不容易保证,那就把出错点的信息尽量详细的记录并报告,不要把异常吃了不吭声,否则那就是隐蔽bug的根源。把实在无法规避的问题像断言一样报告出来中断掉也比默不作声强。

四、KISS。Keep
it simple, stupid!即使异常被吃掉了,简单的代码也比错综复杂的容易debug。

事务原子性的重要程度足以写到每个团队的编码规范里,成为程序员潜意识的一部分。下次在写一段代码,甚至可能是一个for循环时,都要想一下中途失败该如何应对。代码质量说的容易做到难。好的代码的烂的代码都是长期积累的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: