After some investigation it turns out that this isn't about IntegrityErrors at all. Instead the problem is that inside @atomic block Model.save() uses @atomic(savepoint=False) internally. And @atomic(savepoint=False) forces the outer atomic block to roll back if errors happen.
If I recall correctly there is transaction.set_rollback(False) which can be used to remove forced rollback. In general, there are three ways to respond to errors inside transactions: 1. allow usage of the TX (MySQL, SQLite etc), allow user to decide commit/rollback 2. forbid usage of the TX (PostgreSQL), force it to be rolled back. 3. allow usage of the TX, but force rollback (Django) To me it seems explicit error when using connection in "forced to rollback" state is better than allowing saving more data, then silently rolling back the transaction. As you said this is useless. To be clear, this is about exceptions (database or other) in atomic(savepoint=False) blocks, not about caught IntegrityErrors - Django will allow you to continue and commit the TX in the caught IntgerityError case assuming the DB allows that. - Anssi On Thursday, September 19, 2013 5:29:39 PM UTC+3, Aymeric Augustin wrote: > > 2013/9/19 Anssi Kääriäinen <[email protected] <javascript:>> > >> There is a definite disparency about what the code does and what the docs >> say: >> """ >> If the block of code is successfully completed, the changes are committed >> to the database. If there is an exception, the changes are rolled back. >> """ >> >> If an exception is catched inside the block, then there should be no >> rollback. >> > > I'm not following you; as far as I can tell, that's what the docs say and > what the code does. > > With PostgreSQL you can't continue to use the transaction, but in other >> databases you can. >> > > You... may... might... Truth be said, you shan't. > > >> For these other databases allowing use of the transaction, yet still >> rolling back it later on seems to be a footgun - why are you allowed to >> continue to use the transaction if a rollback is going to happen anyways? >> > > Allowing a transaction to proceed after a statement has failed is: > - stupid if the transaction is allowed to commit — you would end up with a > successful transaction where not all statements have executed, which is > exactly the situation transactions are designed to prevent! > - useless if it isn't allowed to commit. > > That's why PostgreSQL forbids it. > > That's also what the SQLite docs say: > http://www.sqlite.org/lang_transaction.html > "It is recommended that applications respond to the errors listed above by > explicitly issuing a ROLLBACK command." > > Extracting the same information from the MySQL and Oracle docs is left as > an exercise for the reader. > > -- > 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-developers. For more options, visit https://groups.google.com/groups/opt_out.
