Sixteen Locks Ought to Be Enough for Anybody
3 days ago
- 对表的每次查询都会锁定该表上的每个索引,无论查询是否使用它们,因为规划器会检查所有关系。
- 当表的索引超过16个时,快速路径锁定数组会溢出,导致LWLock:LockManager争用和CPU飙升。
- 在具有21个索引(主键+20个)的表上进行单行主键查找需要22个关系锁,填满所有16个快速路径槽位。
- 预备语句可以通过缓存仅锁定实际使用的关系的通用计划来大幅减少锁的数量。
- 预备语句有注意事项:参数倾斜可能导致次优计划,而RDS Proxy等连接池程序可能无法很好地支持它们。
- PostgreSQL 18将快速路径数组大小增加为可通过max_locks_per_transaction动态配置,消除了16槽位限制。
- 最终的解决方法是删除未使用的索引,以减少每次查询的关系锁数量并完全避免争用。