This project is archived and is in readonly mode.

#1925 ✓invalid
Nicholas Faiz

Mysql::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1

Reported by Nicholas Faiz | February 10th, 2009 @ 12:26 AM | in 2.x

Hi,

I'm upgrading a Rails 2.1.1 app to 2.3 rc1 and encountering this quite a bit in my specs.

Trying to workaround it now, but thought I'd point it out. I'm surprised I haven't found mention of it anywhere else just yet.

Comments and changes to this ticket

  • Nicholas Faiz

    Nicholas Faiz February 10th, 2009 @ 12:36 AM

    Sorry, a bit more information for ths ticket.

    It seems to be happening on AR exectute statements calls to TRUNCATE:

    e.g.

    
    
    
    ActiveRecord::Base.connection.execute("TRUNCATE factsheets")
    
    
    
    
    
  • Jonathan Viney

    Jonathan Viney February 10th, 2009 @ 03:01 PM

    Can you show more of your logs? Are the savepoints being defined?

  • Nicholas Faiz

    Nicholas Faiz February 10th, 2009 @ 10:49 PM

    Unfortunately yesterday was also the day I chose to clean up my huge log files.

    If you can't replicate it in your environment, let me know and I'll restore the code and try to generate a log file for you. If you can replicate it there's probably not much point in my doing it.

    Thanks for the quick response.

    Regards, Nicholas

  • Jonathan Viney

    Jonathan Viney February 11th, 2009 @ 11:06 AM

    A basic test seems to work ok:

    
    Person::Note.transaction do
      Person::Note.transaction :requires_new => true do
        ActiveRecord::Base.connection.execute("TRUNCATE person_notes")
      end
    end
    

    Runs:

    
    SQL (0.2ms)  BEGIN
    SQL (0.1ms)  SAVEPOINT active_record_1
    SQL (3.0ms)  TRUNCATE person_notes
    SQL (0.4ms)  RELEASE SAVEPOINT active_record_1
    SQL (0.2ms)  COMMIT
    
  • Nicholas Faiz
  • Jonathan Viney

    Jonathan Viney February 11th, 2009 @ 11:56 AM

    It appears that TRUNCATE is a DDL statement, http://dev.mysql.com/doc/refman/..., and therefore causes an implicit commit. The docs already warn against using DDL statements inside savepoints.

    
    Person::Note.transaction do
      ActiveRecord::Base.connection.execute("TRUNCATE person_notes")
      Person::Note.transaction :requires_new => true do
      end
    end
    

    Can you simply use DELETE FROM instead of TRUNCATE?

  • Nicholas Faiz

    Nicholas Faiz February 11th, 2009 @ 12:02 PM

    Short answer - yes.

    This code was appearing in our test code, and was probably added quickly without thought. It's not something we need supported. I wanted to point out this error was occurring though.

    Thanks for the quick response.

    N.

  • Jonathan Viney

    Jonathan Viney February 11th, 2009 @ 12:07 PM

    No worries, let's close this off then.

  • Jeremy Kemper

    Jeremy Kemper February 11th, 2009 @ 06:07 PM

    • State changed from “new” to “invalid”
  • Nicholas Faiz

    Nicholas Faiz February 11th, 2009 @ 07:07 PM

    Is it possible to close this as something like 'Wont's Fix' instead of invalid? This is a real issue.

  • Elia Schito

    Elia Schito March 13th, 2009 @ 12:28 PM

    Found the same issue while running some rspec tests, but...

    in activerecord-2.3.1/lib/active_record/transactions.rb:182 there's the following note:

    === Caveats

    If you're on MySQL, then do not use DDL operations in nested transactions blocks that are emulated with savepoints. That is, do not execute statements like 'CREATE TABLE' inside such blocks. This is because MySQL automatically releases all savepoints upon executing a DDL operation. When #transaction is finished and tries to release the savepoint it created earlier, a database error will occur because the savepoint has already been automatically released. The following example demonstrates the problem: Model.connection.transaction do # BEGIN

    Model.connection.transaction(:requires_new => true) do  # CREATE SAVEPOINT active_record_1
      Model.connection.create_table(...)                    # active_record_1 now automatically released
    end                                                     # RELEASE savepoint active_record_1
                                                            # ^^^^ BOOM! database error!
    
    

    end

    (posted this just to help people that will google to here)

  • Hongli Lai

    Hongli Lai March 24th, 2009 @ 04:06 PM

    I'm not sure how this should best be fixed, so for now I've documented this caveat in docrails: http://github.com/lifo/docrails/...

  • stanislav.pogrebnyak (at gmail)

    stanislav.pogrebnyak (at gmail) June 15th, 2009 @ 08:00 AM

    This bug appears on shoulda tests too. 20% of my tests fail with that strange error. How can I fix it?
    Non transactional tests are unacceptable cos them are slow. What should I do?

  • Jeremy Kemper

    Jeremy Kemper June 17th, 2009 @ 03:03 AM

    stanislav, do not use DDL statements in your tests or code if you want to use transactions to rollback fixtures.

    This is not a "won't fix" -- it's simply not fixable because most databases do not support transactional DDL statements.

  • stanislav.pogrebnyak (at gmail)

    stanislav.pogrebnyak (at gmail) June 19th, 2009 @ 07:37 AM

    Uh, I was dreaming about "do nothing during migration to rails 2.3.x", Actually, I heave a strong filling that this errors cos shoulda contexts, but thnx anyway. Will digg my code.

  • Rob Aldred

    Rob Aldred August 7th, 2009 @ 05:51 PM

    Just wanted to add some comments that might be useful for people experiencing this with Rspec + Cucumber
    basically... turn off transaction fixtures... its the only way I have found to avoid this error in your tests.

    Then use a global before(:each) in the Rspec & Cucumber config files/helpers that uses DatabaseCleaner

    Rspec

    ruby

    config.after(:each) {

    DatabaseCleaner.clean
    

    }

    Cucumber

    ruby

    After('@no-transaction') do DatabaseCleaner.clean end

  • Rob Aldred

    Rob Aldred August 7th, 2009 @ 05:53 PM

    sorry syntax fail - no preview sucks :(

      # rspec
      config.after(:each) {
        DatabaseCleaner.clean
      }
    

    # cucumber After do

    DatabaseCleaner.clean
    

    end

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages