你可能在你的日志中看到如下所示的日志信息:
"""
LOG: 00000: process 65045 still waiting for ShareLock on transaction 46815253 after 1000.072 ms
"""
含义:进程65045在1000.072毫秒之后仍在等待事务46815253上的ShareLock。
这条信息说明数据库表上存在行锁,进程56673正在等待事务46390004上的锁释放,以获得ShareLock。日志消息的详细信息会告诉我们哪个进程持有这个锁,以及这个锁的完整等待队列,列表中的第一个进程将在下一个被授予锁。
日志文件中可能含有如下信息,即上面提到的日志消息的详细信息:
DETAIL: Process holding the lock: 65050. Wait queue: 65045,65131.
它指示:进程65050正持有这个锁,锁的完整等待队列为 65045,65131。列表中的第一个进程也即65045将在下一个被授予锁。
当我们在日志中看到很多这样的消息,我们就有必要去检查下库中是否长时间存在大量的exclusive锁,同时需要确认为什么这样的exclusive锁会一直存在。这一点跟上一篇的解法相同。
或者我们可以启用 log_statement 或 log_min_duration_statement,来记录花费时间超过所设参数值的所有查询,记录服务器上存在的所有慢查询信息,再进一步定位到具体语句。
查看服务器上的锁信息:
SELECT locker.pid,pc.relname,locker.mode,locker_act.application_name,least(query_start,xact_start) start_time,locker_act.state,CASEWHEN granted='f' THEN'wait_lock'WHEN granted='t' THEN'get_lock'END lock_satus,current_timestamp - least(query_start,xact_start) AS runtime,locker_act.queryFROM pg_locks locker,pg_stat_activity locker_act, pg_class pcWHERE locker.pid=locker_act.pidAND NOT locker.pid=pg_backend_pid()AND application_name<>'pg_statsinfod'AND locker.relation = pc.oidAND pc.reltype<>0 --and pc.relname='t'ORDER BY runtime desc;
问:
1、所有的锁等待信息都会被记录吗?
不会,只有在配置了log_lock_waits=on,并且在超过了deadlock_time,进程仍在等待锁时,才会记录这样的日志信息。log_lock_waits含义可参考我上一篇文章。
2、通常什么情况会出现这种现象呢?
对表中特定行的锁争用一般会出现这种现象,特别是当存在需要长时间才提交的复杂事务时。
当日志中频繁出现这种日志,就需要考虑可能的诱因。
比如:
是不是应用中逻辑设计不合理,存在没有及时提交的事务;
是不是数据库负载过高,导致update的执行效率降低;
被更新表上索引太多,导致update的执行效率低;
应用设计不合理,同一时间段重复更新同一条(批)记录;
参考:
https://pganalyze.com/docs/log-insights/locks/L71
https://postgres.fun/20111104143745.html




