How to find the corresponding session in MogDB/openGauss from OS thread ID

诊断需求

当MogDB数据库由于某种原因占用了较大的系统负载,比如CPU占用接近100%,那么如何知道到底是数据库里的哪个会话或者哪些会话占用了资源?
在Oracle数据库中,这样的问题诊断,通常都会关联 v$session, v$process, 以及操作系统top命令或者ps命令中查到的操作系统进程ID。
但是MogDB本身是线程模型,在操作系统上只能看到一个进程号,那么该如何定位问题?

因为MogDB使用的是线程模型,与PostgreSQL的进程模型不同,在操作系统级别如果用lsof命令查看网络端口的接入,虽然是会看到有多个用户会话接入,但是在PID列只会显示进程ID,无法对应到线程。

$ lsof -i 4 -a -p `pgrep -u omm3 mogdb`
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
mogdb   12027 omm3    8u  IPv4 20313752      0t0  TCP *:biimenu (LISTEN)
mogdb   12027 omm3    9u  IPv4 20313753      0t0  TCP *:18001 (LISTEN)
mogdb   12027 omm3  325u  IPv4 28320946      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45206 (ESTABLISHED)
mogdb   12027 omm3  330u  IPv4 28316174      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45208 (ESTABLISHED)
mogdb   12027 omm3  336u  IPv4 28302815      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45210 (ESTABLISHED)
mogdb   12027 omm3  340u  IPv4 28323140      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45212 (ESTABLISHED)
mogdb   12027 omm3  360u  IPv4 28323141      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45214 (ESTABLISHED)
mogdb   12027 omm3  375u  IPv4 28305050      0t0  TCP mogdb-kernel-0004:biimenu->softbank060132034173.bbtec.net:45216 (ESTABLISHED)

如何获取线程ID

可以使用htop,打开htop界面以后,按F5进行进程树形显示,第一个PID是进程号,而树形结构下的每一行的PID都是该进程中对应的线程号。

也可以直接使用ps命令。-L参数表示显示线程,-o参数可以指定显示感兴趣的列。

# ps -Lp `pgrep -u omm3 mogdb` -o %cpu,tid,pid,ppid,cmd,comm
%CPU   TID   PID  PPID CMD                         COMMAND
 0.0 17847 17847     1 /opt/mogdb3/app/bin/mogdb - mogdb
 0.0 17848 17847     1 /opt/mogdb3/app/bin/mogdb - jemalloc_bg_thd
 0.0 17854 17847     1 /opt/mogdb3/app/bin/mogdb - mogdb
 0.0 17855 17847     1 /opt/mogdb3/app/bin/mogdb - syslogger
 0.0 17856 17847     1 /opt/mogdb3/app/bin/mogdb - reaper
 0.0 17857 17847     1 /opt/mogdb3/app/bin/mogdb - jemalloc_bg_thd
 0.0 17858 17847     1 /opt/mogdb3/app/bin/mogdb - jemalloc_bg_thd
 0.0 17860 17847     1 /opt/mogdb3/app/bin/mogdb - jemalloc_bg_thd
 0.0 17884 17847     1 /opt/mogdb3/app/bin/mogdb - checkpointer
 0.0 17885 17847     1 /opt/mogdb3/app/bin/mogdb - Spbgwriter
 0.1 17886 17847     1 /opt/mogdb3/app/bin/mogdb - pagewriter
 0.0 17887 17847     1 /opt/mogdb3/app/bin/mogdb - pagewriter
 0.0 17888 17847     1 /opt/mogdb3/app/bin/mogdb - pagewriter
 0.0 17889 17847     1 /opt/mogdb3/app/bin/mogdb - pagewriter
 0.0 17890 17847     1 /opt/mogdb3/app/bin/mogdb - pagewriter
 0.8 17891 17847     1 /opt/mogdb3/app/bin/mogdb - WALwriter
 0.0 17892 17847     1 /opt/mogdb3/app/bin/mogdb - WALwriteraux
 0.0 17893 17847     1 /opt/mogdb3/app/bin/mogdb - AVClauncher
 0.0 17894 17847     1 /opt/mogdb3/app/bin/mogdb - Jobscheduler
 0.0 17895 17847     1 /opt/mogdb3/app/bin/mogdb - asyncundolaunch
 0.0 17896 17847     1 /opt/mogdb3/app/bin/mogdb - globalstats
 0.0 17897 17847     1 /opt/mogdb3/app/bin/mogdb - applylauncher
 0.0 17898 17847     1 /opt/mogdb3/app/bin/mogdb - statscollector
 0.0 17899 17847     1 /opt/mogdb3/app/bin/mogdb - snapshotworker
 0.1 17900 17847     1 /opt/mogdb3/app/bin/mogdb - TrackStmtWorker
 0.0 17901 17847     1 /opt/mogdb3/app/bin/mogdb - 2pccleaner
 0.0 17902 17847     1 /opt/mogdb3/app/bin/mogdb - faultmonitor
 0.0 17904 17847     1 /opt/mogdb3/app/bin/mogdb - undorecycler
 0.0 18372 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18373 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18374 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18375 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18376 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18377 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18378 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18379 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18380 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18381 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18382 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18454 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 19475 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 19480 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 29529 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 30999 17847     1 /opt/mogdb3/app/bin/mogdb - worker

