CREATE INDEX CONCURRENTLY idx_orders_no ON orders (order_no); SELECT indexrelid::regclass FROM pg_index WHERE NOT indisvalid;
在千万行的表上直接建索引,跑到一半业务写入全部排队,监控里 QPS 掉到个位数。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,普通建索引会拿 ShareLock 挡住表上的写入,大表上跑十几分钟,写入队列越堆越长,超时后开始大量报错,这种操作只能挑低峰做。
这次卡住的地方就在「PG 建索引锁表」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
处理上按这个顺序:线上建索引一律带上 concurrently 关键字,不能图省事;建之前确认没有长事务,否则并发建索引也会卡住;建完查 pg_index 里的 indisvalid 字段,确认索引真的可用。
改完只确认一件事:建索引期间写入不受影响,索引 indisvalid 为 true 且查询已用上。
