----Aymeric.
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Hi again,
On Sunday 03 March 2013, Aymeric Augustin wrote:
> On 2 mars 2013, at 21:46, Shai Berger <sh...@platonix.com> wrote:
> > The Django documentation on transactions, at the moment says this on
> > Django's
> >
> > default behavior[0]:
> >> Django’s default behavior is to run with an open transaction which it
> >> commits automatically when any built-in, data-altering model function is
> >> called. For example, if you call model.save() or model.delete(), the
> >> change will be committed immediately.
>
> Yes, my proposal is a backwards-incompatible change with regard to this
> sentence.
>
> However, I believe that only a small fraction of the users of Django fully
> grok the implications of this sentence, and a fraction of this fraction
> relies on it to ensure some level of integrity.
>
I agree with this belief about users *deliberately* relying on the implications for integrity. I have no idea how many people simply wrote code that works, and will now break. I also have no idea how many people maintain a system started long ago by a more knowledgeable developer.
> > What I have a harder time living with is my other point, which has not
> > been refuted: The proposed change turns code that is currently correct
> > -- liable to break if changed, but still correct as it stands -- into
> > code with "phantom bugs" that show up only in production, under specific
> > timings of concurrent requests (because reads and writes which used to
> > be in the same transaction are now on separate transactions).
> [...]
>
> I believe that the level of backwards-incompatibility described above is
> within acceptable bounds for Django 1.6.
>
I believe this is the core of our disagreement here.
> I also believe that it beats the alternative — namely, live with the
> current behavior forever.
>
I sincerely hope that is not the only alternative; that there's a way to implement the new behavior side-by-side with the old one. There usually is.
> > If anyone can offer a way to detect the situation and warn users of the
> > change, that would make things perfectly fine. Changing the default
> > transaction behavior along the lines you suggested would be a great
> > improvement. I have a strong suspicion, though, that if the new behavior
> > is implemented as default (and with no recourse to the old behavior, to
> > boot), then that simply cannot be done.
> >
> > I think that as suggested, the change would break the project's
> > committments to its users in a way that is much more important than the
> > performance gains, avoided idle-in-transaction errors, and effort
> > considerations, all put together. That is my objection.
>
> Yes, I agree with this way to frame the discussion.
>
> We reach different conclusions because I don't consider backwards
> compatibility an absolute that trumps every other consideration. It's a
> continuum. Backwards compatibility must find a balance with progress.
I don't consider backwards-compatibility an absolute, and the first of my two paras which you quoted above shows just that. I do think there are proper ways to introduce backwards-incompatible changes, and what you suggested isn't one of them.
In particular, per https://docs.djangoproject.com/en/dev/misc/api-stability/, we should have a deprecation process with warnings, unless fixing a security bug. Even with security issues, it was deemed preferrable to take an expedited deprecation process when possible (e.g. with the markdown module) rather than an immediate breaking change. Throwing this process to the wind over an improvement -- as nice as it is -- seems unwise to me.
An immeiately-breaking change, where the breakage is hard to detect and debug, and with high potential for data loss... I don't think any warning in the release notes can be enough. All I can say is, -1.
Shai.
> I also believe that it beats the alternative — namely, live with the> current behavior forever.
I sincerely hope that is not the only alternative; that there's a way to implement the new behavior side-by-side with the old one. There usually is.
I don't consider backwards-compatibility an absolute, and the first of my two paras which you quoted above shows just that. I do think there are proper ways to introduce backwards-incompatible changes, and what you suggested isn't one of them.
An immeiately-breaking change, where the breakage is hard to detect and debug, and with high potential for data loss... I don't think any warning in the release notes can be enough. All I can say is, -1.
Basically, Django intends to provide autocommit by default. Rather than fight the database adapter that itselfs fights the database, I propose to simply turn autocommit on, and stop implicitly starting and committing transactions. Explicit is better than implicit.
This obviously has far-reaching consequences on transaction handling in Django, but the current APIs should still work. (Fixing them is part 2 of the plan.)
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
PostgreSQL and Oracle use the "repeatable read" isolation level by default.
MySQL uses "read committed" and SQLite uses "serializable". Users of these databases
may see a different behavior.
In practice, this would mean:- Define "hook points" that are a superset the old and the new APIs.
- Re-implement the current transaction management with these "hook points"
(hard, because the intended behavior of the dirty flag isn't clear).
- Implement the new transaction management with these "hook points"
(hard, because that prevents using Python's context manager abstraction,
which maps exactly to atomic blocks and guarantees that the exit method
is always called).
- Add checks to prevent invalid operations when mixing the old and new APIs,
this is extremely difficult to get right when there are many hook points.
- Provide simple guidelines on how the old and new APIs may be mixed.
- Ensure that the old API can be trivially removed, because the author of the
new code may not be there in two years.
This looks possible, but not in the amount of time I'm able to spend
volunteering for Django. If someone wants to implement this, I'll put my
branch on hold. Otherwise, I'll propose it for inclusion into core.
--
Aymeric.
Part 2 of the plan is more ambitious — it's about improving the transaction APIs. Here's the general idea.
I'd like to add an @atomic decorator that:- Really guarantees atomicity, by raising an exception if you attempt commit within an atomic block,- Supports nesting within an existing transaction, with savepoints.
On Tue, Mar 5, 2013 at 3:13 PM, Aymeric Augustin
<aymeric....@polytechnique.org> wrote:
> In the mean time, I discovered that it's impossible to implement
> TransactionMiddleware reliably as a middleware, because there's no guarantee
> that process_response or process_exception will be called.
Perhaps this could be fixed. We could add another middleware method
called process_finally or somesuch, that would be guaranteed to be
called on every request after the other methods.
Can
you give a concrete example of an exception being raised at commit
time?
For lack of a better idea, I'm considering deprecating the middleware and replacing it with a setting. This doesn't qualify as loose coupling; better ideas welcome!