[Postgres] 等待事件

1. 等待事件介绍

在任意时间点,每一个数据库服务端进程,要么正忙于处理一个请求(busy),要么正在等待一个特定的事件发生(waiting)。我们说它处于忙的状态,意味着这个进程当时是需要使用CPU的。举例来说,一个会话进程在执行一个SQL过程时,可能正在进行一个算术计算,我们说它处于忙的状态,而不是等待状态。与此同时,另一个会话进程可能在提交事务,它在等待操作系统的响应,告诉它刷写日志时使用的fsync系统调用已经完成,这时我们说它处于等待状态。

虽然说等待事件是oracle的概念,但是实际上它在大多数关系型数据库里面都是存在的。不管你看得到,还是看不到,它都在那里。这是一个性能调优工作永远绕不开的话题。

2. 动态跟踪

PostgreSQL允许对数据库服务器进行动态跟踪。这样就允许在代码内特定的点上调用外部工具来跟踪执行过程。目前此功能主要目的是为了提供给数据库开发者使用,它要求使用者对代码非常熟悉。

3. PostgreSQL的等待事件

下面主要介绍3类等待事件:常规锁、轻量级锁和IO操作。这里只介绍相关的概念,对于观测等待事件的方法,可以通过PostgreSQL的动态跟踪机制,使用dtrace进行跟踪观测,也可以通过进行二次开发对相关的等待事件进行统计收集。

4. 等待事件:常规锁

4.1 常规锁介绍

锁的管理包括对不同粒度锁的操作,这些粒度包括表、内存页(目前只在索引中使用对内存页的加锁)、元组、事务、虚拟事务以及当前数据库中的其他对象。可以通过pg_locks视图观察当前数据库系统中的锁占用和等待的情况。

4.2 相关函数

LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError);

4.3 主要的内置跟踪点

probe lock__wait__start(unsigned int locktag_field1, unsigned int locktag_field2, unsigned int locktag_field3, unsigned int locktag_field4, unsigned int locktag_type, LOCKMODE lockmode);

probe lock__wait__done(unsigned int locktag_field1, unsigned int locktag_field2, unsigned int locktag_field3, unsigned int locktag_field4, unsigned int locktag_type, LOCKMODE lockmode);

4.4 常规锁相关的等待事件

(1) 表对象上的锁: 对表对象进行访问、修改、管理维护等操作时的锁操作

(2) 表对象上的扩展锁: 在对一个表进行页面扩展时的锁操作

(3) 表中页面上的锁: 对一个页面对象进行的加锁操作

(4) 元组上的锁: 对一个元组对象进行的加锁操作

(5) 事务上的锁: 一个事务在运行过程中,会保持一个和事务XID相关的锁,直到事务结束

(6) 虚拟事务上的锁: 一个事务在运行过程中,会保持一个和会话ID、本会话事务ID相关的锁,直到事务结束

(7) 一般的数据库对象上的锁: 对一般数据库对象进行的加锁操作

4.5 常规锁的模式和用途

(1) AccessShareLock: SELECT

(2) RowShareLock: SELECT FOR UPDATE/FOR SHARE

(3) RowExclusiveLock: INSERT, UPDATE, DELETE

(4) ShareUpdateExclusiveLock: VACUUM (non-FULL),ANALYZE, CREATE INDEX CONCURRENTLY

(5) ShareLock: CREATE INDEX (WITHOUT CONCURRENTLY)

(6) ShareRowExclusiveLock: like EXCLUSIVE MODE, but allows ROW SHARE

(7) ExclusiveLock: blocks ROW SHARE/SELECT...FOR UPDATE

5. 等待事件:轻量级锁

5.1 轻量级锁介绍

轻量级锁主要提供对共享存储器的数据结构的互斥访问。这些数据结构包括页面缓冲区、日志缓冲区、缓冲区管理结构、会话状态、事务状态以及数据库中的其他内部数据结构。

5.2 相关函数

static inline bool LWLockAcquireCommon(LWLock *l, LWLockMode mode, uint64 *valptr, uint64 val);

5.3 主要的内置跟踪点

probe lwlock__acquire(const char *name, int id, LWLockMode mode);

probe lwlock__release(const char *name, int id);

