Rust Diesel容器部署执行迁移报relation does not exist错误
问题排查结果及修复方案
这个报错核心是第一个迁移脚本20220525065207/up.sql执行失败,和Rust逻辑、Diesel本身、基础连接配置无关,按概率从高到低的原因和对应修复方式如下:
- 迁移脚本语句顺序错误(概率90%+)
你看到的__diesel_schema_migrations表是Diesel在执行所有迁移前单独创建的,和迁移脚本本身无关。Diesel执行单条迁移时会开启事务,只要脚本里有一句执行失败,整个事务就会回滚,所以你psql看不到to_do表是正常的——建表操作被回滚了。
报错relation "to_do" does not exist说明你的up.sql里,在执行CREATE TABLE to_do建表语句之前,就出现了引用to_do表的操作,常见错误写法包括:- 先写了
GRANT授权语句给to_do表分配权限,后写建表语句 - 先写了
INSERT语句给to_do表灌初始数据,后写建表语句 - 先写了建外键、索引、触发器的语句依赖to_do表,后写建表语句
- 写了
DROP TABLE IF EXISTS to_do之后,漏写建表语句就执行其他操作
修复方式:打开migrations/20220525065207/up.sql检查语句顺序,把所有引用to_do表的语句全部移到CREATE TABLE to_do (...)语句之后即可。
- 先写了
- 镜像未重新构建,嵌入的是旧版错误迁移脚本
你用了embed_migrations!宏,所有迁移SQL是在编译期就直接打包进二进制文件的,如果你改了migrations目录下的文件,没有重新构建Docker镜像就重启容器,运行的还是旧版本的错误SQL。
修复方式:改完迁移文件后执行下面的命令重新构建镜像再启动:docker-compose --env-file .conf build --no-cache app docker-compose --env-file .conf up -d - DATABASE_URL端口配置存在隐患
你现在app连接postgres用的是${POSTGRES_DB_PORT}作为端口,这个变量是给宿主机端口映射用的,容器内部访问postgres服务必须走容器内的默认5432端口,一旦你后续把宿主机映射端口改成别的(比如5433),app就会连错端口。
修复方式:修改docker-compose.yml里app服务的DATABASE_URL,把端口写死为5432:- DATABASE_URL=postgres://${POSTGRES_DB_USER}:${POSTGRES_DB_PASSWORD}@postgres_db:5432/${POSTGRES_DB_NAME} - 数据库等待逻辑不可靠
你现在的entrypoint只检测5432端口是否开放,但PostgreSQL启动时端口先开放,后续还需要几秒时间完成初始化才能正常执行DDL,极端情况下会导致执行异常。
修复方式:- 修改Dockerfile运行阶段的依赖安装,加上postgresql-client:
RUN apt-get update -y && apt-get install -y --no-install-recommends libpq-dev postgresql-client && rm -rf /var/lib/apt/lists/*- 把docker-entrypoint.sh里的端口检测替换成
pg_isready检测:
#!/bin/sh # 等待PostgreSQL完全就绪 until pg_isready -h postgres_db -p 5432 -U ${POSTGRES_DB_USER} -d ${POSTGRES_DB_NAME}; do echo "PostgreSQL is not ready, retrying in 1s..." sleep 1 done # 启动应用 exec ./to_do - 开发环境重置方法
如果要清空之前的错误残留重新初始化,开发环境可以执行下面的命令删除postgres数据卷再重启(注意会清空所有数据库数据,生产环境禁用):docker-compose down -v docker-compose --env-file .conf up -d
内容的提问来源于stack exchange,提问作者mkndyugcfe
相关产品推荐
相关产品推荐

