当前位置:  开发笔记 > 编程语言 > 正文

是否需要在数据库之外进行事务性行为?

如何解决《是否需要在数据库之外进行事务性行为?》经验,为你挑选了4个好方法。

没有交易,我不敢在数据库中做任何复杂的事情.几乎总是有一个简单易用的内置命令.但是当你开始使用其他持久性数据时,你就不会那么简单地使用事务支持.一些例子是

文件系统

网络服务(我没用过)

即使在非持久性数据中,在异常之后撤消工作块通常也很有用.您使用语言获得的标准数据结构都不支持事务.

我想知道的是,为什么数据库是特例?

是否有任何有用的链接指向数据库外的事务行为主题?



1> Rob Williams..:

我必须恭敬地不同意:交易系统不是自动和专门的数据库引擎,恰恰相反......

我已经实现了一个与数据库事务不同的应用程序事务机制(在.NET中).它实际上相当容易(几个小时的工作,包括单元测试套件).它完全用C#编写,不依赖于任何数据库功能或任何其他组件.但首先是一些背景......

这种非数据库事务功能存在于Java平台上的多个表现形式中,例如EJB,ESB,JMS,以及通常与BPM相关联.其中一些表现形式使用底层数据库,但并非总是如此,也不是必需的.其他平台具有可比较的表现形式,例如MSMQ.

大多数遗留版本控制系统不实现ACID事务语义.正如ddaa所说,CVS不是Subversion(它的继任者).Visual Source Safe没有.如果您研究Subversion,您可以找到能够说明这一点的比较图表.

现在,对于关键点,数据库事务或其等价物并不能保证安全的业务逻辑.虽然我喜欢Subversion,但具有讽刺意味的是,这是一个很好的例子.

您可以虔诚地使用Subversion,以及自动构建脚本(一个编译,测试和打包应用程序的命令),并且仍然将破坏的构建提交到源控件存储库.我反复看过它.当然,使用非基于ACID事务的源代码控制工具(如VSS)会更容易.但是很多人都知道使用像Subversion这样的工具是可能的.

请允许我列出这个场景.您和同事正在开发应用程序,并使用Subversion作为源代码控制存储库.你们两个都在编写代码并偶尔提交到存储库.您进行了一些更改,运行干净的构建(重新编译所有源文件),并且所有测试都通过了.所以,你做出改变并回家.你的同事一直在做自己的改变,所以他也运行一个干净的构建,看到所有的测试通过,并提交到存储库.但是,你的同事然后从存储库更新,进行一些更改,运行一个干净的构建,并且构建在他的脸上爆炸!他再次恢复他的更改,从存储库更新(只是为了确定),并发现一个干净的构建仍然爆炸!您的同事花费了接下来的几个小时来对构建和源进行故障排除,并最终发现您在离开之前所做的更改导致构建失败.他向你和你的共同老板发出一封恶意的电子邮件,抱怨你打破了这个版本然后不小心回家了.你早上到达,发现你的同事和你的老板在你的办公桌旁等着骂你,其他人都在看!所以你快速运行一个干净的构建并向他们展示构建没有破坏(所有测试都通过,就像昨晚一样).

那么,这怎么可能呢?这是可能的,因为每个开发人员的工作站都不是ACID交易的一部分; Subversion仅保证存储库的内容.当您的同事从存储库更新时,他的工作站包含存储库内容的混合副本(包括您的更改)和他自己未提交的更改.当您的同事在他的工作站上运行干净的构建时,他正在调用不受ACID语义保护的业务事务.当他恢复更改并执行更新时,他的工作站然后匹配存储库,但构建仍然破坏.为什么?因为您的工作站也是不受ACID语义保护的单独业务事务的一部分,与您对存储库的提交不同.由于在运行干净构建之前尚未更新工作站以匹配存储库,因此实际上并未构建存储库中存在的源文件.如果您执行了此类更新,则会发现您的工作站上的构建也会失败.

