Part of the EllisLab Network
   
 
Nested Transactions in MySQL database does not work (possible bug fix included)
Posted: 19 June 2008 12:23 PM   [ Ignore ]  
Summer Student
Total Posts:  3
Joined  06-15-2008

Hi,

I am having problems nesting code igniter transactions with MySql.  When you have many nested transactions, it doesn’t work properly.  For example:

$this->MT_DB->trans_start();
       
      $this->MT_DB->trans_start();
        INSERT 1
      $this->MT_DB->trans_complete();

      INSERT ERROR
       
$this->MT_DB->trans_complete();       


In the example above, INSERT 1 would still go thru even though there was an insert error.  This is due to MySql not being able to handle nested transactions.

POSSIBLE BUG FIX: I dug into the code igniter db driver code and noticed that code igniter is trying to fix this by keeping track of the number of trans_start and trans_complete calls and only starting/stopping a transaction at the root level. There was a bug in that code.

In mysql_driver.php, updated the following functions:

function trans_begin($test_mode = FALSE)
  {
      if ( ! $this->trans_enabled)
      {
        return TRUE;
      }
     
      // When transactions are nested we only begin/commit/rollback the outermost ones
      if ($this->_trans_depth > 0)
      {
        return TRUE;
      }

      // Reset the transaction failure flag.
      // If the $test_mode flag is set to TRUE transactions will be rolled back
      // even if the queries produce a successful result.
      $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
     
      $this->simple_query(‘SET AUTOCOMMIT=0’);
      $this->simple_query(‘START TRANSACTION’); // can also be BEGIN or BEGIN WORK
      $this->_trans_depth=1;  //LINE UPDATED
      return TRUE;
  }

function trans_commit()
  {
      if ( ! $this->trans_enabled)
      {
        return TRUE;
      }

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

      $this->simple_query(‘COMMIT’);
      $this->simple_query(‘SET AUTOCOMMIT=1’);
      $this->_trans_depth=0;  //LINE UPDATED
      return TRUE;
  }

Profile
 
 
Posted: 19 June 2008 04:16 PM   [ Ignore ]   [ # 1 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  869
Joined  09-25-2007

hi good catch, I found your problem when I first used codeigniter just over half a year ago, however I did not diagnose the root cause of the problem like you have.

http://codeigniter.com/forums/viewthread/61979/

I don’t know if this issue has ever been logged.

Profile
 
 
Posted: 04 September 2008 04:37 AM   [ Ignore ]   [ # 2 ]  
Summer Student
Total Posts:  1
Joined  09-04-2008

Thanks for posting this fix. I haven’t tried it out but it makes total sense. I think you also need to add the line to set the depth=0 after a rollback was executed at the top nested level (depth=1);

  function trans_rollback()
  {
      if ( ! $this->trans_enabled)
      {
        return TRUE;
      }

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

      $this->simple_query(‘ROLLBACK’);
      $this->simple_query(‘SET AUTOCOMMIT=1’);
      $this->_trans_depth=0; //line updated
      return TRUE;
  }

Profile
 
 
   
 
 
Post Marker Legend
New Topic New posts Hot Topic Hot Topic with new posts New Poll New Poll Moved Topic Moved Topic Sticky Topic Sticky topic
Old Topic No new posts Hot Old Topic Hot Topic with no new posts Old Poll Old Poll Closed Topic Closed Topic Announcement Announcements
Theme
Change Theme
Visitor Statistics
The most visitors ever was 819, on March 11, 2010 11:15 AM
Total Registered Members: 120464 Total Logged-in Users: 42
Total Topics: 126542 Total Anonymous Users: 2
Total Replies: 665377 Total Guests: 294
Total Posts: 791919    
Members ( View Memberlist )