修复gitlab里PostgerSQL错误的小问题

小心翼翼地升级了gitlab,升级过程与备份程序一切正常,
第二天使用时却报了一个奇怪的错

RPC failed HTTP 500 curl 22 The requested URL returned error: 500
expected flush after ref listing

那作为一个资深gitlab管理员,当然先check一下哪儿出问题了

gitlab-rake gitlab:check
gitlab-rake db:migrate:status

结果,好家伙,一切正常。那就只能祭出大杀器——错误日志了
gitlab的日志又不在一个地方,只能一个一个猜。http报错我就先看了nginx,结果nginx一切正常,
然后google了一下,定位到rails,日志在/var/log/gitlab/gitlab-rails/production.log

ActiveRecord::StatementInvalid (PG::DataCorrupted: ERROR:  missing chunk number 0 for toast value 90302 in pg_toast_2619):

好吧,这还和数据库有关系了。
继续在互联网追踪问题,通过一个小时的不懈努力,最终完成修复。
以下记录解决方案

进入Gitlab的PostgreSQL

#切换用户
su gitlab-psql
#切换路径,为了使用psql命令
cd /opt/gitlab/embedded/bin/
#直接psql是无效的,要用-h指定sock -d指定数据库
./psql -h /var/opt/gitlab/postgresql -d gitlabhq_production

查询出问题的表

--这将返回出问题的表名,通常是pg_statistic。
SELECT 2619::regclass;

重建索引

REINDEX TABLE pg_toast.pg_toast_2619;
REINDEX TABLE pg_statistic;
VACUUM ANALYZE pg_statistic;

重建完以后重起gitlab测试,问题依旧,那肯定就是有数据损坏了。

定位损坏的数据

#二分搜索法,假设总行数3000左右
./psql -h /var/opt/gitlab/postgresql -d gitlabhq_production -c "select * from pg_statistic order by starelid,staattnum limit 1500 offset 0" > /dev/null || echo "Corrupted chunk read!"
#如果正常,则转
./psql -h /var/opt/gitlab/postgresql -d gitlabhq_production -c "select * from pg_statistic order by starelid,staattnum limit 750 offset 1500" > /dev/null || echo "Corrupted chunk read!"
#如果不正常,则转
./psql -h /var/opt/gitlab/postgresql -d gitlabhq_production -c "select * from pg_statistic order by starelid,staattnum limit 750 offset 0" > /dev/null || echo "Corrupted chunk read!"

……

#最终定位到问题
./psql -h /var/opt/gitlab/postgresql -d gitlabhq_production -c "select * from pg_statistic order by starelid,staattnum limit 1 offset 2451"

利用主键删除损坏的数据

--打印主键
select starelid,staattnum from pg_statistic order by starelid,staattnum limit 1 offset 2451
--结果如下
 starelid | staattnum
----------+-----------
    42890 |         4
(1 row)

--用主键定位错误数据,报错
select * from pg_statistic where starelid=42890 and staattnum=4
--用主键删除错误数据
delete from pg_statistic where starelid=42890 and staattnum=4
--重建索引
REINDEX TABLE pg_toast.pg_toast_2619;
REINDEX TABLE pg_statistic;
VACUUM ANALYZE pg_statistic;

重启gitlab

gitlab-ctl restart

大功告成!