GitLab 升级迁移排查与修复手册
GitLab升级迁移排查与修复手册
本手册总结了在升级GitLab过程中,因历史脏数据约束冲突、数据库Advisory咨询锁阻塞,或后台批处理迁移(Batched Background Migrations,简称BBM)挂起导致db:migrate失败、容器启动循环或Web页面无法访问时的完整命令排查流程与核心注意事项。
目录
一、核心排查与修复命令流程
阶段一:清理数据库死锁与卡顿连接
阶段二:修复历史脏数据(以namespaces.state约束为例)
阶段三:处理后台批处理迁移(BBM)挂起与收尾
阶段四:恢复常规迁移与服务重构
阶段五:健康检查与系统验证
二、关键运维注意事项
1.数据库操作层面
2.后台批处理迁移(BBM)层面
3.容器与服务运维层面
一、核心排查与修复命令流程
阶段一:清理数据库死锁与卡顿连接
当迁移抛出ActiveRecord::ConcurrentMigrationError或提示锁等待超时时,需要清理后台残留的Advisory锁。
#终止所有非当前会话的advisory锁
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"SELECT pg_terminate_backend(pid) FROM pg_locks WHERE locktype = 'advisory' AND pid <> pg_backend_pid();"
阶段二:修复历史脏数据(以namespaces.state约束为例)
新版本添加NOT NULL约束时,老数据如果存在NULL会导致PG::CheckViolation。
# 1.检查是否存在NULL数据(注意:state字段为smallint整数类型,0代表active)
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"SELECT count(*) FROM namespaces WHERE state IS NULL;"
# 2.批量回填默认值(0表示正常激活状态)
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"UPDATE namespaces SET state = 0 WHERE state IS NULL;"
阶段三:处理后台批处理迁移(BBM)挂起与收尾
某些常规迁移(如表分区收尾Finalise...)会强制检查对应的后台批处理任务是否已完成。如果后台任务处于异常状态(如状态5:execution_error),常规迁移会直接中断。
1.查询当前后台任务状态分布
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"SELECT status, count(*) FROM batched_background_migrations GROUP BY status;"
BBM常见状态码语义:
0: paused(已暂停)
1: active(执行中)
3: finished(已完成)
4/5: failed / execution_error(失败/出错挂起)
6: finalized(已终结/完全收尾)
2.定位阻断迁移的具体任务
以定位Commit分区任务为例:
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"SELECT id, job_class_name, table_name, column_name, status FROM batched_background_migrations WHERE job_class_name ILIKE '%Commit%';"
3.解除阻塞(二选一)
方案A(官方Rake任务在线强制收尾):
#格式:gitlab:background_migrations:finalize[任务类名,表名,主键列名, '参数JSON']
docker exec -it gitlab gitlab-rake "gitlab:background_migrations:finalize[BackfillMergeRequestDiffCommitsToPartitioned,merge_request_diff_commits,merge_request_diff_id,'[\"merge_request_diff_commits_b5377a7a34\"]']"
方案B(数据库直接放行,适用于急需恢复系统):
#将挂起的子任务更新为成功(3 = succeeded)
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"UPDATE batched_background_migration_jobs SET status = 3 WHERE batched_background_migration_id = 334;"
#将主后台任务标记为已终结(6 = finalized)
docker exec -it gitlab gitlab-psql -d gitlabhq_production -c \
"UPDATE batched_background_migrations SET status = 6 WHERE id = 334;"
阶段四:恢复常规迁移与服务重构
解除前置阻碍后,按顺序跑完常规迁移并拉起全套组件。
# 1.恢复执行未完成的数据库迁移
docker exec -it gitlab gitlab-rake db:migrate
# 2.检查是否还有处于down状态的迁移(无输出即代表全部成功通过)
docker exec -it gitlab gitlab-rake db:migrate:status | grep " down "
# 3.重新配置并拉起全部服务(Puma、Sidekiq、Nginx等)
docker exec -it gitlab gitlab-ctl reconfigure
# 4.查看各组件运行状态
docker exec -it gitlab gitlab-ctl status
阶段五:健康检查与系统验证
# 1.执行官方全方位健康检查(检查项目归属、存储、Gitaly、Shell、上传文件等)
docker exec -it gitlab gitlab-rake gitlab:check
# 2.验证后台批处理迁移中是否存在异常任务(输出为空[]即为完全健康)
docker exec -it gitlab gitlab-rails runner \
"puts Gitlab::Database::BackgroundMigration::BatchedMigration.where.not(status: [1, 3, 6]).pluck(:id, :job_class_name, :status)"
# 3.查看容器健康状态
docker ps | grep gitlab
二、关键运维注意事项
1.数据库操作层面
严禁随意删除或截断表(DROP / TRUNCATE / DELETE): 历史脏数据(如NULL)只能通过UPDATE回填默认值,绝对不可直接DELETE,否则会触发级联删除,导致关联的项目、分支、权限历史被破坏。
确认字段数据类型:状态枚举多为整型(如namespaces.state是smallint,用0表示active)。切勿使用字符串赋值,避免触发类型转换报错回滚。
避免强杀PostgreSQL进程: 清理死锁时只杀Advisory咨询锁会话,切勿执行宿主机kill -9,防止触发PostgreSQL崩溃恢复机制导致停机时间大幅拉长。
2.后台批处理迁移(BBM)层面
升级前必须确认BBM全部跑完: 这是绝大多数升级故障的根源。在跨版本升级前,必须确保status = 1(运行中)为0,且没有失败/挂起的任务。
不要频繁重复触发批量重试:当任务处于status = 1时代表后台Worker正在消费队列,重复触发可能导致多个Worker争抢同一批次,加剧数据库锁竞争。
注意状态码在版本间的语义:当前新版本中,主迁移表的status = 3代表finished(已完成正常状态),切勿当成失败强行调用retry_failed_jobs!。
3.容器与服务运维层面
迁移期间严禁强行中断(Ctrl+C或 重启容器): 当执行gitlab-rake db:migrate处理大表分区时,终端可能长时间无日志刷新,后台仍在扫描数据。强杀会导致任务状态落入不一致。
必须等数据库迁移完成后再执行gitlab-ctl reconfigure: 若数据库仍有大量down迁移,执行reconfigure大概率失败或产生新的配置死锁。
升级前务必备份配置与密钥:关键文件(特别是gitlab-secrets.json和gitlab.rb)必须做本地备份:
tar -czvf gitlab_config_backup_$(date +%F).tar.gz /path/to/gitlab/config