Hi guys,
I spent literally *months* trying to find the best way to resolve this situation. On our high performance sites + backends (around 120qps, 50/50 split between read and write) we were getting IntegrityError raised by get_or_create (which we now refer to as Object Collisions).
We are able to trigger the issue by having two scripts attempt to get_or_create() a new object at the same time (it takes a few loop iterations until it reproduces itself).
When get_or_create() is called, it'll raise a duplicate key exception, but if you then attempt to do a .get() on the row using the same args/kwargs straight away afterwards, you'll notice it returns an empty result. This (we think) is because when you create a row within a transaction, although the row isn't there, it will still raise a duplicate key error until the row is either commited or rolled back.
Eventually, we created a modified get_or_create() which *reduce* the chance of it happening:
However, we are still left with a final problem, which is we either put a sleep() in the code (eww!) to increase the chance of a successful query, or you raise an ObjectNotReady exception (custom), and then add logic into your code to deal with this occurrence. The other option is that you re-factor your code so that the time between commits on large chunks of code are as small as possible, reducing the chance of this error. But, from what we can tell, you can only "reduce" the chance of raising an ObjectNotReady, you can't get rid of it entirely. (unless you get rid of transactions entirely lol)