背景
客户其中一套系统的 PostgreSQL 出现很多的慢查询,发现 PostgreSQL 所在机器的 IO 利用率很高。 因为该机器有好多块硬盘,而且硬盘的型号以及相应的服务都不一样,因此我们只能一块块硬盘来分析。
分析过程
我们使用 iotop 工具来分析磁盘 IO 的占用问题。比如
1
2
3
4
5
6
Total DISK READ : 66.61 K/s | Total DISK WRITE : 2.45 M/s
Actual DISK READ: 66.61 K/s | Actual DISK WRITE: 1630.07 K/s
PID PRIO USER DISK READ DISK WRITE> COMMAND
9472 be/4 pg 0.00 B/s 1191.21 K/s postgres: walwriter
478127 be/4 pg 0.00 B/s 438.87 K/s postgres: walwriter
1929495 be/4 nobody 0.00 B/s 70.53 K/s nginx: worker process
在使用 iotop 分析问题的过程当中我们发现有一个 updatedb 的进程占用了其中一块磁盘的大多数 IO。 通过下面的命令我们很快确认该命令是 mlocate 软件包提供的。
1
rpm -qf `which updatedb`
通过 mlocate 的 man 手册 我们可以知道 mlocate 提供了 locate 命令用来查找机器上的文件。比如我想查找所有文件名为 nginx 的文件,那么可以通过如下命令来查找。
1
locate -b -r "^nginx$"
要提供文件查找服务,那么必现要有一个后台的索引服务,否则实时遍历所有的磁盘文件,那么性能肯定惨不忍睹。 我们看看 mlocate 都提供了哪些服务呢?通过以下命令可以知道软件包提供您了两个服务。
1
2
3
$ rpm -ql mlocate | grep systemd
/usr/lib/systemd/system/mlocate-updatedb.service
/usr/lib/systemd/system/mlocate-updatedb.timer
我们进一步看看这个服务是怎么调度的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat /usr/lib/systemd/system/mlocate-updatedb.service
[Unit]
Description=Update a database for mlocate
[Service]
ExecStart=/usr/libexec/mlocate-run-updatedb
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
PrivateTmp=true
PrivateDevices=true
PrivateNetwork=true
ProtectSystem=true
$ cat /usr/libexec/mlocate-run-updatedb
#!/bin/sh
nodevs=$(< /proc/filesystems awk '$1 == "nodev" && $2 != "rootfs" && $2 != "zfs" { print $2 }')
/usr/bin/updatedb -f "$nodevs"
通过执行上述命令,我们知道 mlocate-updatedb.service 的服务会调用 updatedb 命令。 updatedb 命令是一个不是后台常驻进程,因此执行结束进程就退出了。
我们再看看 mlocate-updatedb.timer 是怎么工作的。
1
2
3
4
5
6
7
8
9
10
11
cat /usr/lib/systemd/system/mlocate-updatedb.timer
[Unit]
Description=Updates mlocate database every day
[Timer]
OnCalendar=daily
AccuracySec=24h
Persistent=true
[Install]
WantedBy=timers.target
通过上述命令,我们知道这个服务是 24 小时执行一次的,由 timers 这个服务来调度。
解决方案
因为我们并不需要使用 locate 命令来定位文件,因此没有必要开启该服务。
1
2
3
4
systemctl stop mlocate-update.service
systemctk stop mlocate-update.timer
systemctl disable mlocate-update.service
systemctl disable mlocate-update.timer
遗留问题
为什么该要默认开启该服务呢?为什么会默认安装 mlocate 这个软件包呢?这个等待进一步挖掘。