﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
28676	Using select_for_update with next save() in multiple threads stucks	M1ha Shvn	nobody	"I use django 1.10.7, PostgreSQL 9.4, psycopg 2.7.3.1 with gunicorn server. 
One of celery tasks can be executed simmultiniously by multiple workers.
Here is the code:
{{{
    with transaction.atomic(using=settings.DB_SHARD):
        # if I remove select_for_update here, everything works fine
        # Second thread will wait here with ""SELECT ... FOR UPDATE"" query in database with ""active"" status
        conv = Conversation.objects.select_for_update().get(pk=116774)

        # Some code, changing conv object without sending
        conv.user_unread_count = 0

        # First thread is stuck here
        # I see ""UPDATE ..."" query in database with ""idle in transaction"" status
        conv.save(update_fields=['user_unread_count'])

        # This doesn't work as well
        # conv.save(update_fields=['user_unread_count'], force_update=True)
}}}

When 2 workers start on the same Conversation object, second thread is waiting on select_for_update (which is well), and the first is stuck in save() operation. 

I've ran this code with django_debug toolbar and got stange select, done by save() method:

{{{
SELECT ••• FROM ""messages_conversation"" WHERE ""messages_conversation"".""id"" = 116774 FOR UPDATE
-- ??? What is this select here for
SELECT ••• FROM ""messages_conversation"" WHERE ""messages_conversation"".""id"" = 116774 

UPDATE ""messages_conversation"" SET ""user_unread_count"" = 0 WHERE ""messages_conversation"".""id"" = 116774
}}}

Moreover, I've fixed the bug by changing save() with update(), it doesn't do strange select:

{{{
    with transaction.atomic(using=settings.DB_SHARD):
        conv = Conversation.objects.select_for_update().get(pk=116774)

       # Some code here
  
        Conversation.objects.filter(id=conv.id).update(user_unread_count=0)
}}}




"	Bug	closed	Database layer (models, ORM)	1.10	Normal	invalid	django psycopg PostgreSQL select_for_update		Unreviewed	0	0	0	0	0	0
