ActiveRecord should use savepoints for nested transactions
Reported by Sean Kirby | June 10th, 2008 @ 06:54 PM | in 2.x
From http://dev.rubyonrails.org/ticke... in the old rails trac.
Jonathan Viney has created a patch that enables doesn't break existing transaction semantics but allows for transactional behaviour to be tested in transactional fixtures.
Comments and changes to this ticket
-
Jeremy Kemper June 10th, 2008 @ 10:35 PM
- → Assigned user changed from to Jeremy Kemper
I'd love to support savepoints. We've had the discussion regarding the default behavior of nested transactions, though, and it's not the way to go. Nested transactions should be explicit, otherwise we're going to flood the database with junk transactions that really only mean "include me in a transaction" not "start a new transaction". Let's extend the existing semantics instead of stepping on them. And add better test coverage ;)
-
Jeremy Kemper June 10th, 2008 @ 10:35 PM
- → Milestone changed from to 2.2
-
Tarmo Tänav June 16th, 2008 @ 08:02 PM
Jeremy, the plugin by Jonathan Viney actually does make transaction{} only create a nested transaction if an explicit ":force => true" option is passed to it. The only exception being transactional tests where one additional level of non-explicit transactions can be created (because the test class itself uses the first level).
So these changes should not change rails behavior outside tests.
This plugin however does not include the ability to configure rails behavior for implicit transactions (those automatically created by save/destroy). Which means that you will not be able to make some activerecord model always create an implicit transaction for saving itself, even if a higher level transaction already exists. But this is a capability not strictly neccessary for the nested transactions feature to be useful, as you can always create an explicit "transaction :force => true" block around a save if you need it.
-

jonathan July 3rd, 2008 @ 01:12 PM
- → Tag changed from to activerecord nested savepoint transaction
I'd like to see #533 included first (moving the transaction counter from Thread.current to the connection object), and then I'll add an updated patch for the savepoints.
-
Jeremy Kemper August 30th, 2008 @ 05:10 AM
- → State changed from new to open
#533 is in -- interested in porting your work over to Rails master?
-

jonathan August 31st, 2008 @ 11:38 AM
I've attached a patch for master.
The handling of increment/decrement_open_transactions has been moved to the connection object rather than handling it in AR::Base.transaction, seemed better to me.
I've added a transactional_fixtures accessor to the connection which is set by the fixtures. Not the nicest, but I wasn't sure what else to do.
There are some failures for databases that don't support savepoints (eg. sqlite). These are a bit hard to avoid unless we add a supports_savepoints? to the connection.
Anyway, this should get the ball rolling.
-

Hongli Lai October 1st, 2008 @ 03:19 PM
I think ':force => true' is a bit confusing. How about ':nested => true'?
-

Hongli Lai October 9th, 2008 @ 12:22 PM
savepoints-3.diff doesn't apply cleanly om master. Here's an updated patch, with conflicts resolved.
It doesn't pass the unit tests however. More investigation will be required.
-

Hongli Lai October 9th, 2008 @ 12:25 PM
Jonathan, is there a reason why you changed
def transaction(start_db_transaction = false)to
def transaction(start_db_transaction = false)?
-

Hongli Lai October 9th, 2008 @ 03:27 PM
Never mind my last message, I already figured it out. :)
Here's an updated patch which passes all unit tests, for MySQL, PostgreSQL and SQLite3. Changes are:
- Much improved documentation, including documentation about potential caveats on MySQL.
- :force option renamed to :nest, which is probably clearer.
- I had to revert commit 045713ee240fff815edb5962b25d668512649478 by Jeremy Kemper, "PostgreSQL: introduce transaction_active? rather than tracking activity ourselves". It conflicts with the savepoint code.
-

Hongli Lai October 9th, 2008 @ 05:00 PM
After speaking with Koz I've reimplemented Jeremy's transaction state introspection feature. The old implementation was incompatible with the old 'postgres' driver, which I fixed. I also added unit tests for this feature.
-

Hongli Lai October 9th, 2008 @ 05:19 PM
Koz said that it's probably not feasible to include this feature in 2.2, seeing that we're in a feature freeze. If anybody wants to help, I'm maintaining this savepoint stuff in the following git repository:
git://git.phusion.nl/rails.git branch 'savepoints'
-
Pratik October 17th, 2008 @ 05:14 PM
- → Milestone changed from 2.2 to 2.x
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
Source available from github
The Git repository resides at http://github.com/rails
Check out the current development trunk (Edge Rails) with:
git clone git://github.com/rails/rails.git
Creating or reviewing a patch
See the contributor guide.
Creating a feature request
Please don't. If you want a new feature in Rails, you'll have to pull up your sleeves and get busy yourself. Or convince someone else to do it. See the contributor guide on how to get going. But posting them here is just going to lead to ticket root.
Creating a bug report
When creating a bug report, be sure to include as much relevant information as possible. Post the code sample that causes the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.
Security vulnerabilities should be reported via an email to security@rubyonrails.org, do not use trac for reporting security vulnerabilities. All content in trac is publicly available as soon as it is posted.
Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kinda bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to sign on to with a "I'm having this problem too".
