测验:读一个活着的数据库
终止了阻塞会话的 pg_blocking_pids 所指向的 pid,但情况没有变化。最可能的原因是什么?
- 被终止的 pid 本身也是一个被阻塞的会话,阻塞链还有另一个终点
- pg_terminate_backend 不会立即释放锁
- 锁住的不是行而是整张表,因此需要重启
- 统计收集器尚未更新,所以看到的是旧值
请求没有响应,但慢查询列表为空。首先应该查看什么?
- 过去一小时的平均响应时间趋势图
- 检查点周期和 WAL 生成量
- 最旧事务的年龄以及 idle in transaction 会话
- 共享缓冲区命中率和磁盘读取等待
一个会话的 wait_event 为 transactionid,另一个为 tuple。这种差异意味着什么?
- 前者是行锁,后者是表锁,锁的范围不同
- 前者直接等待持有锁的事务,后者等待同一行队列中排在前面的会话
- 前者是读锁,后者是写锁,冲突条件不同
- 前者尚未进行死锁检测,后者已经通过死锁检测
在 lock_timeout 为 0(默认值)的服务中,请求集中到同一行时,最先耗尽的是什么?
- 数据库服务器的 CPU
- 共享缓冲区和工作内存
- 用于保存 WAL 的磁盘空间
- 应用程序的连接池
连接已满时,为什么不应首先提高 max_connections?
- 问题不是连接不足,而是连接没有归还;提高设置只会增加可被占住的连接上限
- 该设置需要重启才能生效,因此故障期间无法修改
- 超级用户预留槽位会随之减少,导致管理员无法连接
- 连接数增加后,锁等待会转变为死锁
为什么迁移中必须设置 lock_timeout?
- 因为 DDL 无法回滚,所以这是唯一能在中途停止的方法
- 因为长期持有锁会使 WAL 无法回收并填满磁盘
- 因为等待 ACCESS EXCLUSIVE 会把其后的读取请求也全部排入队列
- 因为等待中的 DDL 不会被检测为死锁,会永远保留