用户
 找回密码
 入住 CI 中国社区
搜索
楼主: Hex
收起左侧

[数据库] CI中关于DB事务处理的设计缺陷

  [复制链接]
发表于 2012-5-2 19:35:34 | 显示全部楼层
呵呵,楼上这同学,没认真看代码吧。
发表于 2012-5-2 19:55:09 | 显示全部楼层
本帖最后由 太尉天上飞 于 2012-5-3 09:28 编辑
cfc4n 发表于 2012-5-2 19:35
呵呵,楼上这同学,没认真看代码吧。

_trans_status _trans_depth等都有问题
发表于 2012-5-3 07:04:31 | 显示全部楼层
本帖最后由 燃雲 于 2012-5-3 07:08 编辑
cfc4n 发表于 2012-5-2 10:16
呵呵,我的意图不是 “前事务成败不影响后事务执行”,我的意图是“前面的非事务的成败,不影响下面事务的 ...


前面的非事务的成败,不影响下面事务的执行


是的,当然明白!


若指

UPDATE `cfc4n_user_info` SET `cfc4n_user_lock` = 1\nWHERE `cfc4n_user_id`...

是“非事务”,为何trace中会有SET AUTOCOMMIT=0紧随其后?

若update不在事务内,根本没有commit或不commit存在,是直接写,根本无法rollback。

“非事务”根本不会去碰$_trans_status的值。

结论是:这update是在一个事务内,也许与后面的事务无关。

这不是“非事务”,是“无关的事务”。Strict mode是所有事务前后都相关。并非你要的mode。

若指

UPDATE `cfc4n_user_info` SET `cfc4n_user_lock` = 1\nWHERE `cfc4n_user_id`...

应是“非事务”的话,查一下在前面什么时候开启了事务,也许是没有关上。

这段码是整体执行中的一个段落,执行中应还有执行过其他文件,不能说在:这文件中只有单一事务便说整体执行中只有单一事务。
发表于 2012-5-3 10:35:56 | 显示全部楼层
燃雲 发表于 2012-5-3 07:04
是的,当然明白!
是“非事务”,为何trace中会有SET AUTOCOMMIT=0紧随其后?

一个脚本中,一些SQL语句处于非事务中,另外一些出于事务中这难道不允许吗?不是很正常的使用吗?
"set autocommit=0"紧跟其后,不正说明了前面一个update之后,后面开始了事务 吗?

“非事务”根本不会去碰$_trans_status的值。

2.1.0版本的system\database\DB_driver.php中 query方法里,
307                        $this->_trans_status = FALSE;
难道非事务的查询不调用这个方法吗?

这位仁兄,您确定你认真看代码了,认真测试了?
发表于 2012-5-4 08:19:45 | 显示全部楼层
本帖最后由 燃雲 于 2012-5-4 08:21 编辑
cfc4n 发表于 2012-5-3 10:35
一个脚本中,一些SQL语句处于非事务中,另外一些出于事务中这难道不允许吗?不是很正常的使用吗?
"set  ...

没看,为你公司的问题,我去全面检查CI的源码,我有毛病吗?

但这307行

$this->_trans_status = FALSE;

引致你看到的错误吗?

翻查一下手册,$this->db->trans_off()才能真正关掉事务,默认$this->trans_enabled是TRUE。这是说,一般人理解的事务(transaction)从头到尾都开了。

你认为前面的update是“非事务”,但除非执行过$this->db->trans_off();,它肯定是“事务”。

trans_start(),trans_complete()是事务组的事,与事务无关。当然,对非事务,它们会无效。


回头再说,DB_Driver.php的307行是否有问题,我不敢说。似乎应先检查$this->trans_enabled,要测试过才知。若有trans_on(),这很可能出问题。

有$this->db->trans_off()而无$this->db->trans_on()也许是个缺失,也许是故意的,要问原设计者原因。

事务关了不能重开,又不想关掉事务,也许只能以non strict mode或manual transaction进行,没多选择。

整体而言,退一万步,假设真的有错,若“非事务处理”时出错,却修改“事务组处理”去补救,道理何在?



发表于 2012-5-4 11:00:23 | 显示全部楼层
没看,为你公司的问题,我去全面检查CI的源码,我有毛病吗?


既然都参与技术争论了,为啥不让自己的证据更严谨,更准确呢?

你认为前面的update是“非事务”,但除非执行过$this->db->trans_off();,它肯定是“事务”。


普通的SQL语句查询,调用的不是 query方法么?既然是,那么如果SQL出错,很明显会把_trans_status设为false,即307行的代码。普通SQL语句查询之后,再执行事务这是再正常不过的用法了。

整体而言,退一万步,假设真的有错,若“非事务处理”时出错,却修改“事务组处理”去补救,道理何在?

非事务处理时出错,影响了事务,那不在事务里处理,在哪里处理呢?  (别太纠结“事务、事务组”的概念,执行一个事务也是事务组,多个才算事务组,而且,跟文中意思并不违背)


---------------------------------------------------
PS:感谢关注,不再回复。谢谢。
发表于 2012-5-6 17:18:06 | 显示全部楼层
CI的事务问题的确有些复杂~~~~
发表于 2012-5-9 17:17:35 | 显示全部楼层
事务执行失败是怎么回事??
发表于 2012-5-12 01:14:30 | 显示全部楼层
其实说到事物,总让人感觉到一种取舍的艰难。即到底什么样的操作放到事物中,回滚的设置到底定在什么位置,strict模式的开启和关闭等等。
有一次参与国内某家大型电子商务网站的底层代码开发,对于事物有过多次争论,对此项目组多次开会统一思想,最后仍然是各执一词。就我个人而言,如果已经牵扯到数据库事务层面的操作,这样的项目,PHP的作用更应注重于前台,对于数据库的操作部分,应该交给更强势的语言,如java。
发表于 2012-5-28 17:19:55 | 显示全部楼层
使用存储过程来控制事务是不是更好呢,放到数据库层面就解决。

本版积分规则