Rails rails多表关联save的时候需不需要transaction?

tumayun · 发布于 2012年03月24日 · 最后由 yangyanhao 回复于 2012年03月27日 · 5841 次阅读
967

如题 在新公司,还没弄清这边的习惯,结果写代码的时候悲剧了,都是根据以前的经验写的 在关联表操作的时候加上了transaction,在partial里面用的是@var,结果push代码后,架构师说不要用transaction,这样会锁行,然后影响性能,还有要把partial当成function来看,尽量不要里面使用类似@var的变量,而要用local var,然后我就想问:

  1. 使用transaction的优点和缺点,以及各位平时都用不用(架构师说淘宝还有亚马逊等其他电商网站都不用transaction)
  2. partial里面用@var好还是local var

thx!!!

共收到 16 条回复
96

2、partial 里当然用 local var 1、transaction 一般没显示的用过。我在自己写 cron 任务的时候用

465

不用事务通常是比较关注性能,对数据一致性或同步要求不高的情况

22

我相信支付宝到处都是transaction..

96

1.如果关联表操作用的是AR callback,那自动就加了transaction哦。如果自己写存储流程的话,建议还是加上比较好。淘宝可能有强大的异步机制吧,所以不用,这个我猜的。 2.partial用local var,不过有时一个partial在哪里使用到自己心里清楚的话,用@var也未尝不可嘛。

967

能不能深入的分析一下transaction的优劣?性能差在哪里?

465

经典例子就是银行取款,如果一边在提款机取钱,一边用存折在柜台取钱,如果两边同时取,一个账号只有1000元有可能被两边都取走,那怎么办呢?就给账号上个锁,一边操作的时候账户就锁住,另一边的操作只能排队,这就保证每次账户数据都是正确的。这就是事务,transaction,同步问题,资源锁的一个例子。有很多地方说事务就是里面的操作要不全改,要不全不改,这其实说的是事务的特点,也是一回事,全不改就是事务中如你银行操作其中一步错了,账户就会回滚,所有操作都不起效。如你所见,事务,上锁,是为了保证数据一致,上了锁,大家都得排队,性能就慢下来了

686

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html 看了一下 api 确实需要加上好点 特别是 balance 这样的字段

967

@reducm 什么时候需要用到嵌套事务?与非嵌套事务有什么区别?

1342

多表同时进行增删改操作我还没遇到过不用事务的情况

8

那你们架构师把rails的内建事务关掉了没?

594

1 只有在必要的时候才使用Transaction,Transaction的确不该滥用。 2 你说的@var是指成员变量吧,如果是的话, 那么,partial里面用local var比@var好, 而且代码中应该尽量减少@var的数量, 等你当几年程序员之后,你会发现@var是和祸害, 绝大多数的Bug和奇怪的现象都和@var有关, 所以少用,但又不是说不能用,慢慢摸索吧。

594

还有,我记得,rails在多表关联上,内部已经做了事务处理啦。 不需要程序员自己再调用事务处理啦, 你把代码写出来给大家看看吧。 看代码更加直观一些。

967

@hooopo @ery 其实是那种没有写has_many的广联,但是业务上确实是有关联的, 比如deals表与n_deals是一对一的关系,但是rails中没有声明,然后在create action里面代码 类似于: deals.save n_deals.save 并没有做其他处理,经常导致要是n_deal表单填错了的话,deal保存上了,n_deal却没保存上, 我觉得这样很不舒服,然后改成事务的了,然后就悲剧了

594

#13楼 @tumayun 明白了,先说事务处理, 如果业务逻辑要求 deals.saven_deals.save 应该一起成功,或一起失败, 不能一个成功且另一个失败, 那么就要使用事务处理, 否则,没有必要使用事务处理。 至于业务逻辑,是产品经理或者项目经理决定的。

另外一个问题,我很奇怪,有这种关系,为什么不在model上做关联。 而且,在action中调用两次save是很不好的设计, 至少应该把两次save封装到一个model的public函数里。

96

#13楼 @tumayun 我觉得看你这种说法,deals.save和n_deals.save,是需要Transaction的,不然你这段代码的结果是未知的,大多情况未知的状况不失很你可以再这段代码改成:

deals.save
raise "stupid error"
n_deals.save

然后看看数据库的结果给是否满足你们的需求,如果这样的数据无所谓依然可以继续的话,那就不用。但是这显然不是一个一刀切的问题,如果为性能不用transaction,可是要设计一个回滚deals的办法, 这种情况性能可能还不如transaction。

即便是在model中的方法,以上的情况也是存在的。

96
  1. 就算你简单的save一下,Rails也会把数据库操作放在transaction里,留意一下日志就知道了,所以,你无法避免。
  2. partial里用Instance Variable主要是影响重用性。当不同的view里包含这个partial时,不同的action提供的数据未必放在同名的Instance Variable中。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册