开发者

Django on MySQL: how to enable autocommit?

开发者 https://www.devze.com 2023-02-10 21:10 出处:网络
I have something like the following code that runs in a background process: def run() while True: objs = MyModel.objects.filter(last_updated < time.time() - FREQUENCY)

I have something like the following code that runs in a background process:

def run()
    while True:
        objs = MyModel.objects.filter(last_updated < time.time() - FREQUENCY)
        print objs

def update()
    while True:
       # some processing code
       mymodel.last_updated = time.time()
       mymodel.save()

The above functions run in two separate threads: update() updates all the models in turn, while run() selects the models that need updating. This all runs against MySQL and MyModel lives in an InnoDB table.

The problem is that run() always sees the same value for last_updated. The reason is that it is inside of a transaction and selects a consistent snapshot of the data. Naturally, I want it to select the latest data instead. It works if I do the following:

def run()
    from django.db import connection
    while True:
        connection.connection.execute('SET autocommit = 1')
        objs = MyModel.objects.filter(last_updated < time.time() - FREQUENCY)
        print objs

But that means that I'll be executing an additional query every single time. On top of that, if the connection gets closes between where I set autocommit = 1 and the following select, it will not work.

Postgres happily supports this: http://docs.djangoproject.com/en/dev开发者_运维技巧/ref/databases/#autocommit-mode (at least according to the docs), but is there a way to enable autocommit for MySQL?

Also, since this is running as a background process, no requests are processed, and no middleware is involved.


In Django, I listen to the connection_created signal, send a "set autocommit=1" statement once the connection is established. It works fine!

from django.db.backends.signals import connection_created
from django.dispatch import receiver

@receiver(connection_created)
def connection_init(sender, connection, **kwargv):
    connection.cursor().execute("SET autocommit=1")


The solution I am using is basically to run a commit at the end of the loop. So far as I can tell, Django just does not support this option, so there is no way to just disable autocommit.


You could look into transaction isolation level (Read uncommitted, Read committed, Repeatable read, Serializable).

Also, you should not tweak the connection behind Django ORM, but use the dedicated methods for that.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号