插入约1亿条数据后AWS Aurora Postgres插入突然卡顿
插入数据突然卡顿的原因分析
问题现象
向AWS Aurora Postgres(或非Aurora的Postgres RDS)的一张170列的表插入3亿条数据时,出现以下异常:
- 多线程并行插入时,插入约9200万条(非Aurora RDS为8500万条)后突然卡顿:之前每秒约插1500条,卡顿后单条插入需约30分钟
- 截断表重试、换新Aurora实例,问题仍在相同记录数附近触发
- 重启数据库、升级实例规格、移除主键外的所有索引和约束,都无法解决问题
- 原表插不动时,其他表插入完全正常
关键日志信息
问题发生后,数据库反复输出以下日志:
2023-08-21 13:36:49 UTC:10.142.211.20(36632):mit@postgres:[13997]:LOG: still searching for an unused OID in relation "pg_toast_16720" 2023-08-21 13:36:49 UTC:10.142.211.20(36632):mit@postgres:[13997]:DETAIL: OID candidates have been checked 1000000 times, but no unused OID has been found yet.
原因剖析
核心问题是目标表对应的TOAST表OID耗尽:
- PostgreSQL会为包含大字段(哪怕是varchar这类普通类型,只要内容长度超过阈值)的表自动创建TOAST表,用来存储溢出的大字段数据。TOAST表的每一行都需要唯一的OID(32位整数,理论上限约42亿)。
- 当TOAST表的行数接近OID的可用临界值时,数据库分配OID时需要循环扫描寻找未被使用的ID,这个过程的开销会急剧飙升,直接导致插入操作近乎停滞。
- 你的场景中,170列的表插入9000万条数据后,对应的TOAST表行数已经触及OID分配的临界阈值,所以出现卡顿。不同环境(Aurora/非Aurora RDS)的触发记录数略有差异,是因为两者的OID初始分配池或复用策略有细微区别。
- 其他表插入正常,是因为这些表的TOAST表(或无TOAST表)的OID使用量远未达到临界值;而换实例、删索引等操作不影响TOAST表的OID消耗,所以无法解决问题。
日志内容直接实锤了这个结论——数据库一直在尝试为TOAST表的新行找可用OID,检查了100万次都没找到,自然插不动。
内容的提问来源于stack exchange,提问作者Lahiru Chandima
相关产品推荐
相关产品推荐

