Part of the EllisLab Network
   
 
Nested Transactions in MySQL database does not work (possible bug fix included)
Posted: 19 June 2008 11:23 AM   [ 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 03: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 03: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 721, on January 06, 2010 09:38 AM
Total Registered Members: 115007 Total Logged-in Users: 58
Total Topics: 122440 Total Anonymous Users: 5
Total Replies: 647312 Total Guests: 522
Total Posts: 769752    
Members ( View Memberlist )