如何通过同时/admin和管理命令会话解决“操作错误:数据库已锁定”?

问题描述 投票:0回答:1

我正在将 django 与 sqlite 用于 Web 应用程序,该应用程序执行长时间运行的管理命令来更新数据库 (

./manage.sh download_company_data
)。但是,当它运行时,我无法在 Django 管理界面中创建新用户。我已经将数据库的超时选项增加到 20000:

DATABASES = {                                                                              
    'default': {                                                                           
        'ENGINE': 'django.db.backends.sqlite3',                                            
        'NAME': BASE_DIR / 'db.sqlite3',                                                   
        'OPTIONS': { 'timeout': 20000 },                                                   
    }                                                                                      
}   

忽略配置的超时,操作错误是立即发生的。当尝试将用户添加到数据库时,单击“保存”按钮后会发生这种情况。

我正在同时运行数据库更新进程和管理站点的

runserver
进程。个别更新简单快速,不要访问
User
表,我也尝试断开与数据库的连接并睡眠,为服务器进程腾出空间:

    for line in c:                                                                
        line = preprocess(line, prefix)                                           
        search = { unique: line[unique] }
        for i in range(10):                                                       
            try:                                                                  
                Model.objects.update_or_create(**search, defaults=line)           
                break                                                             
            except OperationalError as e:                                         
                info('Operational error. Delayed retry...')                       
                sleep(0.02)                                                       
        connections.close_all()                                                   
        sleep(1)                                                                  

我不明白为什么管理站点反复给出操作错误,提到数据库被锁定,即使大多数时候只有 1 个到 sqlite 文件的连接。

有什么方法可以解决这个问题而不需要将sqlite切换到另一个数据库后端吗?

python django sqlite
1个回答
0
投票

尝试使用 transaction.atomic()

from django.db import transaction

# Inside your management command
@transaction.atomic(isolation=transaction.ISOLATION_READ_UNCOMMITTED)
def your_long_running_task():
    # Your code here
© www.soinside.com 2019 - 2024. All rights reserved.