在我正在使用的现有代码中,我发现没有包含在交易中的汇款程序是完全不可接受的还是可以的,因为有所有需要的健全性检查,即要转账的金额大于零,以及余额大于或等于零的 ORM 级别验证。
我实际上对此感到如此困惑的原因是因为它来自一个可靠的开发人员,而且它是一段书本上的代码,看到这样的事情而没有看到交易是很奇怪的:
self.balance -= amount
save!
target.balance += amount
target.save!
在我正在使用的现有代码中,我发现没有包含在交易中的汇款程序是完全不可接受的还是可以的,因为有所有需要的健全性检查,即要转账的金额大于零,以及余额大于或等于零的 ORM 级别验证。
我实际上对此感到如此困惑的原因是因为它来自一个可靠的开发人员,而且它是一段书本上的代码,看到这样的事情而没有看到交易是很奇怪的:
self.balance -= amount
save!
target.balance += amount
target.save!
在没有看到任何代码的情况下,我会做出有根据的猜测,即现有代码是不可接受的。即使进行了健全性检查,如果在“转移”过程中的语句之间从该帐户提款,您的代码中也会出现竞争条件,这将导致不存在的资金转移。当然,当有很多并发用户时,这种情况发生的概率更大。
让我向您展示为什么使用一些伪代码这是一件坏事。
两次汇款:
#1: How much money does George have? $1500, that is fine.
#1: Send $1000 to Martha.
#1: Take $1000 from George.
#2: How much money does George have? $500, this is not enough. Give up!
#2: Do not send $1000 to Martha.
#2: Do not take $1000 from George.
真正发生的事情:
#1: How much money does George have? $1500, that is fine.
#2: How much money does George have? $1500, that is fine.
#1: Send $1000 to Martha.
#2: Send $1000 to Martha.
#1: Take $1000 from George.
#2: Take $1000 from George.
乔治已经成功转移了他没有的钱!
您的数据库获得的流量越多,这种冲突的可能性就越大。
当然,您必须尽快修复它。事务是一个逻辑工作单元,可以包括任意数量的文件或数据库操作。只有事务可以确保一切正常或不正常,并让您逃避从不一致的意外状态恢复的日志。