We solve this in Phabricator by using BEGIN (depth 0) or SAVEPOINT (depth 1+) when incrementing the counter, ROLLBACK TO SAVEPOINT (depth 1+) or ROLLBACK (depth 0) when decrementing it after a failure, and nothing (depth 1) or COMMIT (depth 0) when decrementing it after a success. Our experience with transaction stacks has generally been good (no real surprises, doesn't feel magical, significantly reduces the complexity of transactional code), although we don't support anything but MySQL.
On Aug 23, 2012, at 1:49 PM, Brion Vibber wrote:
On Thu, Aug 23, 2012 at 1:37 PM, Daniel Kinzler daniel@brightbyte.dewrote:
I think it would be extremely useful to allow nested database transactions
- or
simulate them using a counter that would only to the actual commit after commit() has been called as many times as begin() was called before.
This actually used to be the case, according to the comment on Database::trxLevel:
* Historically, transactions were allowed to be "nested". This is
no * longer supported, so this function really only returns a boolean.
This means that currently, if you call begin() while a transaction is already in progress, the previous transaction is inadvertently committed, possibly causing inconsistencies (at least on MySQL).
Why was this feature removed? Not counting transaction levels is causing a world of pain for us on the Wikidata project, and I'm sure the same problem arises elsewhere.
Well, the main reason is probably that MySQL doesn't support nested transactions... trying to simulate them with a counter sounds fragile, as a single rollback would roll back the entire transaction "tree", not just the last nested one you started (or else do nothing if you just decrement the counter, also possibly dangerous if you expected the rollback to work).
-- brion _______________________________________________ Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l