comm列中显示为woker的都是用户会话的数据库端后台进程,通常占用CPU较高的会是用户会话,因此可以用grep命令来过滤只显示用户会话。

#  ps -Lp `pgrep -u omm3 mogdb` -o %cpu,tid,pid,ppid,cmd,comm | grep -w worker
 0.0 18372 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18373 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18374 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18375 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18376 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18377 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18378 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18379 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18380 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18381 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18382 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 18454 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 19475 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 19480 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 29529 17847     1 /opt/mogdb3/app/bin/mogdb - worker
 0.0 30999 17847     1 /opt/mogdb3/app/bin/mogdb - worker

如何将操作系统线程ID跟数据库会话对应

假设在这台服务器上,线程ID=18372的线程占用了大量CPU。

在MogDB里查询pg_os_threads视图,可以获得该线程在数据库中对应的会话ID 。

MogDB=# select * from pg_os_threads where lwpid=18372;
 node_name |       pid       | lwpid | thread_name |         creation_time
-----------+-----------------+-------+-------------+-------------------------------
 dn_6001   | 140545137571584 | 18372 | dn_6001     | 2022-05-30 19:54:42.459129+08
(1 row)

pg_os_threads视图里记录了轻量级线程号和会话ID的关系,其中lwpid是操作系统线程ID,pid列是数据库会话ID。具体信息可以参考MogDB文档-PG_OS_THREADS
如果具备monadmin权限,也可以查询dbe_perf模式下的os_threads视图,信息是一样的。

找到数据库会话ID之后,就可以为所欲为了,比如可以查询dbe_perf.session_stat_activity视图来获取该会话的应用名,发起的客户端IP地址,还有该会话正在执行的SQL。

MogDB=# select application_name,client_addr,query from dbe_perf.session_stat_activity where pid=140545137571584;
 application_name | client_addr  |                          query
------------------+--------------+---------------------------------------------------------
 dn_6001          | 172.16.0.176 | SELECT cfg_value FROM bmsql_config  WHERE cfg_name = $1
(1 row)

也可以查询dbe_perf.thread_wait_status视图来获取会话的当前等待事件。BTW,实际上该视图中有lwtid字段,可以直接对应到线程ID。

MogDB=# select lwtid,wait_status,wait_event from dbe_perf.thread_wait_status where sessionid=140545137571584;
 lwtid | wait_status | wait_event
-------+-------------+------------
 18372 | wait cmd    | wait cmd
(1 row)

How to make Total Commander works with Everything and QuickLook

让Windows操作系统更好用

大多数时间我的工作是在自己的Macbook Pro里完成的,但是因为主要用于游戏的Windows配置了较大的屏幕,有时候也还是会顺手在Windows上进行工作。那么如何让Windows操作系统用起来更顺手?

Total Commander是神器

Total Commander是必装的WIndows资源管理器,从转到macOS之前,我最开始用Windows的时候就一直在用Total Commander,这个老牌的资源管理器从1996年就有了,现在已经更新到了10.0版本,软件价格不到300人民币,一次性购买终身免费升级,物超所值。
网络里有大量关于TC如何更有效率使用的文章,甚至有专门的TC学堂

Everything是神器

Everything是Windows下的搜索工具,所有使用的人都震惊于其闪电般的搜索速度,Everything on Windows的搜索效率远胜Spotlight on macOS。Everything是免费软件。

QuickLook是神器

macOS下的一大方便之处就是在Finder中选中任何文件,然后按空格键,就可以快速浏览,这个使用习惯一旦形成,当Windows没有内置这个功能的时候非常别扭。幸好,有QuickLook软件可以实现该功能。QuickLook是免费且开源的软件。

如何让Total Commander和Everything及QuickLook协同工作

现在我们要实现的是,在TC窗口里,选中文件按空格,打开QuickLook进行快速浏览;按Ctrl+F快捷键(TC默认的Ctrl+F快捷键是打开连接FTP服务器的窗口,用处不大)打开Everything搜索窗口。

  1. 在TC的配置文件目录下创建usercmd.ini文件,并且设置用户命令。
    网上的一些教程谈及在TC主目录下创建usercmd.ini,实际上是不全面的,TC会在自己的配置文件目录下寻找所有配置,而该目录可能在TC的程序安装目录下,也可能在单独的额外目录里。
    在菜单栏的帮助-关于 Total Commander页面里,可以找到设置文件路径,我的TC安装,程序文件和设置文件就是在不同的目录的。

