代码改变世界

【PostgreSQL】PostgreSQL中的锁--轻量级的锁

2022-06-15 14:35  abce  阅读(696)  评论(0编辑  收藏  举报

PostgreSQL中轻量级的锁,控制内存的访问。PostgreSQL使用多进程架构,对于内存结构支持一致性读和写。

有两个级别的轻量级的锁:共享的、排他的。有些数据库将轻量级的锁称作“latch”。因为轻量级的锁底层实现的一个细节,应用程序开发人员不应该过多关注这种锁。

从 PostgreSQL 9.6 开始,可以使用pg_stat_activity系统视图查看轻量级的锁的活动,它在CPU利用率高的情况下可能很有用。有一些系统设置可以帮助解决特定轻量级锁的争用。

在 PostgreSQL 9.5之前,轻量级的锁的实现使用自旋锁。这是一个瓶颈。在9.5中通过原子状态变量修复了。

潜在严重竞争的地方

·WALinsertLock:保护WAL缓冲区。可以增加wal缓冲区的大小以获得轻微的改进。顺便说一句, synchronous_commit=off会更加增加锁的压力,但这也不是一件坏事。full_page_writes=off可以减少争用,但一般不推荐。

·WALWriteLock:当WAL记录刷新到磁盘或在WAL段切换期间由PostgreSQL 进程累积。synchronous_commit=off避免了等待磁盘刷新,full_page_writes=off减少要刷新的数据量。

·LockMgrLock:在只读工作负载下出现在top等待中。无论relation大小如何,它都会锁定relation。它不是单个锁,而是至少16个分区。因此,在基准测试期间使用多个表并避免生产中的反模式单表非常重要。

·ProcArrayLock:保护ProcArray结构。在PostgreSQL 9.0之前,每个事务在提交之前都获得了这个锁。

·CLogControlLock:保护CLogControl结构,如果它显示在pg_stat_activity的顶部,你应该检查$PGDATA/pg_clog的位置——它可能在缓冲文件系统上。

·SInvalidReadLock:保护sinval数组。读使用共享锁。SICleanupQueue和其他数组范围的更新需要排他锁。当共享缓冲池处于压力之下时,它显示在pg_stat_activity的顶部。使用更多的shared_buffers有助于减少争用。

·BufMappingLocks:保护buffers区域。设置128个区域(regions)(9.5之前为16 个)的buffer来处理整个缓冲区缓存(buffer cache)。

自旋锁(Spinlocks)

最低级别是自旋锁。它是在特定于CPU的指令中实现的。PostgreSQL尝试在循环中更改原子变量值。如果该值从零变为一:进程获得自旋锁。如果无法立即获得自旋锁,则该进程将成倍增加其等待延迟。没有对自旋锁的监控,也不可能一次释放所有累积的自旋锁。由于单一的状态变化,它也是一个排他锁。为了简化PostgreSQL到外来CPU和操作系统变体的移植,PostgreSQL使用操作系统信号量来实现其自旋锁。当然,与native CPU指令端口相比,它要慢得多。

总结

·使用pg_stat_activity查找哪些查询或轻量级所导致了锁等待。