Django项目部署到Heroku时db.sqlite3数据丢失问题咨询
首先明确结论
你想靠保留部署时的db.sqlite3实现数据持久化的思路在Heroku上行不通,这是平台底层特性决定的,不是你配置有误。
根本原因
Heroku的dyno运行环境用的是临时文件系统:每次你push代码触发重新部署、或者平台自动重启dyno(正常运行状态下每天至少会发生一次),整个运行环境的文件都会被重置为你push的代码包的初始状态。
你遇到的部署后只剩superuser、其他数据归零的问题,本质就是部署后线上运行时写入db.sqlite3的新数据全存在临时存储里,环境重置后直接被清除,只留下你代码包里自带的、存了superuser的初始db.sqlite3文件。
不建议硬扛用sqlite的原因
- 就算你每次都把本地最新的db.sqlite3跟着代码一起push上去,只要部署完有新数据写入,下次部署/重启还是会丢,根本解决不了持久化问题
- SQLite是单文件嵌入式数据库,不支持Heroku的多dyno分布式运行场景,并发访问时很容易出现数据库锁死、数据写入错误的问题
生产环境正确持久化方案(一劳永逸)
直接用Heroku官方提供的托管关系型数据库,所有数据存在独立于dyno的存储服务上,不管怎么部署重启都不会丢:
- 给你的Heroku应用绑定Heroku Postgres插件,免费额度足够小型站点使用,绑定后平台会自动注入
DATABASE_URL环境变量 - 安装依赖:把
dj-database-url、psycopg2-binary加到项目的requirements.txt中 - 修改settings.py的数据库配置,让线上环境自动读取Postgres连接信息,本地开发依然可以用sqlite:
import os import dj_database_url from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent # 默认本地开发用sqlite DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } # 检测到线上环境的DATABASE_URL时自动切换到Postgres if os.getenv("DATABASE_URL"): DATABASES['default'] = dj_database_url.config( conn_max_age=600, ssl_require=True )
- 提交代码push到Heroku后,执行线上迁移和初始化账号:
heroku run python manage.py migrateheroku run python manage.py createsuperuser
配置完成后后续所有部署都不需要额外处理数据库,数据会永久保存在Postgres服务中。
临时同步本地db.sqlite3的操作步骤(仅适合一次性导数据,不可长期用)
如果你只是临时需要把本地存量数据传到线上,接受后续新数据会在下次部署时丢失的后果,可以按以下步骤操作:
- 本地先执行
python manage.py makemigrations和python manage.py migrate,确保本地db.sqlite3的表结构和最新模型完全一致 - 检查项目根目录的.gitignore文件,删除其中
db.sqlite3相关的忽略规则,确保git可以追踪到这个文件 - 执行
git add db.sqlite3把最新的本地数据库加入暂存区,和其他代码变更一起commit后push到Heroku远程分支 - push完成后执行
heroku run python manage.py migrate,确认线上表结构没有冲突
警告:这个方案仅能做一次性数据导入,绝对不能用于生产环境长期运行,只要触发dyno重启或者重新部署,部署后产生的所有新数据都会被清空。
内容的提问来源于stack exchange,提问作者ReliableAirRepair
相关产品推荐
相关产品推荐

