You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

golang-migrate如何在DB版本高于本地脚本时跳过迁移执行?

问题根因
  • 变量赋值异常的核心原因是golang-migrate的版本号输出和业务日志分别输出到不同的IO流,命令替换默认仅捕获标准输出(stdout),导致你拿到的是日志内容而非版本号
  • 你之前用wc -l统计迁移脚本数量作为最高版本的逻辑存在缺陷:迁移版本号允许不连续,统计数量不等于实际最高版本号

解决方案1:正确捕获迁移版本,手动判断执行

修正后的脚本如下:

#!/bin/bash
set -euo pipefail

# 正确获取本地迁移脚本的最高版本(兼容版本号不连续场景)
MAX_LOCAL_VERSION=$(ls /app/config/db/migrations/*.up.sql | sed 's/.*\/\([0-9]*\)_.*/\1/' | sort -n | tail -n 1)
echo "MAX_LOCAL_VERSION: $MAX_LOCAL_VERSION"

# 合并标准输出和错误流,过滤出纯数字的当前数据库版本
CURRENT_VERSION=$(/app/migrate -source=file:///app/config/db/migrations/ -database=<connection_string> version 2>&1 | grep -E '^[0-9]+$')
# 处理无迁移记录的场景,默认版本为0
CURRENT_VERSION=${CURRENT_VERSION:-0}
echo "CURRENT_VERSION: $CURRENT_VERSION"

if [ "$MAX_LOCAL_VERSION" -gt "$CURRENT_VERSION" ]; then
  /app/migrate \
  -source=file:///app/config/db/migrations/ \
  -database=<connection_string> \
  up
fi

/app/my-app

逻辑说明:

  1. 用sed提取所有迁移脚本前缀的版本号,排序后取最大值作为本地最高版本,避免跳号场景下的逻辑错误
  2. 执行version命令时添加2>&1合并标准输出和错误流,再通过grep过滤纯数字行,确保拿到的是数值类型的版本号
  3. 新增无迁移记录时的默认值处理,避免空值判断报错

解决方案2:直接捕获迁移错误,忽略版本过高的场景

如果你不想手动处理版本号逻辑,可以直接对migrate up的错误做过滤,只有非"缺失迁移脚本"的错误才中断流程:

#!/bin/bash
set -euo pipefail

# 执行迁移,输出日志同时保存到临时文件
/app/migrate -source=file:///app/config/db/migrations/ -database=<connection_string> up 2>&1 | tee /tmp/migrate_log
EXIT_CODE=${PIPESTATUS[0]}

if [ $EXIT_CODE -ne 0 ]; then
  # 检查错误是否为数据库版本过高导致的迁移脚本缺失
  if grep -q "no migration found for version" /tmp/migrate_log; then
    echo "当前数据库版本高于本地迁移脚本最高版本,跳过迁移步骤"
  else
    echo "迁移执行失败,错误日志如下:"
    cat /tmp/migrate_log
    exit $EXIT_CODE
  fi
fi

/app/my-app

这个方案不需要依赖版本号解析逻辑,兼容性更强。


内容的提问来源于stack exchange,提问作者PersonThatCodes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 14:45:03