probe lwlock__wait__start(const char *name, int id, LWLockMode mode);

probe lwlock__wait__done(const char *name, int id, LWLockMode mode);

5.4 轻量级锁相关的等待事件

(1) Bufffer Content Lock

描述: 访问缓冲区中的页面时的相关加锁操作

场景说明: 多个并发事务同时对同一个数据页面进行访问时会发生争用

(2) Buffer Freelist Lock

描述: 访问页面缓冲区空闲链表的相关加锁操作

场景说明: 数据库启动时,大量事务并发访问数据会出现对该锁的争用

(3) Process Array Lock

描述: 访问会话和事务状态列表的相关加锁操作

场景说明: 大量并发的短事务会出现对该锁的争用

(4) WAL Insert Lock

描述: 向XLOG缓冲区插入日志时的加锁操作

场景说明: 大量事务并发修改数据会出现对该锁的争用

(5) WAL Write Lock

描述: 将XLOG缓冲区中的日志写入文件时的加锁操作

场景说明: 大量事务并发修改数据会出现对该锁的争用,可考虑组提交

(6) CLog Control Lock

描述: 在Clog缓冲区中设置和访问事务状态时的加锁操作

场景说明: 大量并发的短事务会出现对该锁的争用

(7) Subtrans Control Lock

描述: 在子事务日志缓冲区中设置和访问事务状态时的加锁操作

场景说明: 大量子事务会出现对该锁的争用,比如SQL过程中循环执行BEGIN … EXCEPTION语句块的情况,应该尽量避免

(8) MultiXact Offset Control Lock、MultiXact Member Control Lock

描述: 在组合事务日志缓冲区中设置和访问事务状态时的加锁操作

场景说明: 多个事务对相同数据并发执行SELECT FOR SHARE时会出现对该锁的争用

(9) Two Phase State Lock

描述: 设置和访问两阶段事务状态时的加锁操作

场景说明: 在分布式环境中,大量并发的两阶段事务会出现该锁的争用

6. 等待事件:IO操作

6.1 IO操作介绍

IO操作是指对文件进行访问或者通过网络进行收发的操作,这些文件包括表、索引、临时表、临时数据文件、XLOG日志文件、事务状态文件、运行日志文件和配置文件等。

6.2 主要的函数

void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync);

void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer);

6.3 几个主要的内置跟踪点

probe buffer__read__start(ForkNumber forkNum, BlockNumber blockNum, Oid spcNode, Oid dbNode, Oid relNode, int backend, bool isExtend);

probe buffer__read__done(ForkNumber forkNum, BlockNumber blockNum, Oid spcNode, Oid dbNode, Oid relNode, int backend, bool isExtend, bool);

probe buffer__flush__start(ForkNumber forkNum, BlockNumber blockNum, Oid spcNode, Oid dbNode, Oid relNode);

probe buffer__flush__done(ForkNumber forkNum, BlockNumber blockNum, Oid spcNode, Oid dbNode, Oid relNode);

6.4 IO操作相关的等待事件

(1) base或global目录下文件

描述: 访问表进行相关操作时的IO事件

(1) pgsql_tmp目录下文件

描述: 执行查询过程中进行排序或散列操作时访问临时文件产生的IO事件

(2) pg_stat_tmp目录下文件

描述: 更新和读取临时的统计信息时的IO事件

(3) pg_tblspc目录下文件

描述: 访问用户自定义表空间下的表进行相关操作时的IO事件

(4) pg_xlog目录下文件

描述: 修改数据时写XLOG日志的IO事件,或者主备机进行日志传输时产生的IO事件

(5) pg_clog目录下文件

描述: 设置和访问事务状态时的IO事件

(6) pg_log目录下文件

描述: 记录运行时日志产生的IO事件

(7) pg_twophase目录下文件

描述: 设置和访问两阶段事务状态时的IO事件

(8) pg_subtrans目录下文件

描述: 设置和访问子事务状态时的IO事件

(9) pg_multixact目录下文件

描述: 设置和访问组合事务状态时的IO事件

(10) 网络套接字

描述: 通过网络发送查询和接收结果时产生的IO事件

你可能感兴趣的:([Postgres] 等待事件)