现在我可以阐述我的初始观点 - 交易的范围/背景必须仔细考虑.仅仅因为你有一个ACID事务并不意味着你的业务逻辑是安全的,除非ACID事务的范围/上下文和业务逻辑完全匹配.如果您依赖于某种形式的数据库ACID事务,但是您在业务逻辑中执行了该数据库事务未涵盖的任何事情,那么您将有一个间隙可以产生可比较的灾难性错误.如果您可以强制您的业务逻辑与您的数据库事务完全匹配,那么一切都很好.如果没有,那么您可能需要单独的业务交易.根据不受保护的逻辑的性质,您可能需要实现自己的事务机制.

因此,消息传递可以是事务性的,但范围仅仅是消息.关于上面的示例,Subversion的上下文只是对存储库的单独提交.但是,业务事务是一个干净的构建,涉及更大的范围.这个特定问题通常通过将干净的构建与干净的结账一起编写,理想地使用连续集成实现(例如,通过CruiseControl等)来解决.在开发人员工作站上,它要求每个开发人员在清理构建之前执行规则以执行完整更新(甚至是干净的签出).

因此,回顾一下,每个事务都有一个限制其保护的范围或上下文.业务事务通常包含超出我们通常使用的事务机制(例如数据库引擎)范围的逻辑.你可能需要弥补差异.在极少数情况下,编写自己的事务机制甚至可能有意义.

我为一家规模不大的九十人公司设计了重要的业务系统.我发现有必要实施这样一种机制,我发现这种体验很简单,有价值,也很有价值.我会再做一次,或许更容易一点,但我总是会质疑为什么我不能坚持只是一个数据库事务.



2> ddaa..:

我认为只在数据库中看到事务的原因是,根据定义,提供事务的系统称为数据库.这听起来很圆,所以我必须详细说明.

事务支持是提供ACID属性的功能.通俗地说,这意味着事务是允许1.将一些谨慎的操作捆绑到一个包中,这个包可以作为一个整体成功,也可以作为一个整体失败.2.隐藏对并发用户的未提交更改,以便3.并发用户始终拥有系统的"一致"视图.

文件系统传统上提供一些锁定机制,但这与提供事务不同.但是,所有文件系统都具有一些原子属性.例如,如果您有目录/a/,并/b/和你同时尝试执行mv /a /b/amv /b /a/b,只有一个操作会成功,而不会影响完整性.然而,文件系统通常缺少的是能够将多个操作捆绑到一个孤立的原子束中.

答案提到了Subversion.所有理智的版本控制系统都有交易.当提交多个文件时,系统要么完全应用提交,要么完全拒绝提交(除了CVS,我不认为是理智的).拒绝的原因始终是同时发生的变化.版本控制系统实现者非常清楚维护数据库.

另一个答案提到消息系统是事务性的.我没有阅读链接材料,但答案本身只提到了消息的原子传递.那不是交易.

在布莱恩C.在这里提到之前,我从未听说过Clojure.在我看来,它确实是数据库上下文之外的事务的实现.这里的重点是并发控制,而不是保持持久数据的一致性.

因此,除了Clojure之外,任何需要事务的系统似乎都使用底层数据库,或者将自身变成数据库.



3> Powerlord..:

现代文件系统确实有交易.它们对最终用户来说是透明的.

NTFS,XFS,JFS,EXT3和ReiserFS都可以,仅举几例.

这只是文件系统的内部.许多操作系统还支持文件锁定(例如,参见*NIX世界中的flock(2)),具有独占(写入)和共享(读取)锁定.

编辑:如果您考虑一下,文件系统没有像现代数据库那样的隔离级别,因为一旦您读完文件,如果您没有锁定文件,传统上就会将其关闭.然后在想要写入时重新打开它.



4> Brian Carper..:

Clojure使用软件事务内存,它使用事务使编写多线程程序变得简单而安全,而无需手动锁定.Clojure具有不可变的数据结构,其中包含对它们的可变引用,并且需要事务来更改引用.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有