Django+Postgres在WSL环境数据看似保存成功实际丢失且报连接已关闭错误
问题根因定位
首先明确两个核心逻辑对应你遇到的所有异常现象:
- 「save后同代码块get能读到数据、但psql和页面刷新读不到」:Django默认对每个请求启用隐式事务,你在同一个数据库连接内执行的save操作产生的是未提交的脏数据,仅当前连接可见。一旦连接意外中断,事务会自动回滚,所有写入操作直接失效。
- 「psycopg2.InterfaceError: connection already closed未被业务代码捕获」:该异常是Django数据库连接池层在向Postgres申请游标时抛出的,未传递到上层业务的try块内,所以你的异常捕获逻辑无法触发。
- 结合日志、SQL转储文件丢失的现象,WSL更新是触发所有问题的根因:WSL2更新后常出现两个典型问题:一是内核自动回收空闲内存时会误杀后台Postgres进程,导致数据库连接被强制断开;二是WSL文件系统出现软损坏,非用户目录下的日志、数据文件被意外清理。
可落地的修复步骤
- 首先修复WSL层异常
- 停止所有WSL实例,执行
wsl --shutdown,重启后先检查WSL文件系统完整性:在WSL内执行sudo fsck /dev/sdb(根据你WSL根分区的设备名调整) - 禁止WSL内存回收杀后台进程:在Windows用户目录下新建
.wslconfig文件,写入以下配置:
保存后再次执行[wsl2] vmBehavior=disableOOMKiller=truewsl --shutdown生效
- 停止所有WSL实例,执行
- 修复Django数据库连接和事务逻辑
- 显式控制事务提交,在save操作后手动提交事务,避免隐式事务回滚导致数据丢失:
from django.db import transaction from django.db import DatabaseError try: nodeToUpdate.save() # Hit the database. transaction.commit() # 手动提交事务,确保数据落盘 node = Node.objects.get(pk=itemID, ofmap=mapId) # Retrieve again to confirm it was saved # This shows the correct data: print("STORE TO MAP:" + str(node.ofmap_id) + " NODE:" + str(node.id) + " label:" + str(node.label)) except DatabaseError as err: transaction.rollback() # 异常时主动回滚事务 print(str(err)) raise Exception(err) except ValidationError as err: raise Exception(err) - 配置Django数据库参数,启用连接健康检查:在settings.py的DATABASES配置项中增加
"CONN_HEALTH_CHECKS": True,该参数会在每次从连接池取出连接时检查是否存活,断开的连接会自动重建
- 显式控制事务提交,在save操作后手动提交事务,避免隐式事务回滚导致数据丢失:
- 修复PostgreSQL层配置
- 确认PostgreSQL的数据目录存放在WSL的原生ext4分区下(不要放在
/mnt/开头的Windows挂载分区),否则会出现权限、IO异常导致数据写入失败 - 调整PostgreSQL的
client_connection_check_interval参数为60s,主动清理断开的客户端连接,避免僵死连接被Django连接池复用
- 确认PostgreSQL的数据目录存放在WSL的原生ext4分区下(不要放在
验证方案
执行上述操作后,先手动写入一条测试数据,同时开启Postgres的事务日志:在postgresql.conf中设置log_statement = 'all',确认写入操作对应的COMMIT语句是否正常落盘,再通过psql查询是否能读到数据,确认修复生效。
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

