#16649: Models.save() refactoring: check updated rows to determine action
-------------------------------------+-------------------------------------
     Reporter:  akaariai             |                    Owner:  nobody
         Type:                       |                   Status:  new
  Cleanup/optimization               |                  Version:  1.3
    Component:  Database layer       |               Resolution:
  (models, ORM)                      |             Triage Stage:  Design
     Severity:  Normal               |  decision needed
     Keywords:                       |      Needs documentation:  0
    Has patch:  1                    |  Patch needs improvement:  0
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------

Comment (by akaariai):

 A bit more information about what the approach suggested is about. Assume
 you load a model from DB, change some fields and save it. We currently do:
 {{{
 SELECT - load from DB
 [change fields]; save()
 In save:
     SELECT - assert that the PK exists in the DB
     if yes:
         UPDATE
     else:
         INSERT
 }}}

 The second select above is usually redundant. If we know the object is
 loaded from DB (self._state.adding == False), and we are saving it to the
 same DB it was loaded from (self._state.db == the db we are saving to),
 then it is very likely the object exists in the DB. So, instead we should
 do:
 {{{
 In save:
     if same db, not adding:
         exists = UPDATE
     else:
         exists = SELECT
         if exists:
             UPDATE
     if not exists:
         INSERT
 }}}
 So, in the case the model is already in the DB, we do just a single update
 instead of select + update. If it so happens it doesn't exist (which
 should be very unlikely), we do update with zero rows modified and still
 know to do an insert.

 This does lead to behaviour change on MySQL when there is a concurrent
 insert to the same table. Currently the SELECT sees nothing, and the
 insert will lead to integrity error. After this, the update will block
 until the inserting transaction is committed, and then update the matching
 row. However, on PostgreSQL the update sees nothing, so there is no
 behaviour change there. For MySQL users this will be better than what we
 have now. For PostgreSQL users there is no change from behaviour
 standpoint.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/16649#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to