Django项目Docker多数据库配置后副本库查询报错(column不存在)的解决方法咨询
看起来你已经完成了Docker容器和Django数据库的基础配置,但查询副本库时遇到column COLUMN_NAME does not exist的错误,大概率是副本库没有和主库保持数据结构同步,或者压根没配置主从复制机制。我来帮你一步步排查修复:
1. 先确认副本库的表结构是否和主库一致
首先得搞清楚副本库到底有没有对应的表和列:
- 用pgAdmin连接到端口5433的副本库,找到报错的表,查看它的字段列表,和主库(5432端口)的同一张表对比,看是不是缺少报错的列。
- 或者用命令行直接检查:
# 检查主库表结构 docker exec -it sl_database psql -U <你的POSTGRES_USER> -d <你的POSTGRES_DB> -c "\d <报错的表名>" # 检查副本库表结构 docker exec -it sl_database_replica psql -U <你的POSTGRES_USER> -d <副本库的POSTGRES_DB> -c "\d <报错的表名>"
如果副本库的表结构和主库不一样,那问题就出在同步上。
2. 确保迁移命令执行到了副本库
Django默认只会把迁移应用到default数据库,你需要手动指定副本库执行迁移:
# 普通Django迁移 python manage.py migrate --database=replica # 如果你用了django-tenants,还要同步租户的schema迁移 python manage.py migrate_schemas --database=replica
执行完之后再去检查副本库的表结构,看是否已经同步。
3. 核心问题:你还没配置PostgreSQL主从复制!
看你的Docker Compose配置,db和db-replica只是两个独立的PostGIS容器,没有设置任何主从复制机制——这意味着主库的迁移、数据变更不会自动同步到副本库,两个库完全是独立的。要实现真正的主从读写分离,你得配置PostgreSQL的流复制:
步骤1:配置主库(db)
- 在主库的初始化脚本里(可以添加一个
init.sql挂载到容器的/docker-entrypoint-initdb.d/目录),创建复制用户:-- 创建复制用户 CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'your_replica_password'; - 修改主库的
postgresql.conf(可以通过挂载自定义配置文件或者在Dockerfile里修改):wal_level = replica max_wal_senders = 5 wal_keep_size = 64MB listen_addresses = '*' - 修改主库的
pg_hba.conf,允许副本库连接:host replicator replicator db_network/24 md5
步骤2:配置副本库(db-replica)
副本库需要先从主库拉取基础备份,然后启动复制:
- 停止副本库容器,清空它的数据卷:
docker stop sl_database_replica docker volume rm db_vesatogo_starling_v1_replica - 修改Docker Compose里的
db-replica服务,添加启动命令实现自动同步:db-replica: image: mdillon/postgis container_name: sl_database_replica ports: - "5433:5432" volumes: - db_vesatogo_starling_v1_replica:/var/lib/postgresql/data env_file: - ./config/dev1.env command: > bash -c " until pg_isready -h db -p 5432 -U replicator; do sleep 1 done pg_basebackup -h db -U replicator -D /var/lib/postgresql/data -P -X stream -C -S replica1 echo 'primary_conninfo = ''host=db port=5432 user=replicator password=your_replica_password''' >> /var/lib/postgresql/data/postgresql.conf echo 'standby_mode = on' > /var/lib/postgresql/data/recovery.signal exec postgres " networks: - db_network depends_on: - db
这样副本库启动时会先等待主库就绪,然后拉取主库的完整数据,再以 standby 模式启动,自动同步主库的后续变更。
4. 修正Django副本库配置的小问题
看你的DATABASES配置里,副本库的NAME用了os.environ.get("POSTGRES_DB", "starling_replica")——如果是主从复制的话,副本库的库名应该和主库完全一致,因为复制的是整个库。所以你需要确保dev1.env里的POSTGRES_DB和主库的dev.env里的POSTGRES_DB相同,而不是starling_replica。
另外,非生产环境下副本库的HOST设为localhost是对的,但要确认你的环境变量POSTGRES_PORT在非生产时确实是5433,避免连接到主库。
完成以上步骤后,再执行副本库的查询,应该就能正常获取数据了。
内容的提问来源于stack exchange,提问作者Abdullah Ansari

