跳到正文

数据库锁堆积

SysAdmin Crisis 中的数据库锁堆积:Web 服务器看似正常,延迟却不断攀升。了解它的日志特征以及与其他事件的区别。

最后更新:

这是专门惩罚套用固定模式的事件。机架上一切正常,流量条也正常,这一夜却照样分崩离析。

它做什么

在某台数据库机器上,查询开始在锁上等待,而不是完成。没有任何东西崩溃,没有机器进入饱和——但请求在数据库后面排起了队,延迟攀升,可用率随之下降。

Web 层从头到尾都是正常的。这正是该事件的全部特点:症状是整个服务器群变慢,原因却是一台从不变红的机器。

日志特征

数据库机器的 PostgreSQL 日志里有等待和耗时的记录,而在边缘只会出现一条延迟警告:

04:03:11 db-01 postgres[1187]: [2210] LOG:  process 2210 still waiting for ShareLock on transaction 48212 after 1000.051 ms
04:03:11 db-01 postgres[1187]: [2210] DETAIL:  Process holding the lock: 2207. Wait queue: 2210.
04:03:40 web-01 monit[598]: 'shop-api' failed protocol test [HTTP] at [localhost]:80/healthz [TCP/IP] -- HTTP: response time 2100 ms exceeds 1000 ms
04:04:12 db-01 postgres[1187]: [1187] FATAL:  remaining connection slots are reserved for non-replication superuser connections

持有锁的会话只报告自己的持续时间;等待的会话则会说明自己在等谁。要找到根因,需要沿着这条链从末端一路走回起点。db_stat 按 ID、等待时间和名称列出活动查询,并标出卡在锁上的那些。

置之不理的后果

锁队列不断增长,延迟在班次余下的时间里一直居高不下。由于没有机器进入 DOWN,可用率的损失完全来自延迟,随后来自 SLA 债务。这就是为什么整排机架全绿,一夜照样可能输掉。

如何区分

看起来相似区分依据
DDoS 洪水两者都会推高延迟。洪水还会推高 Web 机器的 CPU,并带来内核的 SYN 警告;锁堆积两者都没有。
失控任务两者都可能涉及数据库机器,但失控任务会占满 CPU 并点出一个进程;本事件点出的是一条查询。

何时出现

最早出现的夜3
前提一台 db 机器
权重80
同时出现一个实例

该事件收尾时可能带来真实的可用率损失;收尾的那行日志可以据此区分是干净收尾还是带着损失收尾。