CodeIgniter框架数据库事务处理的设计缺陷和解决方案

前端技术 2023/09/09 PHP

起因:

在我们线上的某个业务中,使用较老版本的CodeIgniter框架,其中的DB类中,对DB事物处理部分存在着一个设计上的缺陷,或许也算不上缺陷吧。但他却影响了我们生产环境,导致连锁反应。对业务产生较大影响,且不容易排查。这个问题,我在今年的3月中旬,曾向codeigniter中国的站长Hex 报告过,之后,我也忘记这件事情了。直到今天,我们线上业务又一次以为这个问题,害的我又排查一次。具体原因,各位且先听我慢慢说完。(这个问题同样存在于最新版本Version 2.1.0中)

分析:

以CodeIgniter框架Version 2.1.0为例,在system\\database\\DB_driver.php的CI_DB_driver类中第58行有个$_trans_status属性。

复制代码 代码如下:

//system\\database\\DB_driver.php
var $trans_strict = TRUE;
var $_trans_depth = 0;
var $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur
var $cache_on  = FALSE;

同时,这个类的query方法中,有赋值此属性的代码,见文件306、307行

复制代码 代码如下:

// This will trigger a rollback if transactions are being used
$this->_trans_status = FALSE;

这里也给了注释,告诉我们,如果使用了事物处理,那么这属性将成为一个回滚的决定条件。

在520行的事物提交方法trans_complete中,如下代码:

复制代码 代码如下:

/**
 * Complete Transaction
 *
 * @access public
 * @return bool
 */
function trans_complete()
{
 if ( ! $this->trans_enabled)
 {
  return FALSE;
 }

 // When transactions are nested we only begin/commit/rollback the outermost ones
 if ($this->_trans_depth > 1)
 {
  $this->_trans_depth -= 1;
  return TRUE;
 }

 // The query() function will set this flag to FALSE in the event that a query failed
 if ($this->_trans_status === FALSE)
 {
  $this->trans_rollback();

  // If we are NOT running in strict mode, we will reset
  // the _trans_status flag so that subsequent groups of transactions
  // will be permitted.
  if ($this->trans_strict === FALSE)
  {
   $this->_trans_status = TRUE;
  }

  log_message(\'debug\', \'DB Transaction Failure\');
  return FALSE;
 }

 $this->trans_commit();
 return TRUE;
}

本文地址:https://www.stayed.cn/item/25907

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。