{"action":"created","issue":{"url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/61","repository_url":"https://api.github.com/repos/BertrandBordage/django-cachalot","labels_url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/61/labels{/name}","comments_url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/61/comments","events_url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/61/events","html_url":"https://github.com/BertrandBordage/django-cachalot/issues/61","id":179485884,"number":61,"title":"SELECT FOR UPDATE should never be cached","user":{"login":"jklardie","id":236199,"avatar_url":"https://avatars.githubusercontent.com/u/236199?v=3","gravatar_id":"","url":"https://api.github.com/users/jklardie","html_url":"https://github.com/jklardie","followers_url":"https://api.github.com/users/jklardie/followers","following_url":"https://api.github.com/users/jklardie/following{/other_user}","gists_url":"https://api.github.com/users/jklardie/gists{/gist_id}","starred_url":"https://api.github.com/users/jklardie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jklardie/subscriptions","organizations_url":"https://api.github.com/users/jklardie/orgs","repos_url":"https://api.github.com/users/jklardie/repos","events_url":"https://api.github.com/users/jklardie/events{/privacy}","received_events_url":"https://api.github.com/users/jklardie/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/BertrandBordage/django-cachalot/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2016-09-27T12:59:22Z","updated_at":"2016-09-29T10:01:42Z","closed_at":null,"body":"The SELECT FOR UPDATE mechanism is negated by cachalot because it caches the results of queries that include SELECT FOR UPDATE. This results in unwanted concurrent behavior in systems that rely on the exclusive locking of rows. These bugs are very hard to reproduce but can and do occur.\r\n\r\nAccording to postgres documentation (https://www.postgresql.org/docs/9.3/static/explicit-locking.html):\r\n\r\n> To acquire an exclusive row-level lock on a row without actually modifying the row, select the row with SELECT FOR UPDATE. Note that once the row-level lock is acquired, the transaction can update the row multiple times without fear of conflicts.\r\n\r\nProper behaviour should be to let all SELECT FOR UPDATE queries through to the database. The testcase in the following link should fail (it should produce a single query, instead of using the cached result): \r\n\r\nhttps://github.com/BertrandBordage/django-cachalot/blob/7e3137eac7bc1b4f683a336579653623e71c991e/cachalot/tests/read.py#L539\r\n\r\nA temporary workaround for now is to set the CACHALOT_QUERY_KEYGEN method, and to ignore queries containing select for updates:\r\n\r\n```\r\ndef get_query_cache_key(compiler):\r\n    if compiler.query.select_for_update or compiler.query.select_for_update_nowait:\r\n        raise UncachableQuery\r\n    return original_query_keygen(compiler)\r\n```\r\n\r\n----------------\r\n\r\n**EDIT**: Internally the Query object distinguishes between select_for_update and select_for_update_nowait. I added the latter to the code above, as both should be ignored by cachelot."},"comment":{"url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/comments/250423694","html_url":"https://github.com/BertrandBordage/django-cachalot/issues/61#issuecomment-250423694","issue_url":"https://api.github.com/repos/BertrandBordage/django-cachalot/issues/61","id":250423694,"user":{"login":"jklardie","id":236199,"avatar_url":"https://avatars.githubusercontent.com/u/236199?v=3","gravatar_id":"","url":"https://api.github.com/users/jklardie","html_url":"https://github.com/jklardie","followers_url":"https://api.github.com/users/jklardie/followers","following_url":"https://api.github.com/users/jklardie/following{/other_user}","gists_url":"https://api.github.com/users/jklardie/gists{/gist_id}","starred_url":"https://api.github.com/users/jklardie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jklardie/subscriptions","organizations_url":"https://api.github.com/users/jklardie/orgs","repos_url":"https://api.github.com/users/jklardie/repos","events_url":"https://api.github.com/users/jklardie/events{/privacy}","received_events_url":"https://api.github.com/users/jklardie/received_events","type":"User","site_admin":false},"created_at":"2016-09-29T10:01:42Z","updated_at":"2016-09-29T10:01:42Z","body":"You are right, I was not aware of this. I wrongly assumed Django handled them exclusively. I will update my initial post."}}
{"actor":{"display_login":"jklardie"}}