在该路径下创建usercmd.ini,TC默认安装是没有该ini文件的,需要手工创建。
在该文件中增加如下内容。

[em_Everything]  
cmd=C:\Program Files\Everything\Everything.exe  
param="-search "%P "" 

[em_QuickLook]
cmd=D:\Tools\QuickLook\QuickLook.exe 
param="%P%N" 

其中cmd部分是填写Everything和QuickLook的安装路径,该部分需要根据自己安装路径的不同自行做修改;param就是当前的目录和文件名作为变量传入,该部分无需修改。

  1. 设置TC快捷键
    在菜单栏 配置-选项-其他页面,有“重新定义快捷键”部分。

下图是设置Ctrl+F快捷键,点击命令后面的放大镜图标,就可以找到之前在usercmd.ini中设置的em_Everything命令。

下图是设置空格快捷键,命令部分选择之前在usercmd.ini中设置的em_QuickLook命令。

One more thing

如果想要实现macOS里的Alfred快速启动的功能,推荐安装ueli,基本上可以复刻在Alfred中的体验。

Make a perfect terminal experience from zero in 3 steps

Step1 – 确认已经在使用 zsh

kamus@Kamus-MBP-2015 ~ % echo $SHELL
/bin/zsh

如果不是,安装zsh并设置成默认shell

brew install zsh
chsh

Step2 – 安装必须的字体

因为我们期望在终端中可以显示丰富的图标,因此需要Nerd Font,可以从这个页面中挑选自己喜欢的字体

https://www.nerdfonts.com/

我个人很喜欢Sauce Code Pro这款。

Sauce Code Pro Nerd Font Complete Mono.ttf

Configure your terminal to use this font: Sauce Code Pro Nerd Font

以iTerm2为例,设置界面如下:

当然也可以选择本文要介绍的zsh4humans以及神级zsh样式powerlevel10k的原作者Roman Perepelitsa推荐的MesloLGS NF。

https://github.com/romkatv/powerlevel10k/blob/master/font.md

Step3 – 安装zsh4humans

https://github.com/romkatv/zsh4humans

if command -v curl >/dev/null 2>&1; then
sh -c “$(curl -fsSL https://raw.githubusercontent.com/romkatv/zsh4humans/v5/install)”
else
sh -c “$(wget -O- https://raw.githubusercontent.com/romkatv/zsh4humans/v5/install)”
fi

z4h不但内置了powerlevel10k的配置,而且自身还实现了很多ohmyzsh的插件功能,因此使用了z4h之后就不再需要单独进行onmyzsh的安装和配置,非常方便。

z4h在安装的同时也会拉取一份最新的ohmyzsh,如果确实需要修改z4h的默认配置而要加载更多ohmyzsh的插件,可以在~/.zshrc中进行修改。参看“z4h load ”部分的例子,可以自行加载需要的ohmyzsh包含的插件。

比如如果你更喜欢用autojump,而不是用z4h内置的fzf来进行历史目录的快速跳转;比如你喜欢sudo插件,双击ESC键就可以在上一条命令的前面加上sudo,可以通过在~/.zshrc文件中增加如下行来加载这些插件。

z4h load ohmyzsh/ohmyzsh/plugins/autojump
z4h load ohmyzsh/ohmyzsh/plugins/sudo

注意:以上的autojump仅仅是for zsh的插件,本体程序autojump还是要通过brew install autojump来安装的。

GitHub – wting/autojump: A cd command that learns – easily navigate directories from the command line

实际上根据z4h作者的说法,有很大用处的插件或者功能都基本上已经内置到z4h里了,比如对于上述的autojump功能,z4h内置了fzf,默认的快捷键是Alt(Option)+r,按一下有惊喜。同时还内置了Shift+左箭头快速跳转到之前的目录;Shift+上箭头快速跳转到父目录等快捷键。这些快捷键的设置在.zshrc中可以找到。

# Define key bindings.
z4h bindkey undo Ctrl+/ Shift+Tab # undo the last command line change
z4h bindkey redo Option+/ # redo the last undone command line change

z4h bindkey z4h-cd-back Shift+Left # cd into the previous directory
z4h bindkey z4h-cd-forward Shift+Right # cd into the next directory
z4h bindkey z4h-cd-up Shift+Up # cd into the parent directory
z4h bindkey z4h-cd-down Shift+Down # cd into a child directory

后续如果需要,可以执行一条命令就更新z4h

❯ z4h update
z4h: fetching z4h.zsh
z4h: updating zsh4humans
z4h: updating zsh-history-substring-search
z4h: updating zsh-autosuggestions
z4h: updating zsh-completions
z4h: updating zsh-syntax-highlighting
z4h: updating terminfo
z4h: updating fzf
z4h: updating fzf binary
z4h: updating tmux
z4h: updating ohmyzsh/ohmyzsh
z4h: updating powerlevel10k
z4h: updating gitstatus binary
z4h: initializing zsh
z4h: update successful
z4h: restarting zsh