django处理多线程访问和操作数据库的安全问题

当多线程对数据库进行访问和操作时,需要考虑到一些并发的问题。django针对此类问题给出了很多解决方案。在django体系中,将每一次的数据库访问称为一次transaction。于此同时,django对数据库的操作还提供了<model_name>.select_for_update().<function>的api。这个select_for_update能够调用数据库的api,对某些数据进行锁定,让并发的其他线程无法立刻访问。

总体上来说,做到多线程安全操作的关键在于2个点,第一,锁定django的transaction防止django内部的多线程互相干涉。第二,锁定数据库的访问,防止多个服务器对数据库的操作互相干涉。

具体操作方法如下:

为Model增加类函数。之所以是类函数,是因为成员函数的本身能够访问时,就已经从数据库提取过数据了。

from django.db import models, transaction

#... in model class...
    @classmethod
    def getPendingTask(cls):
        with transaction.atomic():                                                                      
            try:
                pendings = cls.objects.select_for_update().filter(status = TaskStatus.PENDING)          
                if len(pendings) < 1:                                                                   
                    return False
                first = pendings[0]
                first.convert_start_date = timezone.now()                                               
                first.status = TaskStatus.CONVERTING                                                    
                first.save()                                                                            
                return {
                    'name': first.name,
                    'filename': first.filename                                                          
                }
            except Exception as e:                                                                      
                return False