-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested transactions. #506
Comments
Maybe the rollback should work independently of the depth? |
That only works if any inner transaction block propagates an exception that will skip any remaining outer calls. If an inner block signals that it wants a rollback by returning So something like:
Where the Now it could be that the An alternative might be to maintain a stack of results (whether commit or rollback,) which is processed by the outer I'm beginning to wonder whether a separate 'transaction manager' is the way to go. |
I’m starting to agree that the transaction manager may be the way to go.
|
Another advantage of having a transaction manager is that if someone disagrees with the strategy chosen, or has differing requirements then they can implement their own. It also opens the possibility to distributed transaction management which is something I've been thinking about for a while. |
I think that sounds great! Any suggestion on how that should work? |
In a sort of handwavey way, I'd see there being a single transaction manager within the dynamic scope of an outer transaction (i.e the first For a hypothetical "distributed" or "multi-service" transaction manager, I'd imagine the manager would allow the registration of service drivers (which presumably implement some interface,) which could also take part in the transaction, so, for instance some future STOMP client could be registered and have the 'transaction' managed for them. |
I'm beginning to think that a general purpose "Transaction Manager" could be developed separately, to work out what the interface should look like and how it would work for a variety of different services. |
A simple solution for this problem (the .^create inside a red-do :transaction) could be .^create be aware it's inside a transaction already and don't create a transaction for itself. A dynamic variable on Red-do would easily allow that. We still need a transaction manager, but for this specific case, I think that would be a good enough solution. |
Maybe generalising that a bit would also be good... maybe we could make all transaction calls set a dynamic variable and all transaction calls be ignored if that dynamic variable is set. (I don't know why, but this idea is sounding very familiar... have I already tried that?) |
The SQL Standards are a bit handwavey about nested transactions and different DB backends handle it different, but for our current purposes both Pg and SQLite basically ignore any subsequent
BEGIN
before aCOMMIT
orROLLBACK
:This has implications for code like:
Where the implicit transaction formed ( after the #505 ,) by the first statement in the
red-do
will create a warning about the nested transaction, but crucially theCOMMIT
of that implicit transaction will silently end the transaction formed by thered-do
so a failure in the second statement will not rollback any changes from the first, the subsequentROLLBACK
emitting a warning.An inadvertent side effect of the #504 is that a failure in the nested transaction will lead to a rollback of the outer transaction, however because they are in effect separate transactions (on different client connections,) a failure in the second transaction will have no effect on the first. Prior to #504 the behaviour would have depended on the number of concurrent clients of the driver (so essentially non-deterministic.)
So what I think needs to happen is that when the
new-connection
is called to get a new driver forbegin
then an e.g.transaction-depth
should be set (on the driver,) then any subsequentbegin
should check this and if it is set should increment the value and do nothing else and for anycommit
orrollback
should check the value and if it is not the original value then should should do nothing but decrement the value, if it is the original value set by the first begin then thecommit
orrollback
should be performed (and thetransaction-depth
unset though it is assumed that this instance of the driver will go out of scope at this point.)The text was updated successfully, but these errors were encountered: